mid-job push so i can pull from work to continue. working on updating ctx objects to have getters

This commit is contained in:
Terence Parr 2012-02-13 09:15:54 -08:00
parent f8285bcca0
commit 3dbf4cdabc
63 changed files with 625 additions and 413 deletions

View File

@ -156,7 +156,7 @@ case <index> : return <actions.(index)>;}; separator="\n">
RuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble) ::= <<
<ruleCtx>
<altLabelCtxs; separator="\n">
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
<currentRule.ctxType> _localctx = new <currentRule.ctxType>(_ctx, <currentRule.startState><currentRule.args:{a | , <a.name>}>);
@ -186,7 +186,7 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
<<
<ruleCtx>
<altLabelCtxs; separator="\n">
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
<if(currentRule.modifiers)><currentRule.modifiers:{f | <f> }><else>public final <endif><currentRule.ctxType> <currentRule.name>(<currentRule.args; separator=",">) throws RecognitionException {
ParserRuleContext\<Token> _parentctx = _ctx;
@ -214,13 +214,13 @@ LeftRecursiveRuleFunction(currentRule,code,locals,ruleCtx,altLabelCtxs,
}
>>
CodeBlockForOuterMostAlt(c, locals, preamble, ops) ::= <<
<if(c.altLabel)>_localctx = new <c.altLabel>Context(_localctx);<endif>
enterOuterAlt(_localctx, <c.alt.altNum>);
<CodeBlockForAlt(...)>
CodeBlockForOuterMostAlt(currentOuterMostAltCodeBlock, locals, preamble, ops) ::= <<
<if(currentOuterMostAltCodeBlock.altLabel)>_localctx = new <currentOuterMostAltCodeBlock.altLabel>Context(_localctx);<endif>
enterOuterAlt(_localctx, <currentOuterMostAltCodeBlock.alt.altNum>);
<CodeBlockForAlt(currentAltCodeBlock=currentOuterMostAltCodeBlock, ...)>
>>
CodeBlockForAlt(c, locals, preamble, ops) ::= <<
CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= <<
{
<locals; separator="\n">
<preamble; separator="\n">
@ -425,7 +425,7 @@ setState(<w.stateNumber>);
// ACTION STUFF
Action(a, chunks) ::= "<chunks>"
Action(a, foo, chunks) ::= "<chunks>"
ArgAction(a, chunks) ::= "<chunks>"
@ -448,32 +448,33 @@ LexerPushModeCommand(arg) ::= "pushMode(<arg>);"
DefaultParserSuperClass(s) ::= "Parser"
ActionText(t) ::= "<t.text>"
ActionTemplate(t) ::= "<t.st>"
ArgRef(a) ::= "_localctx.<a.name>"
LocalRef(a) ::= "_localctx.<a.name>"
RetValueRef(a) ::= "_localctx.<a.name>"
QRetValueRef(a) ::= "_localctx.<a.dict>.<a.name>"
QRetValueRef(a) ::= "<ctx(a)>.<a.dict>.<a.name>"
/** How to translate $tokenLabel */
TokenRef(t) ::= "_localctx.<t.name>"
LabelRef(t) ::= "_localctx.<t.name>"
ListLabelRef(t) ::= "_localctx.<ListLabelName(t.name)>"
SetAttr(s,rhsChunks) ::= "_localctx.<s.name> = <rhsChunks>;"
TokenRef(t) ::= "<ctx(t)>.<t.name>"
LabelRef(t) ::= "<ctx(t)>.<t.name>"
ListLabelRef(t) ::= "<ctx(t)>.<ListLabelName(t.name)>"
SetAttr(s,rhsChunks) ::= "<ctx(s)>.<s.name> = <rhsChunks>;"
LexerSetAttr(s,rhsChunks) ::= "_<s.name> = <rhsChunks>;" // _type etc...
TokenLabelType() ::= "<file.TokenLabelType; null={Token}>"
InputSymbolType() ::= "<file.InputSymbolType; null={Token}>"
TokenPropertyRef_text(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getText():null)"
TokenPropertyRef_type(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getType():0)"
TokenPropertyRef_line(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getLine():0)"
TokenPropertyRef_pos(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getCharPositionInLine():0)"
TokenPropertyRef_channel(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getChannel():0)"
TokenPropertyRef_index(t) ::= "(_localctx.<t.label>!=null?_localctx.<t.label>.getTokenIndex():0)"
TokenPropertyRef_int(t) ::= "(_localctx.<t.label>!=null?Integer.valueOf(_localctx.<t.label>.getText()):0)"
TokenPropertyRef_text(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getText():null)"
TokenPropertyRef_type(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getType():0)"
TokenPropertyRef_line(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getLine():0)"
TokenPropertyRef_pos(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getCharPositionInLine():0)"
TokenPropertyRef_channel(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getChannel():0)"
TokenPropertyRef_index(t) ::= "(<ctx(t)>.<t.label>!=null?<ctx(t)>.<t.label>.getTokenIndex():0)"
TokenPropertyRef_int(t) ::= "(<ctx(t)>.<t.label>!=null?Integer.valueOf(<ctx(t)>.<t.label>.getText()):0)"
RulePropertyRef_start(r) ::= "(_localctx.<r.label>!=null?(_localctx.<r.label>.start):null)"
RulePropertyRef_stop(r) ::= "(_localctx.<r.label>!=null?(_localctx.<r.label>.stop):null)"
RulePropertyRef_text(r) ::= "(_localctx.<r.label>!=null?_input.toString(_localctx.<r.label>.start,_localctx.<r.label>.stop):null)"
RulePropertyRef_ctx(r) ::= "_localctx.<r.label>"
RulePropertyRef_start(r) ::= "(<ctx(r)>.<r.label>!=null?(<ctx(r)>.<r.label>.start):null)"
RulePropertyRef_stop(r) ::= "(<ctx(r)>.<r.label>!=null?(<ctx(r)>.<r.label>.stop):null)"
RulePropertyRef_text(r) ::= "(<ctx(r)>.<r.label>!=null?_input.toString(<ctx(r)>.<r.label>.start,<ctx(r)>.<r.label>.stop):null)"
RulePropertyRef_ctx(r) ::= "<ctx(r)>.<r.label>"
ThisRulePropertyRef_start(r) ::= "_localctx.start"
ThisRulePropertyRef_stop(r) ::= "_localctx.stop"
@ -486,11 +487,11 @@ SetNonLocalAttr(s, rhsChunks) ::=
AddToLabelList(a) ::= "_localctx.<a.listName>.add(<labelref(a.label)>);"
TokenDecl(t) ::= "Token <t.name>;"
TokenDecl(t) ::= "Token <t.name>"
TokenTypeDecl(t) ::= "int <t.name>;"
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>();"
RuleContextDecl(r) ::= "<r.ctxName> <r.name>;"
RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>();"
TokenListDecl(t) ::= "List\<Token> <t.name> = new ArrayList\<Token>()"
RuleContextDecl(r) ::= "<r.ctxName> <r.name>"
RuleContextListDecl(rdecl) ::= "List\<<rdecl.ctxName>> <rdecl.name> = new ArrayList\<<rdecl.ctxName>>()"
LexerRuleContext() ::= "RuleContext"
@ -499,8 +500,8 @@ LexerRuleContext() ::= "RuleContext"
*/
RuleContextNameSuffix() ::= "Context"
ImplicitTokenLabel(tokenName) ::= "_t<tokenName>"
ImplicitRuleLabel(ruleName) ::= "_r<ruleName>"
ImplicitTokenLabel(tokenName) ::= "<tokenName>"
ImplicitRuleLabel(ruleName) ::= "<ruleName>"
ImplicitSetLabel(id) ::= "_tset<id>"
ListLabelName(label) ::= "<label>_list"
@ -529,8 +530,9 @@ public static class <s.name> extends <superClass><if(interfaces)> implements <in
>>
AltLabelStructDecl(s,attrs,visitorDispatchMethods) ::= <<
public static class <s.label>Context extends <currentRule.name>Context {
public <s.label>Context(<currentRule.name>Context ctx) { copyFrom(ctx); }
public static class <s.name> extends <currentRule.name>Context {
<attrs:{a | public <a>;}; separator="\n">
public <s.name>(<currentRule.name>Context ctx) { copyFrom(ctx); }
<visitorDispatchMethods; separator="\n">
}
>>
@ -545,7 +547,10 @@ public void <if(method.isEnter)>enter<else>exit<endif>Rule(ParseTreeListener\<<I
AttributeDecl(d) ::= "<d.decl>"
/** If we don't know location of label def x, use this template */
labelref(x) ::= "<if(!x.isLocal)>_localctx.<endif><x.name>"
labelref(x) ::= "<if(!x.isLocal)>((<x.ctx.name>)_localctx).<endif><x.name>"
/** For any action chunk, what is correctly-typed context struct ptr? */
ctx(actionChunk) ::= "((<actionChunk.ctx.name>)_localctx)"
// used for left-recursive rules
recRuleDefArg() ::= "int _p"
@ -563,10 +568,10 @@ pushNewRecursionContext(_localctx, RULE_<ruleName>);
_localctx.start = _prevctx.start;
>>
recRuleLabeledAltStartAction(ruleName, ctxName, label) ::= <<
_localctx = new <ctxName>Context(new <ruleName>Context(_parentctx, _startState, _p));
recRuleLabeledAltStartAction(ruleName, currentAltLabel, label) ::= <<
_localctx = new <currentAltLabel>Context(new <ruleName>Context(_parentctx, _startState, _p));
_localctx.addChild(_prevctx);
<if(label)>_localctx.<label> = _prevctx;<endif>
<if(label)>((<currentAltLabel>Context)_localctx).<label> = _prevctx;<endif>
pushNewRecursionContext(_localctx, RULE_<ruleName>);
_localctx.start = _prevctx.start;
>>

View File

@ -31,29 +31,18 @@ package org.antlr.v4;
import org.antlr.runtime.*;
import org.antlr.v4.analysis.AnalysisPipeline;
import org.antlr.v4.automata.ATNFactory;
import org.antlr.v4.automata.LexerATNFactory;
import org.antlr.v4.automata.ParserATNFactory;
import org.antlr.v4.automata.*;
import org.antlr.v4.codegen.CodeGenPipeline;
import org.antlr.v4.parse.ANTLRLexer;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.parse.ToolANTLRParser;
import org.antlr.v4.runtime.misc.LogManager;
import org.antlr.v4.runtime.misc.Nullable;
import org.antlr.v4.parse.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.semantics.SemanticPipeline;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.GrammarASTErrorNode;
import org.antlr.v4.tool.ast.GrammarRootAST;
import org.antlr.v4.tool.ast.*;
import org.stringtemplate.v4.STGroup;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.*;
public class Tool {
public String VERSION = "4.0-"+new Date();
@ -90,11 +79,12 @@ public class Tool {
public String grammarEncoding = null; // use default locale's encoding
public String msgFormat = "antlr";
public boolean saveLexer = false;
public boolean genListener = true;
public boolean launch_ST_inspector = false;
public boolean force_atn = false;
public boolean log = false;
public boolean verbose_dfa = false;
public boolean no_auto_element_labels = false;
public boolean no_listener = false;
public static Option[] optionDefs = {
new Option("outputDirectory", "-o", OptionArgType.STRING, "specify output directory where all output is generated"),
@ -103,10 +93,13 @@ public class Tool {
new Option("printGrammar", "-print", "print out the grammar without actions"),
new Option("debug", "-debug", "generate a parser that emits debugging events"),
new Option("profile", "-profile", "generate a parser that computes profiling information"),
new Option("generate_ATN_dot", "-atn", "generate rule augmented transition networks"),
new Option("generate_ATN_dot", "-atn", "generate rule augmented transition network diagrams"),
new Option("grammarEncoding", "-encoding", OptionArgType.STRING, "specify grammar file encoding; e.g., euc-jp"),
new Option("msgFormat", "-message-format", OptionArgType.STRING, "specify output style for messages"),
new Option("genListener", "-walker", "generate parse tree walker and listener"),
new Option("no_listener", "-no-listener", "don't generate parse tree listener"),
new Option("no_auto_element_labels",
"-no-auto-ctx-labels", "don't auto generate context fields for each rule element"),
new Option("saveLexer", "-Xsave-lexer", "save temp lexer file created for combined grammars"),
new Option("launch_ST_inspector", "-XdbgST", "launch StringTemplate visualizer on generated code"),
new Option("force_atn", "-Xforce-atn", "use the ATN simulator for all predictions"),

View File

@ -32,19 +32,19 @@ package org.antlr.v4.analysis;
import org.antlr.v4.tool.ast.AltAST;
public class LeftRecursiveRuleAltInfo {
public int alt;
public int altNum; // original alt index (from 1)
public String leftRecursiveRuleRefLabel;
public String altLabel;
public String altText;
public AltAST altAST;
public int nextPrec;
public LeftRecursiveRuleAltInfo(int alt, String altText) {
this(alt, altText, null, null);
public LeftRecursiveRuleAltInfo(int altNum, String altText) {
this(altNum, altText, null, null);
}
public LeftRecursiveRuleAltInfo(int alt, String altText, String leftRecursiveRuleRefLabel, String altLabel) {
this.alt = alt;
public LeftRecursiveRuleAltInfo(int altNum, String altText, String leftRecursiveRuleRefLabel, String altLabel) {
this.altNum = altNum;
this.altText = altText;
this.leftRecursiveRuleRefLabel = leftRecursiveRuleRefLabel;
this.altLabel = altLabel;

View File

@ -29,21 +29,15 @@
package org.antlr.v4.analysis;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.runtime.tree.Tree;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.v4.Tool;
import org.antlr.v4.codegen.CodeGenerator;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.parse.LeftRecursiveRuleWalker;
import org.antlr.v4.misc.Pair;
import org.antlr.v4.parse.*;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.ast.AltAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.GrammarASTWithOptions;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupFile;
import org.antlr.v4.tool.ast.*;
import org.stringtemplate.v4.*;
import java.util.*;
@ -62,7 +56,8 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
public List<LeftRecursiveRuleAltInfo> otherAlts = new ArrayList<LeftRecursiveRuleAltInfo>();
/** Pointer to ID node of ^(= ID element) */
public List<GrammarAST> leftRecursiveRuleRefLabels = new ArrayList<GrammarAST>();
public List<Pair<GrammarAST,String>> leftRecursiveRuleRefLabels =
new ArrayList<Pair<GrammarAST,String>>();
public GrammarAST retvals;
@ -131,10 +126,13 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
@Override
public void binaryAlt(AltAST altTree, int alt) {
altTree = (AltAST)altTree.dupTree();
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
GrammarAST lrlabel = stripLeftRecursion(altTree);
String label = lrlabel != null ? lrlabel.getText() : null;
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
if ( lrlabel!=null ) {
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST,String>(lrlabel,altLabel));
}
stripAssocOptions(altTree);
stripAltLabel(altTree);
@ -145,7 +143,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
stripAltLabel(altTree);
String altText = text(altTree);
altText = altText.trim();
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
a.nextPrec = nextPrec;
binaryAlts.put(alt, a);
@ -156,10 +153,13 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
@Override
public void ternaryAlt(AltAST altTree, int alt) {
altTree = (AltAST)altTree.dupTree();
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
GrammarAST lrlabel = stripLeftRecursion(altTree);
String label = lrlabel != null ? lrlabel.getText() : null;
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
if ( lrlabel!=null ) {
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST,String>(lrlabel,altLabel));
}
stripAssocOptions(altTree);
stripAltLabel(altTree);
@ -168,7 +168,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
String altText = text(altTree);
altText = altText.trim();
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
a.nextPrec = nextPrec;
ternaryAlts.put(alt, a);
@ -195,13 +194,16 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
@Override
public void suffixAlt(AltAST altTree, int alt) {
altTree = (AltAST)altTree.dupTree();
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
GrammarAST lrlabel = stripLeftRecursion(altTree);
String label = lrlabel != null ? lrlabel.getText() : null;
if ( lrlabel!=null ) {
leftRecursiveRuleRefLabels.add(new Pair<GrammarAST,String>(lrlabel,altLabel));
}
stripAltLabel(altTree);
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
String altText = text(altTree);
altText = altText.trim();
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
suffixAlts.put(alt, a);
// System.out.println("suffixAlt " + alt + ": " + altText + ", rewrite=" + rewriteText);
@ -210,17 +212,10 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
@Override
public void otherAlt(AltAST altTree, int alt) {
altTree = (AltAST)altTree.dupTree();
GrammarAST lrlabel = stripLeftRecursion(altTree);
String label = lrlabel != null ? lrlabel.getText() : null;
stripAltLabel(altTree);
if ( lrlabel!=null ) leftRecursiveRuleRefLabels.add(lrlabel);
String altText = text(altTree);
String altLabel = altTree.altLabel!=null ? altTree.altLabel.getText() : null;
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, label, altLabel);
// if ( altLabel!=null ) {
// a.startAction = codegenTemplates.getInstanceOf("recRuleReplaceContext");
// a.startAction.add("ctxName", altLabel);
// }
LeftRecursiveRuleAltInfo a = new LeftRecursiveRuleAltInfo(alt, altText, null, altLabel);
otherAlts.add(a);
// System.out.println("otherAlt " + alt + ": " + altText);
}
@ -256,8 +251,6 @@ public class LeftRecursiveRuleAnalyzer extends LeftRecursiveRuleWalker {
ruleST.add("primaryAlts", prefixAlts);
ruleST.add("primaryAlts", otherAlts);
ruleST.add("leftRecursiveRuleRefLabels", leftRecursiveRuleRefLabels);
tool.log("left-recursion", ruleST.render());
return ruleST.render();

View File

@ -31,13 +31,12 @@ package org.antlr.v4.analysis;
import org.antlr.runtime.*;
import org.antlr.v4.Tool;
import org.antlr.v4.misc.OrderedHashMap;
import org.antlr.v4.misc.*;
import org.antlr.v4.parse.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
/** Remove left-recursive rule refs, add precedence args to recursive rule refs.
* Rewrite rule so we can create ATN.
@ -142,12 +141,16 @@ public class LeftRecursiveRuleTransformer {
}
// define labels on recursive rule refs we delete; they don't point to nodes of course
for (GrammarAST labelNode : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
// these are so $label in action translation works
for (Pair<GrammarAST,String> pair : leftRecursiveRuleWalker.leftRecursiveRuleRefLabels) {
GrammarAST labelNode = pair.a;
GrammarAST labelOpNode = (GrammarAST)labelNode.getParent();
GrammarAST elementNode = (GrammarAST)labelOpNode.getChild(1);
LabelElementPair lp = new LabelElementPair(g, labelNode, elementNode, labelOpNode.getType());
r.alt[1].labelDefs.map(labelNode.getText(), lp);
}
// copy to rule from walker
r.leftRecursiveRuleRefLabels = leftRecursiveRuleWalker.leftRecursiveRuleRefLabels;
tool.log("grammar", "added: "+t.toStringTree());
return true;
@ -189,6 +192,7 @@ public class LeftRecursiveRuleTransformer {
*/
public void setAltASTPointers(LeftRecursiveRule r, RuleAST t) {
System.out.println("RULE: "+t.toStringTree());
BlockAST ruleBlk = (BlockAST)t.getFirstChildWithType(ANTLRParser.BLOCK);
AltAST mainAlt = (AltAST)ruleBlk.getChild(0);
BlockAST primaryBlk = (BlockAST)mainAlt.getChild(0);
@ -196,12 +200,14 @@ public class LeftRecursiveRuleTransformer {
for (int i = 0; i < r.recPrimaryAlts.size(); i++) {
LeftRecursiveRuleAltInfo altInfo = r.recPrimaryAlts.get(i);
altInfo.altAST = (AltAST)primaryBlk.getChild(i);
// System.out.println(altInfo.altAST.toStringTree());
altInfo.altAST.leftRecursiveAltInfo = altInfo;
System.out.println(altInfo.altAST.toStringTree());
}
for (int i = 0; i < r.recOpAlts.size(); i++) {
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
altInfo.altAST = (AltAST)opsBlk.getChild(i);
// System.out.println(altInfo.altAST.toStringTree());
altInfo.altAST.leftRecursiveAltInfo = altInfo;
System.out.println(altInfo.altAST.toStringTree());
}
}

View File

@ -29,23 +29,16 @@
package org.antlr.v4.codegen;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.Token;
import org.antlr.runtime.*;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.codegen.model.chunk.*;
import org.antlr.v4.parse.ActionSplitter;
import org.antlr.v4.parse.ActionSplitterListener;
import org.antlr.v4.tool.Attribute;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.codegen.model.decl.StructDecl;
import org.antlr.v4.parse.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.ActionAST;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/** */
public class ActionTranslator implements ActionSplitterListener {
@ -78,6 +71,7 @@ public class ActionTranslator implements ActionSplitterListener {
RuleFunction rf;
List<ActionChunk> chunks = new ArrayList<ActionChunk>();
OutputModelFactory factory;
StructDecl nodeContext;
public ActionTranslator(OutputModelFactory factory, ActionAST node) {
this.factory = factory;
@ -116,6 +110,10 @@ public class ActionTranslator implements ActionSplitterListener {
ActionTranslator translator = new ActionTranslator(factory, node);
translator.rf = rf;
factory.getGrammar().tool.log("action-translator", "translate " + action);
String altLabel = node.getAltLabel();
System.out.println("label="+altLabel);
if ( rf!=null ) translator.nodeContext = rf.ruleCtx;
if ( altLabel!=null ) translator.nodeContext = rf.altLabelCtxs.get(altLabel);
ANTLRStringStream in = new ANTLRStringStream(action);
in.setLine(tokenWithinAction.getLine());
in.setCharPositionInLine(tokenWithinAction.getCharPositionInLine());
@ -130,27 +128,27 @@ public class ActionTranslator implements ActionSplitterListener {
Attribute a = node.resolver.resolveToAttribute(x.getText(), node);
if ( a!=null ) {
switch ( a.dict.type ) {
case ARG: chunks.add(new ArgRef(x.getText())); break;
case RET: chunks.add(new RetValueRef(x.getText())); break;
case LOCAL: chunks.add(new LocalRef(x.getText())); break;
case ARG: chunks.add(new ArgRef(nodeContext,x.getText())); break;
case RET: chunks.add(new RetValueRef(rf.ruleCtx, x.getText())); break;
case LOCAL: chunks.add(new LocalRef(nodeContext,x.getText())); break;
case PREDEFINED_RULE: chunks.add(getRulePropertyRef(x)); break;
}
}
if ( node.resolver.resolvesToToken(x.getText(), node) ) {
chunks.add(new TokenRef(getTokenLabel(x.getText()))); // $label
chunks.add(new TokenRef(nodeContext,getTokenLabel(x.getText()))); // $label
return;
}
if ( node.resolver.resolvesToLabel(x.getText(), node) ) {
chunks.add(new LabelRef(getTokenLabel(x.getText()))); // $x for x=ID etc...
chunks.add(new LabelRef(nodeContext,getTokenLabel(x.getText()))); // $x for x=ID etc...
return;
}
if ( node.resolver.resolvesToListLabel(x.getText(), node) ) {
chunks.add(new ListLabelRef(x.getText())); // $ids for ids+=ID etc...
chunks.add(new ListLabelRef(nodeContext,x.getText())); // $ids for ids+=ID etc...
return;
}
Rule r = factory.getGrammar().getRule(x.getText());
if ( r!=null ) {
chunks.add(new LabelRef(getRuleLabel(x.getText()))); // $r for r rule ref
chunks.add(new LabelRef(nodeContext,getRuleLabel(x.getText()))); // $r for r rule ref
}
}
@ -159,22 +157,22 @@ public class ActionTranslator implements ActionSplitterListener {
gen.g.tool.log("action-translator", "setQAttr "+x+"."+y+"="+rhs);
// x has to be current rule; just set y attr
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
chunks.add(new SetAttr(y.getText(), rhsChunks));
chunks.add(new SetAttr(nodeContext,y.getText(), rhsChunks));
}
public void qualifiedAttr(String expr, Token x, Token y) {
gen.g.tool.log("action-translator", "qattr "+x+"."+y);
Attribute a = node.resolver.resolveToAttribute(x.getText(), y.getText(), node);
switch ( a.dict.type ) {
case ARG: chunks.add(new ArgRef(y.getText())); break; // has to be current rule
case ARG: chunks.add(new ArgRef(nodeContext,y.getText())); break; // has to be current rule
case RET:
if ( factory.getCurrentRuleFunction()!=null &&
factory.getCurrentRuleFunction().name.equals(x.getText()) )
{
chunks.add(new RetValueRef(y.getText())); break;
chunks.add(new RetValueRef(rf.ruleCtx, y.getText())); break;
}
else {
chunks.add(new QRetValueRef(getRuleLabel(x.getText()), y.getText())); break;
chunks.add(new QRetValueRef(nodeContext, getRuleLabel(x.getText()), y.getText())); break;
}
case PREDEFINED_RULE:
if ( factory.getCurrentRuleFunction()!=null &&
@ -195,22 +193,22 @@ public class ActionTranslator implements ActionSplitterListener {
public void setAttr(String expr, Token x, Token rhs) {
gen.g.tool.log("action-translator", "setAttr "+x+" "+rhs);
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
SetAttr s = new SetAttr(x.getText(), rhsChunks);
if ( factory.getGrammar().isLexer() ) s = new LexerSetAttr(x.getText(), rhsChunks);
SetAttr s = new SetAttr(nodeContext, x.getText(), rhsChunks);
if ( factory.getGrammar().isLexer() ) s = new LexerSetAttr(nodeContext, x.getText(), rhsChunks);
chunks.add(s);
}
public void nonLocalAttr(String expr, Token x, Token y) {
gen.g.tool.log("action-translator", "nonLocalAttr "+x+"::"+y);
Rule r = factory.getGrammar().getRule(x.getText());
chunks.add(new NonLocalAttrRef(x.getText(), y.getText(), r.index));
chunks.add(new NonLocalAttrRef(nodeContext, x.getText(), y.getText(), r.index));
}
public void setNonLocalAttr(String expr, Token x, Token y, Token rhs) {
gen.g.tool.log("action-translator", "setNonLocalAttr "+x+"::"+y+"="+rhs);
Rule r = factory.getGrammar().getRule(x.getText());
List<ActionChunk> rhsChunks = translateActionChunk(factory,rf,rhs.getText(),node);
SetNonLocalAttr s = new SetNonLocalAttr(x.getText(), y.getText(), r.index, rhsChunks);
SetNonLocalAttr s = new SetNonLocalAttr(nodeContext, x.getText(), y.getText(), r.index, rhsChunks);
chunks.add(s);
}
@ -218,15 +216,15 @@ public class ActionTranslator implements ActionSplitterListener {
}
public void text(String text) {
chunks.add(new ActionText(text));
chunks.add(new ActionText(nodeContext,text));
}
TokenPropertyRef getTokenPropertyRef(Token x, Token y) {
try {
Class c = tokenPropToModelMap.get(y.getText());
Constructor ctor = c.getConstructor(new Class[] {String.class});
Constructor ctor = c.getConstructor(new Class[] {StructDecl.class, String.class});
TokenPropertyRef ref =
(TokenPropertyRef)ctor.newInstance(getTokenLabel(x.getText()));
(TokenPropertyRef)ctor.newInstance(nodeContext, getTokenLabel(x.getText()));
return ref;
}
catch (Exception e) {
@ -239,9 +237,9 @@ public class ActionTranslator implements ActionSplitterListener {
RulePropertyRef getRulePropertyRef(Token prop) {
try {
Class c = thisRulePropToModelMap.get(prop.getText());
Constructor ctor = c.getConstructor(new Class[] {String.class});
Constructor ctor = c.getConstructor(new Class[] {StructDecl.class, String.class});
RulePropertyRef ref =
(RulePropertyRef)ctor.newInstance(getRuleLabel(prop.getText()));
(RulePropertyRef)ctor.newInstance(nodeContext, getRuleLabel(prop.getText()));
return ref;
}
catch (Exception e) {
@ -254,9 +252,9 @@ public class ActionTranslator implements ActionSplitterListener {
Grammar g = factory.getGrammar();
try {
Class c = rulePropToModelMap.get(prop.getText());
Constructor ctor = c.getConstructor(new Class[] {String.class});
Constructor ctor = c.getConstructor(new Class[] {StructDecl.class, String.class});
RulePropertyRef ref =
(RulePropertyRef)ctor.newInstance(getRuleLabel(x.getText()));
(RulePropertyRef)ctor.newInstance(nodeContext, getRuleLabel(x.getText()));
return ref;
}
catch (Exception e) {

View File

@ -46,7 +46,7 @@ public class CodeGenPipeline {
}
else {
gen.writeRecognizer(gen.generateParser());
if ( g.tool.genListener) {
if ( !g.tool.no_listener) {
gen.writeListener(gen.generateListener());
gen.writeBlankListener(gen.generateBlankListener());
}

View File

@ -29,18 +29,12 @@
package org.antlr.v4.codegen;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.codegen.model.RuleFunction;
import org.antlr.v4.codegen.model.SrcOp;
import org.antlr.v4.codegen.model.decl.CodeBlock;
import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.misc.Nullable;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.tool.*;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
/** Create output objects for elements *within* rule functions except
* buildOutputModel() which builds outer/root model object and any
@ -66,6 +60,11 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
this.controller = controller;
}
@Override
public OutputModelController getController() {
return controller;
}
// Convenience methods
@NotNull
@ -87,7 +86,7 @@ public abstract class DefaultOutputModelFactory extends BlankOutputModelFactory
public CodeBlock getCurrentBlock() { return controller.getCurrentBlock(); }
@Override
public CodeBlock getCurrentOuterMostAlternativeBlock() { return controller.getCurrentOuterMostAlternativeBlock(); }
public CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock() { return controller.getCurrentOuterMostAlternativeBlock(); }
@Override
public int getCodeBlockLevel() { return controller.codeBlockLevel; }

View File

@ -33,22 +33,12 @@ import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.CodeBlock;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.parse.GrammarASTAdaptor;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.PredAST;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
import org.antlr.v4.parse.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import org.stringtemplate.v4.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.*;
/** This receives events from SourceGenTriggers.g and asks factory to do work.
* Then runs extensions in order on resulting SrcOps to get final list.
@ -72,8 +62,7 @@ public class OutputModelController {
public Stack<RuleFunction> currentRule = new Stack<RuleFunction>();
public Alternative currentOuterMostAlt;
public CodeBlock currentBlock;
public CodeBlock currentOuterMostAlternativeBlock;
public CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock;
public OutputModelController(OutputModelFactory factory) {
this.delegate = factory;
@ -214,36 +203,39 @@ public class OutputModelController {
if ( altInfo.altLabel==null ) continue;
ST altActionST = codegenTemplates.getInstanceOf("recRuleReplaceContext");
altActionST.add("ctxName", altInfo.altLabel);
Action altAction = new Action(delegate, altActionST.render());
Action altAction =
new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST);
CodeBlockForAlt alt = primaryAltsCode.get(i);
alt.insertOp(0, altAction);
}
// Insert code to set ctx.stop after primary block and before op * loop
ST setStopTokenAST = codegenTemplates.getInstanceOf("recRuleSetStopToken");
Action setStopTokenAction = new Action(delegate, setStopTokenAST.render());
Action setStopTokenAction = new Action(delegate, function.ruleCtx, setStopTokenAST);
outerAlt.insertOp(1, setStopTokenAction);
// Insert code to set _prevctx at start of * loop
ST setPrevCtx = codegenTemplates.getInstanceOf("recRuleSetPrevCtx");
Action setPrevCtxAction = new Action(delegate, setPrevCtx.render());
Action setPrevCtxAction = new Action(delegate, function.ruleCtx, setPrevCtx);
opAltStarBlock.addIterationOp(setPrevCtxAction);
// Insert code in front of each op alt to create specialized ctx if there was a label
// Insert code in front of each op alt to create specialized ctx if there was an alt label
for (int i = 0; i < opAltsCode.size(); i++) {
ST altActionST;
LeftRecursiveRuleAltInfo altInfo = r.recOpAlts.getElement(i);
if ( altInfo.altLabel!=null ) {
altActionST = codegenTemplates.getInstanceOf("recRuleLabeledAltStartAction");
altActionST.add("ctxName", altInfo.altLabel);
altActionST.add("currentAltLabel", altInfo.altLabel);
}
else {
altActionST = codegenTemplates.getInstanceOf("recRuleAltStartAction");
altActionST.add("ctxName", r.name);
}
altActionST.add("ruleName", r.name);
// add label of any lr ref we deleted
altActionST.add("label", altInfo.leftRecursiveRuleRefLabel);
Action altAction = new Action(delegate, altActionST.render());
Action altAction =
new Action(delegate, function.altLabelCtxs.get(altInfo.altLabel), altActionST);
CodeBlockForAlt alt = opAltsCode.get(i);
alt.insertOp(0, altAction);
}
@ -312,7 +304,9 @@ public class OutputModelController {
public CodeBlockForAlt alternative(Alternative alt, boolean outerMost) {
CodeBlockForAlt blk = delegate.alternative(alt, outerMost);
if ( outerMost ) currentOuterMostAlternativeBlock = blk;
if ( outerMost ) {
currentOuterMostAlternativeBlock = (CodeBlockForOuterMostAlt)blk;
}
for (CodeGeneratorExtension ext : extensions) blk = ext.alternative(blk, outerMost);
return blk;
}
@ -431,15 +425,13 @@ public class OutputModelController {
return currentBlock;
}
public void setCurrentOuterMostAlternativeBlock(CodeBlock currentOuterMostAlternativeBlock) {
public void setCurrentOuterMostAlternativeBlock(CodeBlockForOuterMostAlt currentOuterMostAlternativeBlock) {
this.currentOuterMostAlternativeBlock = currentOuterMostAlternativeBlock;
}
public CodeBlock getCurrentOuterMostAlternativeBlock() {
public CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock() {
return currentOuterMostAlternativeBlock;
}
public int getCodeBlockLevel() { return codeBlockLevel; }
public int getTreeLevel() { return treeLevel; }
}

View File

@ -32,11 +32,8 @@ package org.antlr.v4.codegen;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.CodeBlock;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import java.util.List;
@ -47,6 +44,8 @@ public interface OutputModelFactory {
void setController(OutputModelController controller);
OutputModelController getController();
ParserFile parserFile(String fileName);
Parser parser(ParserFile file);
@ -109,7 +108,7 @@ public interface OutputModelFactory {
CodeBlock getCurrentBlock();
CodeBlock getCurrentOuterMostAlternativeBlock();
CodeBlockForOuterMostAlt getCurrentOuterMostAlternativeBlock();
int getCodeBlockLevel();

View File

@ -31,21 +31,12 @@ package org.antlr.v4.codegen;
import org.antlr.v4.analysis.AnalysisPipeline;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
import org.antlr.v4.codegen.model.decl.TokenDecl;
import org.antlr.v4.codegen.model.decl.TokenListDecl;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.DecisionState;
import org.antlr.v4.runtime.atn.PlusBlockStartState;
import org.antlr.v4.runtime.atn.StarLoopEntryState;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.Alternative;
import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.BlockAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.TerminalAST;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import java.util.List;
@ -101,10 +92,10 @@ public class ParserFactory extends DefaultOutputModelFactory {
String label = labelAST.getText();
Decl d = getTokenLabelDecl(label);
((MatchToken)matchOp).labels.add(d);
getCurrentRuleFunction().addContextDecl(d);
getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
TokenListDecl l = getTokenListLabelDecl(label);
getCurrentRuleFunction().addContextDecl(l);
getCurrentRuleFunction().addContextDecl(ID.getAltLabel(), l);
}
}
if ( controller.needsImplicitLabel(ID, matchOp) ) defineImplicitLabel(ID, matchOp);
@ -129,10 +120,10 @@ public class ParserFactory extends DefaultOutputModelFactory {
String label = labelAST.getText();
Decl d = getTokenLabelDecl(label);
((MatchSet)matchOp).labels.add(d);
getCurrentRuleFunction().addContextDecl(d);
getCurrentRuleFunction().addContextDecl(setAST.getAltLabel(), d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
TokenListDecl l = getTokenListLabelDecl(label);
getCurrentRuleFunction().addContextDecl(l);
getCurrentRuleFunction().addContextDecl(setAST.getAltLabel(), l);
}
}
if ( controller.needsImplicitLabel(setAST, matchOp) ) defineImplicitLabel(setAST, matchOp);
@ -148,10 +139,10 @@ public class ParserFactory extends DefaultOutputModelFactory {
String label = labelAST.getText();
Decl d = getTokenLabelDecl(label);
wild.labels.add(d);
getCurrentRuleFunction().addContextDecl(d);
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
TokenListDecl l = getTokenListLabelDecl(label);
getCurrentRuleFunction().addContextDecl(l);
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), l);
}
}
if ( controller.needsImplicitLabel(ast, wild) ) defineImplicitLabel(ast, wild);
@ -173,11 +164,11 @@ public class ParserFactory extends DefaultOutputModelFactory {
String label = labelAST.getText();
Decl d = getTokenLabelDecl(label);
c.label = d;
getCurrentRuleFunction().addContextDecl(d);
getCurrentRuleFunction().addContextDecl(labelAST.getAltLabel(), d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
String listLabel = gen.target.getListLabel(label);
TokenListDecl l = new TokenListDecl(this, listLabel);
getCurrentRuleFunction().addContextDecl(l);
getCurrentRuleFunction().addContextDecl(labelAST.getAltLabel(), l);
}
}
@ -288,7 +279,7 @@ public class ParserFactory extends DefaultOutputModelFactory {
}
op.getLabels().add(d);
// all labels must be in scope struct in case we exec action out of context
getCurrentRuleFunction().addContextDecl(d);
getCurrentRuleFunction().addContextDecl(ast.getAltLabel(), d);
}
public AddToLabelList getListLabelIfPresent(LabeledOp op, GrammarAST label) {

View File

@ -84,8 +84,10 @@ alternative returns [CodeBlockForAlt altCodeBlock, List<SrcOp> ops]
alt[boolean outerMost] returns [CodeBlockForAlt altCodeBlock, List<SrcOp> ops]
: {
// set alt if outer ALT only (the only ones with alt field set to Alternative object)
if ( outerMost ) controller.setCurrentOuterMostAlt(((AltAST)$start).alt);
List<SrcOp> elems = new ArrayList<SrcOp>();
AltAST altAST = (AltAST)retval.start;
if ( outerMost ) controller.setCurrentOuterMostAlt(altAST.alt);
List<SrcOp> elems = new ArrayList<SrcOp>();
// TODO: shouldn't we pass $start to controller.alternative()?
$altCodeBlock = controller.alternative(controller.getCurrentOuterMostAlt(), outerMost);
$altCodeBlock.ops = $ops = elems;
controller.setCurrentBlock($altCodeBlock);

View File

@ -30,16 +30,14 @@
package org.antlr.v4.codegen.model;
import org.antlr.runtime.CommonToken;
import org.antlr.v4.codegen.ActionTranslator;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.chunk.ActionChunk;
import org.antlr.v4.codegen.model.chunk.ActionText;
import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.model.chunk.*;
import org.antlr.v4.codegen.model.decl.StructDecl;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.*;
import org.stringtemplate.v4.ST;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
/** */
public class Action extends RuleElement {
@ -57,7 +55,7 @@ public class Action extends RuleElement {
//System.out.println("actions="+chunks);
}
public Action(OutputModelFactory factory, String action) {
public Action(OutputModelFactory factory, StructDecl ctx, String action) {
super(factory,null);
ActionAST ast = new ActionAST(new CommonToken(ANTLRParser.ACTION, action));
RuleFunction rf = factory.getCurrentRuleFunction();
@ -67,7 +65,14 @@ public class Action extends RuleElement {
}
else {
chunks = new ArrayList<ActionChunk>();
chunks.add(new ActionText(action));
chunks.add(new ActionText(ctx, action));
}
}
public Action(OutputModelFactory factory, StructDecl ctx, ST actionST) {
super(factory, null);
chunks = new ArrayList<ActionChunk>();
chunks.add(new ActionTemplate(ctx, actionST));
}
}

View File

@ -34,5 +34,8 @@ import org.antlr.v4.codegen.model.decl.CodeBlock;
/** Contains Rewrite block (usually as last op) */
public class CodeBlockForAlt extends CodeBlock {
public CodeBlockForAlt(OutputModelFactory factory) { super(factory); }
public CodeBlockForAlt(OutputModelFactory factory) {
super(factory);
}
}

View File

@ -29,19 +29,14 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.ActionTranslator;
import org.antlr.v4.codegen.CodeGenerator;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.model.chunk.ActionChunk;
import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
import org.antlr.v4.codegen.model.decl.RuleContextListDecl;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.runtime.atn.RuleTransition;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.*;
import java.util.List;
@ -72,11 +67,11 @@ public class InvokeRule extends RuleElement implements LabeledOp {
String label = labelAST.getText();
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
labels.add(d);
rf.addContextDecl(d);
rf.addContextDecl(ast.getAltLabel(), d);
if ( labelAST.parent.getType() == ANTLRParser.PLUS_ASSIGN ) {
String listLabel = gen.target.getListLabel(label);
RuleContextListDecl l = new RuleContextListDecl(factory, listLabel, ctxName);
rf.addContextDecl(l);
rf.addContextDecl(ast.getAltLabel(), l);
}
}
if ( ast.getChildCount()>0 ) {
@ -89,15 +84,8 @@ public class InvokeRule extends RuleElement implements LabeledOp {
String label = gen.target.getImplicitRuleLabel(ast.getText());
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
labels.add(d);
rf.addContextDecl(d);
rf.addContextDecl(ast.getAltLabel(), d);
}
// LinearApproximator approx = new LinearApproximator(factory.g, ATN.INVALID_DECISION_NUMBER);
// RuleTransition call = (RuleTransition)ast.atnState.transition(0);
// IntervalSet fset = approx.FIRST(call.followState);
// System.out.println("follow rule ref "+name+"="+fset);
// follow = factory.createFollowBitSet(ast, fset);
// factory.defineBitSet(follow);
}
public List<Decl> getLabels() {

View File

@ -33,7 +33,7 @@ import org.antlr.v4.codegen.model.decl.Decl;
import java.util.List;
/** */
/** All the rule elements we can label like tokens, rules, sets, wildcard. */
public interface LabeledOp {
public List<Decl> getLabels();
}

View File

@ -29,34 +29,35 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.CodeGenerator;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.RuleContextDecl;
import org.antlr.v4.tool.LabelElementPair;
import org.antlr.v4.tool.LabelType;
import org.antlr.v4.tool.LeftRecursiveRule;
import org.antlr.v4.tool.Rule;
import org.stringtemplate.v4.misc.MultiMap;
import java.util.Iterator;
import java.util.Set;
import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.misc.Pair;
import org.antlr.v4.parse.ANTLRParser;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.GrammarAST;
public class LeftRecursiveRuleFunction extends RuleFunction {
public LeftRecursiveRuleFunction(OutputModelFactory factory, LeftRecursiveRule r) {
super(factory, r);
// Since we delete x=lr, we have to manually add decls for all labels on left-recur refs
CodeGenerator gen = factory.getGenerator();
MultiMap<String,LabelElementPair> labelDefs = r.alt[1].labelDefs;
Set<String> labels = labelDefs.keySet();
for (Iterator<String> iterator = labels.iterator(); iterator.hasNext(); ) {
String label = iterator.next();
LabelElementPair l = r.getAnyLabelDef(label);
Rule targetRule = factory.getGrammar().getRule(l.element.getText());
if ( l.type == LabelType.RULE_LABEL ) {
// Since we delete x=lr, we have to manually add decls for all labels
// on left-recur refs to proper structs
for (Pair<GrammarAST,String> pair : r.leftRecursiveRuleRefLabels) {
GrammarAST idAST = pair.a;
String altLabel = pair.b;
String label = idAST.getText();
GrammarAST rrefAST = (GrammarAST)idAST.getParent().getChild(1);
if ( rrefAST.getType() == ANTLRParser.RULE_REF ) {
Rule targetRule = factory.getGrammar().getRule(rrefAST.getText());
String ctxName = gen.target.getRuleFunctionContextStructName(targetRule);
RuleContextDecl d = new RuleContextDecl(factory,label,ctxName);
addContextDecl(d);
StructDecl struct = ruleCtx;
if ( altLabelCtxs!=null ) {
StructDecl s = altLabelCtxs.get(altLabel);
if ( s!=null ) struct = s; // if alt label, use subctx
}
struct.addDecl(d); // stick in overall rule's ctx
}
}
}

View File

@ -1,13 +1,11 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.misc.Triple;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
/** A model object representing a parse tree listener file.
* These are the rules specific events triggered by a parse tree visitor.
@ -26,11 +24,11 @@ public class ListenerFile extends OutputFile {
parserName = g.getRecognizerName();
grammarName = g.name;
for (Rule r : g.rules.values()) {
List<String> labels = r.getAltLabels();
List<Triple<Integer,AltAST,String>> labels = r.getAltLabels();
listenerNames.add(r.name);
if ( labels!=null ) {
for (String label : labels) {
listenerNames.add(label);
for (Triple<Integer,AltAST,String> pair : labels) {
listenerNames.add(pair.c);
}
}
}

View File

@ -29,13 +29,9 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.CodeGenerator;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.chunk.ActionChunk;
import org.antlr.v4.codegen.model.chunk.ActionText;
import org.antlr.v4.codegen.model.chunk.DefaultParserSuperClass;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.codegen.*;
import org.antlr.v4.codegen.model.chunk.*;
import org.antlr.v4.tool.*;
import java.util.*;
@ -86,7 +82,7 @@ public class Parser extends OutputModelObject {
rules = g.rules.values();
atn = new SerializedATN(factory, g.atn);
if (g.getOptionString("superClass") != null) {
superclass = new ActionText(g.getOptionString("superClass"));
superclass = new ActionText(null, g.getOptionString("superClass"));
} else {
superclass = new DefaultParserSuperClass();
}

View File

@ -30,18 +30,18 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.AltLabelStructDecl;
import org.antlr.v4.codegen.model.decl.Decl;
import org.antlr.v4.codegen.model.decl.StructDecl;
import org.antlr.v4.codegen.model.decl.*;
import org.antlr.v4.misc.*;
import org.antlr.v4.misc.Utils;
import org.antlr.v4.runtime.atn.ATNState;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.Attribute;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.tool.*;
import org.antlr.v4.tool.ast.*;
import java.util.*;
import static org.antlr.v4.parse.ANTLRParser.*;
/** */
public class RuleFunction extends OutputModelObject {
public String name;
@ -54,12 +54,13 @@ public class RuleFunction extends OutputModelObject {
public int index;
public Collection<Attribute> args = null;
public Rule rule;
public AltLabelStructDecl[] altToContext;
@ModelElement public List<SrcOp> code;
@ModelElement public OrderedHashSet<Decl> locals; // TODO: move into ctx?
@ModelElement public StructDecl ruleCtx;
@ModelElement public Set<AltLabelStructDecl> altLabelCtxs;
@ModelElement public Map<String, Action> namedActions;
@ModelElement public Map<String,AltLabelStructDecl> altLabelCtxs;
@ModelElement public Map<String,Action> namedActions;
@ModelElement public Action finallyAction;
@ModelElement public List<SrcOp> postamble;
@ -76,12 +77,35 @@ public class RuleFunction extends OutputModelObject {
index = r.index;
ruleCtx = new StructDecl(factory, r);
altToContext = new AltLabelStructDecl[r.getOriginalNumberOfAlts()+1];
List<String> labels = r.getAltLabels();
// Add ctx labels for elements in alts with no -> label
if ( !factory.getGrammar().tool.no_auto_element_labels ) {
List<Alternative> altsNoLabels = r.getUnlabeledAlts();
if ( altsNoLabels!=null ) {
for (Alternative alt : altsNoLabels) {
List<Decl> decls = getLabelsForAltElements(alt.ast);
// we know to put in rule ctx, so do it directly
for (Decl d : decls) ruleCtx.addDecl(d);
}
}
}
// make structs for -> labeled alts, define ctx labels for elements
altLabelCtxs = new HashMap<String,AltLabelStructDecl>();
List<Triple<Integer,AltAST,String>> labels = r.getAltLabels();
if ( labels!=null ) {
altLabelCtxs = new HashSet<AltLabelStructDecl>();
for (String label : labels) {
altLabelCtxs.add(new AltLabelStructDecl(factory, r, label));
for (Triple<Integer,AltAST,String> pair : labels) {
Integer altNum = pair.a;
AltAST altAST = pair.b;
String label = pair.c;
altToContext[altNum] = new AltLabelStructDecl(factory, r, altNum, label);
altLabelCtxs.put(label, altToContext[altNum]);
if ( !factory.getGrammar().tool.no_auto_element_labels ) {
List<Decl> decls = getLabelsForAltElements(altAST);
// we know which ctx to put in, so do it directly
for (Decl d : decls) altToContext[altNum].addDecl(d);
}
}
}
@ -111,6 +135,50 @@ public class RuleFunction extends OutputModelObject {
startState = factory.getGrammar().atn.ruleToStartState[r.index];
}
/** Get list of decls for token/rule refs.
* Single ref X becomes label X
* Multiple refs to X become X1, X2, ...
* Ref X in a loop then is part of List
*
* Does not gen labels for literals like '+', 'begin', ';', ...
*/
public List<Decl> getLabelsForAltElements(AltAST altAST) {
List<Decl> decls = new ArrayList<Decl>();
IntervalSet reftypes = new IntervalSet(RULE_REF,
TOKEN_REF);
List<GrammarAST> refs = altAST.getNodesWithType(reftypes);
System.out.println(refs);
FrequencySet<String> freq = new FrequencySet<String>();
for (GrammarAST t : refs) {
freq.add(t.getText());
}
// track which ref for X we are at so we can gen X1 if necessary
FrequencySet<String> counter = new FrequencySet<String>();
for (GrammarAST t : refs) {
boolean inLoop = t.hasAncestor(CLOSURE) || t.hasAncestor(POSITIVE_CLOSURE);
// System.out.println(altAST.toStringTree()+" "+t+" inLoop? "+inLoop);
Decl d;
String refLabelName = t.getText();
if ( !inLoop && freq.count(refLabelName)>1 ) {
counter.add(refLabelName);
refLabelName = refLabelName+counter.count(refLabelName);
}
if ( t.getType()==RULE_REF ) {
Rule rref = factory.getGrammar().getRule(t.getText());
String ctxName = factory.getGenerator().target
.getRuleFunctionContextStructName(rref);
if ( inLoop ) d = new RuleContextListDecl(factory, refLabelName, ctxName);
else d = new RuleContextDecl(factory, refLabelName, ctxName);
}
else {
if ( inLoop ) d = new TokenListDecl(factory, refLabelName);
else d = new TokenDecl(factory, refLabelName);
}
decls.add(d);
}
return decls;
}
/** Add local var decl */
public void addLocalDecl(Decl d) {
if ( locals ==null ) locals = new OrderedHashSet<Decl>();
@ -118,8 +186,19 @@ public class RuleFunction extends OutputModelObject {
d.isLocal = true;
}
/** Add decl to struct ctx */
public void addContextDecl(Decl d) {
ruleCtx.addDecl(d);
/** Add decl to struct ctx for rule or alt if labeled */
public void addContextDecl(String altLabel, Decl d) {
CodeBlockForOuterMostAlt alt = d.getOuterMostAltCodeBlock();
// if we found code blk and might be alt label, try to add to that label ctx
if ( alt!=null && altLabelCtxs!=null ) {
System.out.println(d.name+" lives in alt "+alt.alt.altNum);
AltLabelStructDecl altCtx = altLabelCtxs.get(altLabel);
if ( altCtx!=null ) { // we have an alt ctx
System.out.println("ctx is "+ altCtx.name);
altCtx.addDecl(d);
return;
}
}
ruleCtx.addDecl(d); // stick in overall rule's ctx
}
}

View File

@ -30,6 +30,7 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.decl.CodeBlock;
import org.antlr.v4.tool.ast.GrammarAST;
/** */
@ -39,17 +40,42 @@ public abstract class SrcOp extends OutputModelObject {
/** All operations know in which block they live:
*
* CodeBlockForAlt, TreeRewrite, STRewrite
* CodeBlock, CodeBlockForAlt
*
* Templates might need to know block nesting level or find
* a specific declaration, etc...
*/
public SrcOp enclosingBlock;
public CodeBlock enclosingBlock;
public RuleFunction enclosingRuleRunction;
public SrcOp(OutputModelFactory factory) { this(factory,null); }
public SrcOp(OutputModelFactory factory, GrammarAST ast) {
super(factory,ast);
if ( ast!=null ) uniqueID = ast.token.getTokenIndex();
enclosingBlock = factory.getCurrentBlock();
enclosingRuleRunction = factory.getCurrentRuleFunction();
}
/** Walk upwards in model tree, looking for outer alt's code block */
public CodeBlockForOuterMostAlt getOuterMostAltCodeBlock() {
if ( this instanceof CodeBlockForOuterMostAlt ) {
return (CodeBlockForOuterMostAlt)this;
}
CodeBlock p = enclosingBlock;
while ( p!=null ) {
if ( p instanceof CodeBlockForOuterMostAlt ) {
return (CodeBlockForOuterMostAlt)p;
}
p = p.enclosingBlock;
}
return null;
}
/** Return label alt or return name of rule */
public String getContextName() {
CodeBlockForOuterMostAlt alt = getOuterMostAltCodeBlock();
if ( alt!=null && alt.altLabel!=null ) return alt.altLabel;
return enclosingRuleRunction.name;
}
}

View File

@ -1,7 +1,9 @@
package org.antlr.v4.codegen.model;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.misc.Triple;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.AltAST;
import java.util.List;
@ -12,7 +14,7 @@ public class VisitorDispatchMethod extends OutputModelObject {
public VisitorDispatchMethod(OutputModelFactory factory, Rule r, boolean isEnter) {
super(factory);
this.isEnter = isEnter;
List<String> label = r.getAltLabels();
if ( label!=null ) listenerName = label.get(0);
List<Triple<Integer,AltAST,String>> label = r.getAltLabels();
if ( label!=null ) listenerName = label.get(0).c;
}
}

View File

@ -30,7 +30,14 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class ActionChunk extends OutputModelObject {
/** Where is the ctx that defines attrs,labels etc... for this action? */
public StructDecl ctx;
public ActionChunk(StructDecl ctx) {
this.ctx = ctx;
}
}

View File

@ -0,0 +1,13 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
import org.stringtemplate.v4.ST;
public class ActionTemplate extends ActionChunk {
public ST st;
public ActionTemplate(StructDecl ctx, ST st) {
super(ctx);
this.st = st;
}
}

View File

@ -29,11 +29,14 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class ActionText extends ActionChunk {
public String text;
public ActionText(String text) {
public ActionText(StructDecl ctx, String text) {
super(ctx);
this.text = text;
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class ArgRef extends LocalRef {
public ArgRef(String name) {
super(name);
public ArgRef(StructDecl ctx, String name) {
super(ctx, name);
}
}

View File

@ -30,4 +30,5 @@
package org.antlr.v4.codegen.model.chunk;
public class DefaultParserSuperClass extends ActionChunk {
public DefaultParserSuperClass() { super(null); }
}

View File

@ -29,10 +29,13 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
public class LabelRef extends ActionChunk {
public String name;
public LabelRef(String name) {
public LabelRef(StructDecl ctx, String name) {
super(ctx);
this.name = name;
}
}

View File

@ -29,10 +29,12 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
import java.util.List;
public class LexerSetAttr extends SetAttr {
public LexerSetAttr(String name, List<ActionChunk> rhsChunks) {
super(name, rhsChunks);
public LexerSetAttr(StructDecl ctx, String name, List<ActionChunk> rhsChunks) {
super(ctx, name, rhsChunks);
}
}

View File

@ -29,6 +29,8 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
public class ListLabelRef extends LabelRef {
public ListLabelRef(String name) { super(name); }
public ListLabelRef(StructDecl ctx, String name) { super(ctx, name); }
}

View File

@ -29,10 +29,13 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
public class LocalRef extends ActionChunk {
public String name;
public LocalRef(String name) {
public LocalRef(StructDecl ctx, String name) {
super(ctx);
this.name = name;
}
}

View File

@ -29,12 +29,15 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
public class NonLocalAttrRef extends ActionChunk {
public String ruleName;
public String name;
public int ruleIndex;
public NonLocalAttrRef(String ruleName, String name, int ruleIndex) {
public NonLocalAttrRef(StructDecl ctx, String ruleName, String name, int ruleIndex) {
super(ctx);
this.name = name;
this.ruleName = ruleName;
this.ruleIndex = ruleIndex;

View File

@ -29,11 +29,13 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class QRetValueRef extends RetValueRef {
public String dict;
public QRetValueRef(String dict, String name) {
super(name);
public QRetValueRef(StructDecl ctx, String dict, String name) {
super(ctx,name);
this.dict = dict;
}
}

View File

@ -29,11 +29,14 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class RetValueRef extends ActionChunk {
public String name;
public RetValueRef(String name) {
public RetValueRef(StructDecl ctx, String name) {
super(ctx);
this.name = name;
}

View File

@ -29,11 +29,14 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class RulePropertyRef extends ActionChunk {
public String label;
public RulePropertyRef(String label) {
public RulePropertyRef(StructDecl ctx, String label) {
super(ctx);
this.label = label;
}
}

View File

@ -29,8 +29,10 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
public class RulePropertyRef_ctx extends RulePropertyRef {
public RulePropertyRef_ctx(String label) {
super(label);
public RulePropertyRef_ctx(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class RulePropertyRef_start extends RulePropertyRef {
public RulePropertyRef_start(String label) {
super(label);
public RulePropertyRef_start(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class RulePropertyRef_stop extends RulePropertyRef {
public RulePropertyRef_stop(String label) {
super(label);
public RulePropertyRef_stop(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class RulePropertyRef_text extends RulePropertyRef {
public RulePropertyRef_text(String label) {
super(label);
public RulePropertyRef_text(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -30,6 +30,7 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.ModelElement;
import org.antlr.v4.codegen.model.decl.StructDecl;
import java.util.List;
@ -38,17 +39,9 @@ public class SetAttr extends ActionChunk {
public String name;
@ModelElement public List<ActionChunk> rhsChunks;
public SetAttr(String name, List<ActionChunk> rhsChunks) {
public SetAttr(StructDecl ctx, String name, List<ActionChunk> rhsChunks) {
super(ctx);
this.name = name;
this.rhsChunks = rhsChunks;
}
// @Override
// public List<String> getChildren() {
// final List<String> sup = super.getChildren();
// return new ArrayList<String>() {{
// if ( sup!=null ) addAll(sup);
// add("rhsChunks");
// }};
// }
}

View File

@ -29,16 +29,19 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
import java.util.List;
public class SetNonLocalAttr extends SetAttr {
public String ruleName;
public int ruleIndex;
public SetNonLocalAttr(String ruleName, String name, int ruleIndex,
public SetNonLocalAttr(StructDecl ctx,
String ruleName, String name, int ruleIndex,
List<ActionChunk> rhsChunks)
{
super(name, rhsChunks);
super(ctx, name, rhsChunks);
this.ruleName = ruleName;
this.ruleIndex = ruleIndex;
}

View File

@ -29,8 +29,10 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
public class ThisRulePropertyRef_ctx extends RulePropertyRef {
public ThisRulePropertyRef_ctx(String label) {
super(label);
public ThisRulePropertyRef_ctx(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class ThisRulePropertyRef_start extends RulePropertyRef {
public ThisRulePropertyRef_start(String label) {
super(label);
public ThisRulePropertyRef_start(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class ThisRulePropertyRef_stop extends RulePropertyRef {
public ThisRulePropertyRef_stop(String label) {
super(label);
public ThisRulePropertyRef_stop(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class ThisRulePropertyRef_text extends RulePropertyRef {
public ThisRulePropertyRef_text(String label) {
super(label);
public ThisRulePropertyRef_text(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,11 +29,14 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef extends ActionChunk {
public String label;
public TokenPropertyRef(String label) {
public TokenPropertyRef(StructDecl ctx, String label) {
super(ctx);
this.label = label;
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef_channel extends TokenPropertyRef {
public TokenPropertyRef_channel(String label) {
super(label);
public TokenPropertyRef_channel(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef_index extends TokenPropertyRef {
public TokenPropertyRef_index(String label) {
super(label);
public TokenPropertyRef_index(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef_int extends TokenPropertyRef {
public TokenPropertyRef_int(String label) {
super(label);
public TokenPropertyRef_int(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef_line extends TokenPropertyRef {
public TokenPropertyRef_line(String label) {
super(label);
public TokenPropertyRef_line(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef_pos extends TokenPropertyRef {
public TokenPropertyRef_pos(String label) {
super(label);
public TokenPropertyRef_pos(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef_text extends TokenPropertyRef {
public TokenPropertyRef_text(String label) {
super(label);
public TokenPropertyRef_text(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,9 +29,11 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenPropertyRef_type extends TokenPropertyRef {
public TokenPropertyRef_type(String label) {
super(label);
public TokenPropertyRef_type(StructDecl ctx, String label) {
super(ctx, label);
}
}

View File

@ -29,11 +29,14 @@
package org.antlr.v4.codegen.model.chunk;
import org.antlr.v4.codegen.model.decl.StructDecl;
/** */
public class TokenRef extends ActionChunk {
public String name;
public TokenRef(String name) {
public TokenRef(StructDecl ctx, String name) {
super(ctx);
this.name = name;
}
}

View File

@ -34,15 +34,21 @@ import org.antlr.v4.tool.Rule;
/** A StructDecl to handle a -> label on alt */
public class AltLabelStructDecl extends StructDecl {
public String label;
public AltLabelStructDecl(OutputModelFactory factory, Rule r, String label) {
public int altNum;
public AltLabelStructDecl(OutputModelFactory factory, Rule r,
int altNum, String label)
{
super(factory, r);
this.label = label;
this.altNum = altNum;
this.name = // override name set in super to the label ctx
label+
factory.getGenerator().templates
.getInstanceOf("RuleContextNameSuffix").render();
}
@Override
public int hashCode() {
return label.hashCode();
return name.hashCode();
}
@Override
@ -50,7 +56,7 @@ public class AltLabelStructDecl extends StructDecl {
if ( obj == this ) return true;
if ( obj.hashCode() != this.hashCode() ) return false;
if ( obj instanceof AltLabelStructDecl ) {
return label.equals(((AltLabelStructDecl)obj).label);
return name.equals(((AltLabelStructDecl)obj).name);
}
return false;
}

View File

@ -37,6 +37,7 @@ public class Decl extends SrcOp {
public String name;
public String decl; // whole thing if copied from action
public boolean isLocal; // if local var (not in RuleContext struct)
public StructDecl ctx; // which context contains us? set by addDecl
public Decl(OutputModelFactory factory, String name, String decl) {
this(factory, name);

View File

@ -30,16 +30,11 @@
package org.antlr.v4.codegen.model.decl;
import org.antlr.v4.codegen.OutputModelFactory;
import org.antlr.v4.codegen.model.ModelElement;
import org.antlr.v4.codegen.model.OutputModelObject;
import org.antlr.v4.codegen.model.VisitorDispatchMethod;
import org.antlr.v4.codegen.model.*;
import org.antlr.v4.runtime.misc.OrderedHashSet;
import org.antlr.v4.tool.Attribute;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
/** This object models the structure holding all of the parameters,
* return values, local variables, and labels associated with a rule.
@ -65,7 +60,7 @@ public class StructDecl extends Decl {
visitorDispatchMethods.add(new VisitorDispatchMethod(factory, r, false));
}
public void addDecl(Decl d) { attrs.add(d); }
public void addDecl(Decl d) { attrs.add(d); d.ctx = this; }
public void addDecl(Attribute a) {
addDecl(new AttributeDecl(factory, a.name, a.decl));

View File

@ -30,16 +30,19 @@
package org.antlr.v4.tool;
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
import org.antlr.v4.misc.OrderedHashMap;
import org.antlr.v4.tool.ast.RuleAST;
import org.antlr.v4.misc.*;
import org.antlr.v4.tool.ast.*;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
public class LeftRecursiveRule extends Rule {
public List<LeftRecursiveRuleAltInfo> recPrimaryAlts;
public OrderedHashMap<Integer, LeftRecursiveRuleAltInfo> recOpAlts;
/** Did we delete any labels on direct left-recur refs? Points at ID of ^(= ID el) */
public List<Pair<GrammarAST,String>> leftRecursiveRuleRefLabels =
new ArrayList<Pair<GrammarAST,String>>();
public LeftRecursiveRule(Grammar g, String name, RuleAST ast) {
super(g, name, ast, 1);
alt = new Alternative[numberOfAlts+1]; // always just one
@ -51,19 +54,31 @@ public class LeftRecursiveRule extends Rule {
return super.hasAltSpecificContexts() || getAltLabels()!=null;
}
/** Get -> labels and also those we deleted for left-recursive rules. */
@Override
public List<String> getAltLabels() {
List<String> labels = new ArrayList<String>();
List<String> normalAltLabels = super.getAltLabels();
public int getOriginalNumberOfAlts() {
int n = 0;
if ( recPrimaryAlts!=null ) n += recPrimaryAlts.size();
if ( recOpAlts!=null ) n += recOpAlts.size();
return n;
}
/** Get -> labels from those alts we deleted for left-recursive rules. */
@Override
public List<Triple<Integer,AltAST,String>> getAltLabels() {
List<Triple<Integer,AltAST,String>> labels = new ArrayList<Triple<Integer,AltAST,String>>();
List<Triple<Integer,AltAST,String>> normalAltLabels = super.getAltLabels();
if ( normalAltLabels!=null ) labels.addAll(normalAltLabels);
for (int i = 0; i < recPrimaryAlts.size(); i++) {
LeftRecursiveRuleAltInfo altInfo = recPrimaryAlts.get(i);
if ( altInfo.altLabel!=null ) labels.add(altInfo.altLabel);
if ( altInfo.altLabel!=null ) {
labels.add(new Triple<Integer,AltAST,String>(altInfo.altNum,altInfo.altAST,altInfo.altLabel));
}
}
for (int i = 0; i < recOpAlts.size(); i++) {
LeftRecursiveRuleAltInfo altInfo = recOpAlts.getElement(i);
if ( altInfo.altLabel!=null ) labels.add(altInfo.altLabel);
if ( altInfo.altLabel!=null ) {
labels.add(new Triple<Integer,AltAST,String>(altInfo.altNum,altInfo.altAST,altInfo.altLabel));
}
}
if ( labels.size()==0 ) return null;
return labels;

View File

@ -29,10 +29,8 @@
package org.antlr.v4.tool;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.PredAST;
import org.antlr.v4.tool.ast.RuleAST;
import org.antlr.v4.misc.Triple;
import org.antlr.v4.tool.ast.*;
import org.stringtemplate.v4.misc.MultiMap;
import java.util.*;
@ -205,18 +203,34 @@ public class Rule implements AttributeResolver {
return getAltLabels()!=null;
}
/** Used for recursive rules (subclass), which have 1 alt, but many original alts */
public int getOriginalNumberOfAlts() {
return numberOfAlts;
}
/** Get -> labels. */
public List<String> getAltLabels() {
List<String> labels = new ArrayList<String>();
public List<Triple<Integer,AltAST,String>> getAltLabels() {
List<Triple<Integer,AltAST,String>> labels = new ArrayList<Triple<Integer,AltAST,String>>();
for (int i=1; i<=numberOfAlts; i++) {
GrammarAST altLabel = alt[i].ast.altLabel;
if ( altLabel==null ) break; // all or none
labels.add(altLabel.getText());
if ( altLabel!=null ) {
labels.add(new Triple<Integer,AltAST,String>(i,alt[i].ast,altLabel.getText()));
}
}
if ( labels.size()==0 ) return null;
return labels;
}
public List<Alternative> getUnlabeledAlts() {
List<Alternative> alts = new ArrayList<Alternative>();
for (int i=1; i<=numberOfAlts; i++) {
GrammarAST altLabel = alt[i].ast.altLabel;
if ( altLabel==null ) alts.add(alt[i]);
}
if ( alts.size()==0 ) return null;
return alts;
}
/** $x Attribute: rule arguments, return values, predefined rule prop.
*/
public Attribute resolveToAttribute(String x, ActionAST node) {

View File

@ -31,13 +31,17 @@ package org.antlr.v4.tool.ast;
import org.antlr.runtime.Token;
import org.antlr.runtime.tree.Tree;
import org.antlr.v4.analysis.LeftRecursiveRuleAltInfo;
import org.antlr.v4.tool.Alternative;
/** Any ALT (which can be child of ALT_REWRITE node) */
public class AltAST extends GrammarAST {
public Alternative alt;
/** If someone specified an outermost alternative label with #foo.
/** If we transformed this alt from a left-recursive one, need info on it */
public LeftRecursiveRuleAltInfo leftRecursiveAltInfo;
/** If someone specified an outermost alternative label with -> foo.
* Token type will be ID.
*/
public GrammarAST altLabel;

View File

@ -108,6 +108,24 @@ public class GrammarAST extends CommonTree {
return null;
}
/** Walk ancestors of this node until we find ALT with
* alt!=null or leftRecursiveAltInfo!=null. Then grab label if any.
* If not a rule element, just returns null.
*/
public String getAltLabel() {
for (Object o : this.getAncestors()) {
GrammarAST p = (GrammarAST)o;
if ( p.getType()== ANTLRParser.ALT ) {
AltAST a = (AltAST)p;
if ( a.altLabel!=null ) return a.altLabel.getText();
if ( a.leftRecursiveAltInfo!=null ) {
return a.leftRecursiveAltInfo.altLabel;
}
}
}
return null;
}
public boolean deleteChild(org.antlr.runtime.tree.Tree t) {
for (int i=0; i<children.size(); i++) {
Object c = children.get(i);

View File

@ -31,9 +31,7 @@ package org.antlr.v4.test;
import org.antlr.v4.automata.ATNSerializer;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.tool.DOTGenerator;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.LexerGrammar;
import org.antlr.v4.tool.*;
import org.junit.Test;
public class TestATNSerialization extends BaseTest {
@ -406,7 +404,7 @@ public class TestATNSerialization extends BaseTest {
"5:PLUS_BLOCK_START 0\n" +
"6:BLOCK_END 0\n" +
"7:PLUS_LOOP_BACK 0\n" +
"8:LOOP_END 0 6\n" +
"8:LOOP_END 0 7\n" +
"rule 0:1 3,-1\n" +
"mode 0:0\n" +
"0->1 EPSILON 0,0,0\n" +
@ -441,10 +439,12 @@ public class TestATNSerialization extends BaseTest {
"6:RULE_STOP 2\n" +
"7:BASIC 0\n" +
"9:BASIC 0\n" +
"10:BASIC 1\n" +
"10:BASIC 0\n" +
"11:BASIC 1\n" +
"12:BASIC 2\n" +
"14:BASIC 2\n" +
"12:BASIC 1\n" +
"13:BASIC 2\n" +
"15:BASIC 2\n" +
"16:BASIC 2\n" +
"rule 0:1 3,0\n" +
"rule 1:3 4,-1\n" +
"rule 2:5 5,1\n" +
@ -453,15 +453,18 @@ public class TestATNSerialization extends BaseTest {
"0->3 EPSILON 0,0,0\n" +
"0->5 EPSILON 0,0,0\n" +
"1->7 EPSILON 0,0,0\n" +
"3->10 EPSILON 0,0,0\n" +
"5->12 EPSILON 0,0,0\n" +
"3->11 EPSILON 0,0,0\n" +
"5->13 EPSILON 0,0,0\n" +
"7->9 ATOM 97,0,0\n" +
"9->2 EPSILON 0,0,0\n" +
"10->11 ATOM 98,0,0\n" +
"11->4 EPSILON 0,0,0\n" +
"12->14 ATOM 99,0,0\n" +
"14->6 EPSILON 0,0,0\n" +
"0:0 1\n";
"9->10 ACTION 0,0,0\n" +
"10->2 EPSILON 0,0,0\n" +
"11->12 ATOM 98,0,0\n" +
"12->4 EPSILON 0,0,0\n" +
"13->15 ATOM 99,0,0\n" +
"15->16 ACTION 2,1,0\n" +
"16->6 EPSILON 0,0,0\n" +
"0:0 1\n" +
"\n";
ATN atn = createATN(lg);
String result = ATNSerializer.getDecoded(lg, atn);
assertEquals(expecting, result);
@ -560,13 +563,15 @@ public class TestATNSerialization extends BaseTest {
"10:PLUS_BLOCK_START 0\n" +
"11:BLOCK_END 0\n" +
"12:PLUS_LOOP_BACK 0\n" +
"13:LOOP_END 0\n" +
"13:LOOP_END 0 12\n" +
"14:BASIC 1\n" +
"15:BASIC 1\n" +
"16:BASIC 1\n" +
"17:BASIC 1\n" +
"18:BASIC 2\n" +
"20:BASIC 2\n" +
"18:BASIC 1\n" +
"19:BASIC 2\n" +
"21:BASIC 2\n" +
"22:BASIC 2\n" +
"rule 0:2 3,-1\n" +
"rule 1:4 4,0\n" +
"rule 2:6 5,1\n" +
@ -577,7 +582,7 @@ public class TestATNSerialization extends BaseTest {
"1->6 EPSILON 0,0,0\n" +
"2->10 EPSILON 0,0,0\n" +
"4->14 EPSILON 0,0,0\n" +
"6->18 EPSILON 0,0,0\n" +
"6->19 EPSILON 0,0,0\n" +
"8->11 RANGE 97,122,0\n" +
"10->8 EPSILON 0,0,0\n" +
"11->12 EPSILON 0,0,0\n" +
@ -587,12 +592,15 @@ public class TestATNSerialization extends BaseTest {
"14->15 ATOM 42,0,0\n" +
"15->16 ATOM 47,0,0\n" +
"16->17 EPSILON 0,0,0\n" +
"17->5 EPSILON 0,0,0\n" +
"18->20 WILDCARD 0,0,0\n" +
"20->7 EPSILON 0,0,0\n" +
"17->18 ACTION 1,0,0\n" +
"18->5 EPSILON 0,0,0\n" +
"19->21 WILDCARD 0,0,0\n" +
"21->22 ACTION 2,1,0\n" +
"22->7 EPSILON 0,0,0\n" +
"0:0 1\n" +
"1:1 1\n" +
"2:12 1\n";
"2:12 1\n" +
"\n";
ATN atn = createATN(lg);
String result = ATNSerializer.getDecoded(lg, atn);
assertEquals(expecting, result);

View File

@ -68,8 +68,8 @@ public class TestActionTranslation extends BaseTest {
@Test public void testComplicatedArgParsingWithTranslation() throws Exception {
String action = "x, $ID.text+\"3242\", (*$ID).foo(21,33), 3.2+1, '\\n', "+
"\"a,oo\\nick\", {bl, \"fdkj\"eck}";
String expected = "x, (_localctx._tID!=null?_localctx._tID.getText():null)+\"3242\"," +
" (*_localctx._tID).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
String expected = "x, (_localctx.ID!=null?_localctx.ID.getText():null)+\"3242\"," +
" (*_localctx.ID).foo(21,33), 3.2+1, '\\n', \"a,oo\\nick\", {bl, \"fdkj\"eck}";
testActions(attributeTemplate, "inline", action, expected);
}
@ -99,39 +99,39 @@ public class TestActionTranslation extends BaseTest {
@Test public void testReturnValues() throws Exception {
String action = "$lab.e; $b.e;";
String expected = "_localctx.lab.e; _localctx._rb.e;";
String expected = "_localctx.lab.e; _localctx.b.e;";
testActions(attributeTemplate, "inline", action, expected);
}
@Test public void testReturnWithMultipleRuleRefs() throws Exception {
String action = "$c.x; $c.y;";
String expected = "_localctx._rc.x; _localctx._rc.y;";
String expected = "_localctx.c.x; _localctx.c.y;";
testActions(attributeTemplate, "inline", action, expected);
}
@Test public void testTokenRefs() throws Exception {
String action = "$id; $ID; $id.text; $id.getText(); $id.line;";
String expected = "_localctx.id; _localctx._tID; (_localctx.id!=null?_localctx.id.getText():null); _localctx.id.getText(); (_localctx.id!=null?_localctx.id.getLine():0);";
String expected = "_localctx.id; _localctx.ID; (_localctx.id!=null?_localctx.id.getText():null); _localctx.id.getText(); (_localctx.id!=null?_localctx.id.getLine():0);";
testActions(attributeTemplate, "inline", action, expected);
}
@Test public void testRuleRefs() throws Exception {
String action = "$lab.start; $c.tree;";
String expected = "(_localctx.lab!=null?((Token)_localctx.lab.start):null); (_localctx._rc!=null?((CommonAST)_localctx._rc.tree):null);";
String action = "$lab.start; $c.text;";
String expected = "(_localctx.lab!=null?(_localctx.lab.start):null); (_localctx.c!=null?_input.toString(_localctx.c.start,_localctx.c.stop):null);";
testActions(attributeTemplate, "inline", action, expected);
}
@Test public void testRefToTextAttributeForCurrentRule() throws Exception {
String action = "$a.text; $text";
String expected =
"(_localctx._ra!=null?_input.toString(_localctx._ra.start,_localctx._ra.stop):" +
"(_localctx.a!=null?_input.toString(_localctx.a.start,_localctx.a.stop):" +
"null); _input.toString(_localctx.start, _input.LT(-1))";
testActions(attributeTemplate, "init", action, expected);
expected =
"_input.toString(_localctx.start, _input.LT(-1)); _input.toString(_localctx.start, _input.LT(-1))";
testActions(attributeTemplate, "inline", action, expected);
expected =
"(_localctx._ra!=null?_input.toString(_localctx._ra.start,_localctx._ra.stop):null);" +
"(_localctx.a!=null?_input.toString(_localctx.a.start,_localctx.a.stop):null);" +
" _input.toString(_localctx.start, _input.LT(-1))";
testActions(attributeTemplate, "finally", action, expected);
}
@ -235,10 +235,6 @@ public class TestActionTranslation extends BaseTest {
@Test public void testRuleLabelWithoutOutputOption() throws Exception {
}
@Test public void testRuleLabelOnTwoDifferentRulesAST() throws Exception {
}
@Test public void testRuleLabelOnTwoDifferentRulesTemplate() throws Exception {
}
@Test public void testMissingArgs() throws Exception {
}
@Test public void testArgsWhenNoneDefined() throws Exception {