Minor fixes for left recursive rules

This commit is contained in:
Peter Boyer 2016-01-07 09:46:00 -05:00
parent 21999adb6e
commit 096f26d3ae
10 changed files with 77 additions and 64 deletions

View File

@ -27,11 +27,11 @@ func main() {
a := antlr4.NewFileStream("foo.txt")
l := parser.NewTLexer(a)
l := parser.NewExprLexer(a)
s := antlr4.NewCommonTokenStream(l, 0)
p := parser.NewTParser(s)
p := parser.NewExprParser(s)
p.BuildParseTrees = true

View File

@ -163,7 +163,7 @@ Assert(s) ::= <<assert(<s>)>>
Cast(t,v) ::= "((<t>)<v>)"
Append(a,b) ::= "<a> + <b>"
Append(a,b) ::= "<a> + fmt.Sprint(<b>)"
Concat(a,b) ::= "<a><b>"
@ -173,9 +173,9 @@ AssertIsList(v) ::= "List\<?> __ttt__ = <v>;" // just use type system
AssignLocal(s,v) ::= "<s> = <v>;"
InitIntMember(n,v) ::= <%var <n> int = <v>;%>
InitIntMember(n,v) ::= <%var <n> int = <v>; var _ int = <n>; // to disable unused var %>
InitBooleanMember(n,v) ::= <%var <n> bool= <v>;%>
InitBooleanMember(n,v) ::= <%var <n> bool= <v>; var _ bool = <n>; // to disable unused var %>
GetMember(n) ::= <%this.<n>%>
@ -197,7 +197,7 @@ Pass() ::= ""
StringList() ::= "[]string"
BuildParseTrees() ::= "this.BuildParseTrees = true"
BuildParseTrees() ::= "p.BuildParseTrees = true"
BailErrorStrategy() ::= <%SetErrorHandler(NewBailErrorStrategy())%>

View File

@ -379,7 +379,7 @@ public class TestCompositeParsers extends BaseTest {
mkdir(parserpkgdir);
String slave_S =
"parser grammar S;\n" +
"a @after {var x int = 0;} : B;";
"a @after {var x int = 0; var _ int = x; // to disable unused var } : B;";
writeFile(parserpkgdir, "S.g4", slave_S);
StringBuilder grammarBuilder = new StringBuilder(62);
@ -406,10 +406,10 @@ public class TestCompositeParsers extends BaseTest {
"ID : 'a'..'z'+;";
writeFile(parserpkgdir, "S.g4", slave_S);
StringBuilder grammarBuilder = new StringBuilder(113);
StringBuilder grammarBuilder = new StringBuilder(125);
grammarBuilder.append("grammar M;\n");
grammarBuilder.append("import S;\n");
grammarBuilder.append("a : A {fmt.Println(\"M.a: \" + $A)};\n");
grammarBuilder.append("a : A {fmt.Println(\"M.a: \" + fmt.Sprint($A))};\n");
grammarBuilder.append("A : 'abc' {fmt.Println(\"M.A\")};\n");
grammarBuilder.append("WS : (' '|'\\n') -> skip ;");
String grammar = grammarBuilder.toString();

View File

@ -12,11 +12,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void test2AltLoop() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(136);
StringBuilder grammarBuilder = new StringBuilder(133);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");
@ -37,11 +37,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void test2Alts() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(129);
StringBuilder grammarBuilder = new StringBuilder(126);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");
@ -62,11 +62,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void testExtraToken() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(142);
StringBuilder grammarBuilder = new StringBuilder(139);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");
@ -91,11 +91,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void testNoViableAlt() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(144);
StringBuilder grammarBuilder = new StringBuilder(141);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");
@ -120,11 +120,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void testRuleRef() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(138);
StringBuilder grammarBuilder = new StringBuilder(135);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");
@ -147,11 +147,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void testSync() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(145);
StringBuilder grammarBuilder = new StringBuilder(142);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");
@ -175,11 +175,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void testToken2() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(127);
StringBuilder grammarBuilder = new StringBuilder(124);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");
@ -200,11 +200,11 @@ public class TestParseTrees extends BaseTest {
@Test
public void testTokenAndRuleContextString() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(166);
StringBuilder grammarBuilder = new StringBuilder(163);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("s\n");
grammarBuilder.append("@init {\n");
grammarBuilder.append("this.BuildParseTrees = true\n");
grammarBuilder.append("p.BuildParseTrees = true\n");
grammarBuilder.append("}\n");
grammarBuilder.append("@after {\n");
grammarBuilder.append("fmt.Println($r.ctx.ToStringTree(nil,p))\n");

View File

@ -12,9 +12,9 @@ public class TestParserErrors extends BaseTest {
@Test
public void testConjuringUpToken() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(62);
StringBuilder grammarBuilder = new StringBuilder(74);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : 'a' x='b' {fmt.Println(\"conjured=\" + $x)} 'c' ;");
grammarBuilder.append("a : 'a' x='b' {fmt.Println(\"conjured=\" + fmt.Sprint($x))} 'c' ;");
String grammar = grammarBuilder.toString();
String input ="ac";
String found = execParser("T.g4", grammar, "TParser", "TLexer",
@ -29,9 +29,9 @@ public class TestParserErrors extends BaseTest {
@Test
public void testConjuringUpTokenFromSet() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(68);
StringBuilder grammarBuilder = new StringBuilder(80);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("a : 'a' x=('b'|'c') {fmt.Println(\"conjured=\" + $x)} 'd' ;");
grammarBuilder.append("a : 'a' x=('b'|'c') {fmt.Println(\"conjured=\" + fmt.Sprint($x))} 'd' ;");
String grammar = grammarBuilder.toString();
String input ="ad";
String found = execParser("T.g4", grammar, "TParser", "TLexer",
@ -383,10 +383,10 @@ public class TestParserErrors extends BaseTest {
@Test
public void testSingleSetInsertionConsumption() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(81);
StringBuilder grammarBuilder = new StringBuilder(93);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("myset: ('b'|'c') ;\n");
grammarBuilder.append("a: 'a' myset 'd' {fmt.Println(\"\" + $myset.stop)} ; ");
grammarBuilder.append("a: 'a' myset 'd' {fmt.Println(\"\" + fmt.Sprint($myset.stop))} ; ");
String grammar = grammarBuilder.toString();
String input ="ad";
String found = execParser("T.g4", grammar, "TParser", "TLexer",
@ -496,10 +496,10 @@ public class TestParserErrors extends BaseTest {
@Test
public void testSingleTokenDeletionConsumption() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(81);
StringBuilder grammarBuilder = new StringBuilder(93);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("myset: ('b'|'c') ;\n");
grammarBuilder.append("a: 'a' myset 'd' {fmt.Println(\"\" + $myset.stop)} ; ");
grammarBuilder.append("a: 'a' myset 'd' {fmt.Println(\"\" + fmt.Sprint($myset.stop))} ; ");
String grammar = grammarBuilder.toString();
String input ="aabd";
String found = execParser("T.g4", grammar, "TParser", "TLexer",

View File

@ -74,9 +74,9 @@ public class TestSemPredEvalParser extends BaseTest {
@Test
public void testActionHidesPreds() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(227);
StringBuilder grammarBuilder = new StringBuilder(268);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("@members {var i int = 0;}\n");
grammarBuilder.append("@members {var i int = 0; var _ int = i; // to disable unused var }\n");
grammarBuilder.append("s : a+ ;\n");
grammarBuilder.append("a : {this.i = 1;} ID {this.i == 1}? {fmt.Println(\"alt 1\")}\n");
grammarBuilder.append(" | {this.i = 2;} ID {this.i == 2}? {fmt.Println(\"alt 2\")}\n");
@ -352,9 +352,9 @@ public class TestSemPredEvalParser extends BaseTest {
@Test
public void testPredTestedEvenWhenUnAmbig_1() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(202);
StringBuilder grammarBuilder = new StringBuilder(254);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("@members {var enumKeyword bool= true;}\n");
grammarBuilder.append("@members {var enumKeyword bool= true; var _ bool = enumKeyword; // to disable unused var }\n");
grammarBuilder.append("primary\n");
grammarBuilder.append(" : ID {fmt.Println(\"ID \"+$ID.text)}\n");
grammarBuilder.append(" | {!this.enumKeyword}? 'enum' {fmt.Println(\"enum\")}\n");
@ -374,9 +374,9 @@ public class TestSemPredEvalParser extends BaseTest {
@Test
public void testPredTestedEvenWhenUnAmbig_2() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(202);
StringBuilder grammarBuilder = new StringBuilder(254);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("@members {var enumKeyword bool= true;}\n");
grammarBuilder.append("@members {var enumKeyword bool= true; var _ bool = enumKeyword; // to disable unused var }\n");
grammarBuilder.append("primary\n");
grammarBuilder.append(" : ID {fmt.Println(\"ID \"+$ID.text)}\n");
grammarBuilder.append(" | {!this.enumKeyword}? 'enum' {fmt.Println(\"enum\")}\n");
@ -397,9 +397,9 @@ public class TestSemPredEvalParser extends BaseTest {
@Test
public void testPredicateDependentOnArg() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(202);
StringBuilder grammarBuilder = new StringBuilder(243);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("@members {var i int = 0;}\n");
grammarBuilder.append("@members {var i int = 0; var _ int = i; // to disable unused var }\n");
grammarBuilder.append("s : a[2] a[1];\n");
grammarBuilder.append("a[int i]\n");
grammarBuilder.append(" : {$i==1}? ID {fmt.Println(\"alt 1\")}\n");
@ -423,9 +423,9 @@ public class TestSemPredEvalParser extends BaseTest {
@Test
public void testPredicateDependentOnArg2() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(158);
StringBuilder grammarBuilder = new StringBuilder(199);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("@members {var i int = 0;}\n");
grammarBuilder.append("@members {var i int = 0; var _ int = i; // to disable unused var }\n");
grammarBuilder.append("s : a[2] a[1];\n");
grammarBuilder.append("a[int i]\n");
grammarBuilder.append(" : {$i==1}? ID \n");
@ -599,9 +599,9 @@ public class TestSemPredEvalParser extends BaseTest {
@Test
public void testToLeftWithVaryingPredicate() throws Exception {
mkdir(parserpkgdir);
StringBuilder grammarBuilder = new StringBuilder(251);
StringBuilder grammarBuilder = new StringBuilder(292);
grammarBuilder.append("grammar T;\n");
grammarBuilder.append("@members {var i int = 0;}\n");
grammarBuilder.append("@members {var i int = 0; var _ int = i; // to disable unused var }\n");
grammarBuilder.append("s : ({this.i += 1;\n");
grammarBuilder.append("fmt.Println(\"i=\" + this.i)} a)+ ;\n");
grammarBuilder.append("a : {this.i % 2 == 0}? ID {fmt.Println(\"alt 1\")}\n");

View File

@ -458,8 +458,7 @@ func (this *ATNDeserializer) stateIsEndStateFor(state ATNState, idx int) ATNStat
// @param atn The ATN.
//
func (this *ATNDeserializer) markPrecedenceDecisions(atn *ATN) {
for i := 0; i < len(atn.states); i++ {
var state = atn.states[i]
for _, state := range atn.states {
if _, ok := state.(*StarLoopEntryState); !ok {
continue
}
@ -468,12 +467,15 @@ func (this *ATNDeserializer) markPrecedenceDecisions(atn *ATN) {
// precedence rule should continue or complete.
//
if atn.ruleToStartState[state.GetRuleIndex()].isPrecedenceRule {
var maybeLoopEndState = state.GetTransitions()[len(state.GetTransitions())-1].getTarget()
if s3, ok := maybeLoopEndState.(*LoopEndState); ok {
s := maybeLoopEndState.GetTransitions()[0].getTarget()
_, ok2 := s.(*RuleStopState)
_, ok2 := maybeLoopEndState.GetTransitions()[0].getTarget().(*RuleStopState)
if s3.epsilonOnlyTransitions && ok2 {
s.(*StarLoopEntryState).precedenceRuleDecision = true
state.(*StarLoopEntryState).precedenceRuleDecision = true
}
}
}

View File

@ -13,6 +13,7 @@ type Parser interface {
GetTokenStream() TokenStream
GetTokenFactory() TokenFactory
GetParserRuleContext() ParserRuleContext
SetParserRuleContext(ParserRuleContext)
Consume() Token
GetParseListeners() []ParseTreeListener
@ -192,6 +193,10 @@ func (p *BaseParser) GetParserRuleContext() ParserRuleContext {
return p._ctx
}
func (p *BaseParser) SetParserRuleContext(v ParserRuleContext) {
p._ctx = v
}
func (p *BaseParser) GetParseListeners() []ParseTreeListener {
if p._parseListeners == nil {
return make([]ParseTreeListener, 0)

View File

@ -170,7 +170,7 @@ const (
func (p *<parser.name>) Sempred(localctx antlr4.RuleContext, ruleIndex, predIndex int) bool {
switch ruleIndex {
<parser.sempredFuncs.values:{f | case <f.ruleIndex>:
return p.<f.name; format="cap">_Sempred(localctx, predIndex);}; separator="\n">
return p.<f.name; format="cap">_Sempred(localctx.(*<f.name; format="cap">Context), predIndex)}; separator="\n">
default:
panic("No predicate with index:" + fmt.Sprint(ruleIndex))
}
@ -187,7 +187,7 @@ func (l *<lexer.name>) Action(localctx antlr4.RuleContext, ruleIndex, actionInde
switch ruleIndex {
<recog.actionFuncs.values:{f|
case <f.ruleIndex>:
l.<f.name; format="cap">_Action(localctx, actionIndex)
l.<f.name; format="cap">_Action(localctx<if(!f.isRuleContext)>.(*<f.ctxType>)<endif>, actionIndex)
}; separator="\n">
default:
panic("No registered action for:" + fmt.Sprint(ruleIndex))
@ -200,7 +200,7 @@ case <f.ruleIndex>:
func (l *<lexer.name>) Sempred(localctx antlr4.RuleContext, ruleIndex, predIndex int) bool {
switch ruleIndex {
<recog.sempredFuncs.values:{f| case <f.ruleIndex>:
return l.<f.name>_Sempred(localctx, predIndex);}; separator="\n">
return l.<f.name>_Sempred(localctx<if(!f.isRuleContext)>.(*<f.ctxType>)<endif>, predIndex);}; separator="\n">
default:
panic("No registered predicate for:" + fmt.Sprint(ruleIndex))
}
@ -216,7 +216,7 @@ func (l *<lexer.name>) Sempred(localctx antlr4.RuleContext, ruleIndex, predIndex
*/
RuleActionFunction(r, actions) ::= <<
func (l *<lexer.name>) <r.name; format="cap">_Action(localctx antlr4.RuleContext, actionIndex int) {
func (l *<lexer.name>) <r.name; format="cap">_Action(localctx <if(r.isRuleContext)>antlr4.RuleContext<else>*<r.ctxType><endif>, actionIndex int) {
switch actionIndex {
<actions:{index|
case <index>:
@ -232,7 +232,7 @@ case <index>:
* overriding implementation impossible to maintain.
*/
RuleSempredFunction(r, actions) ::= <<
func (p *<if(parser)><parser.name><else><lexer.name><endif>) <r.name; format="cap">_Sempred(localctx antlr4.RuleContext, predIndex int) bool {
func (p *<if(parser)><parser.name><else><lexer.name><endif>) <r.name; format="cap">_Sempred(localctx <if(r.isRuleContext)>antlr4.RuleContext<else>*<r.ctxType><endif>, predIndex int) bool {
switch predIndex {
<actions:{index| case <index>:
return <actions.(index)>;}; separator="\n">
@ -251,9 +251,9 @@ RuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,fina
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
func (p *<parser.name>) <currentRule.name; format="cap">(<currentRule.args:{a | <a.name> <a.type>}; separator=", ">) *<currentRule.ctxType> {
func (p *<parser.name>) <currentRule.name; format="cap">(<currentRule.args:{a | <a.name> <a.type>}; separator=", ">) antlr4.ParserRuleContext {
localctx := New<currentRule.ctxType>(p, p.GetParserRuleContext(), p.GetState()<currentRule.args:{a | , <a.name>}>)
var localctx antlr4.ParserRuleContext = New<currentRule.ctxType>(p, p.GetParserRuleContext(), p.GetState()<currentRule.args:{a | , <a.name>}>)
p.EnterRule(localctx, <currentRule.startState>, <parser.name>RULE_<currentRule.name>)
<namedActions.init>
<if(locals)>var <locals; separator="\nvar "><endif>
@ -295,12 +295,12 @@ LeftRecursiveRuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,
<ruleCtx>
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
func (p *<parser.name>) <currentRule.name; format="cap">(_p int<if(currentRule.args)>, <args:{a | , <a.name> <a.type>}><endif>) *<currentRule.ctxType> {
func (p *<parser.name>) <currentRule.name; format="cap">(_p int<if(currentRule.args)>, <args:{a | , <a.name> <a.type>}><endif>) antlr4.ParserRuleContext {
_parentctx := p.GetParserRuleContext()
var _parentctx antlr4.ParserRuleContext = p.GetParserRuleContext()
_parentState := p.GetState()
localctx := New<currentRule.ctxType>(p, p.GetParserRuleContext(), _parentState<args:{a | , <a.name>}>)
_prevctx := localctx
var localctx antlr4.ParserRuleContext = New<currentRule.ctxType>(p, p.GetParserRuleContext(), _parentState<args:{a | , <a.name>}>)
var _prevctx antlr4.ParserRuleContext = localctx
var _ antlr4.ParserRuleContext = _prevctx // to prevent unused variable warning
_startState := <currentRule.startState>
p.EnterRecursionRule(localctx, <currentRule.startState>, <parser.name>RULE_<currentRule.name>, _p)
@ -605,9 +605,10 @@ AddToLabelList(a) ::= "<ctx(a.label)>.<a.listName> = append(<ctx(a.label)>.<a.li
TokenDecl(t) ::= "<t.name> <TokenLabelType()>"
TokenTypeDecl(t) ::= "<t.name> int"
TokenListDecl(t) ::= "var <t.name> Token[] = make([]<TokenLabelType()>, 0)"
TokenListDecl(t) ::= "<t.name> antlr4.Token[] // = make([]<TokenLabelType()>, 0)"
RuleContextDecl(r) ::= "<r.name> *<r.ctxName>"
RuleContextListDecl(rdecl) ::= "var <rdecl.name> []*<rdecl.ctxName> = make([]*<rdecl.ctxName>, 0)"
RuleContextListDecl(rdecl) ::= "<rdecl.name> []*<rdecl.ctxName> // = make([]*<rdecl.ctxName>, 0)"
ContextTokenGetterDecl(t) ::= <<
<t.name; format="cap">() interface{} {
@ -687,6 +688,9 @@ func New<struct.name>(parser antlr4.Parser, parent antlr4.ParserRuleContext, inv
p.parser = parser
p.RuleIndex = <parser.name>RULE_<struct.derivedFromName>
// TODO initialize list attrs
<struct.ctorAttrs:{a | p.<a.name> = <a.name>}; separator="\n">
return p
}
@ -791,7 +795,7 @@ p.PushNewRecursionContext(localctx, _startState, <parser.name>RULE_<ruleName>)
recRuleReplaceContext(ctxName) ::= <<
localctx = New<ctxName>Context(p, localctx)
p.GetParserRuleContext() = localctx
p.SetParserRuleContext(localctx)
_prevctx = localctx
>>

View File

@ -38,6 +38,7 @@ import java.util.LinkedHashMap;
public class RuleActionFunction extends OutputModelObject {
public String name;
public String ctxType;
public boolean isRuleContext;
public int ruleIndex;
/** Map actionIndex to Action */
@ -48,6 +49,7 @@ public class RuleActionFunction extends OutputModelObject {
super(factory);
name = r.name;
ruleIndex = r.index;
isRuleContext = ctxType.equals("RuleContext");
this.ctxType = ctxType;
}
}