diff --git a/tool/src/org/antlr/v4/analysis/LeftRecursiveRuleTransformer.java b/tool/src/org/antlr/v4/analysis/LeftRecursiveRuleTransformer.java index 2e713f78d..cb58c54ee 100644 --- a/tool/src/org/antlr/v4/analysis/LeftRecursiveRuleTransformer.java +++ b/tool/src/org/antlr/v4/analysis/LeftRecursiveRuleTransformer.java @@ -92,7 +92,6 @@ public class LeftRecursiveRuleTransformer { for (Rule r : rules) { if ( !Grammar.isTokenName(r.name) ) { if ( LeftRecursiveRuleAnalyzer.hasImmediateRecursiveRuleRefs(r.ast, r.name) ) { - g.originalTokenStream = g.tokenStream; boolean fitsPattern = translateLeftRecursiveRule(ast, (LeftRecursiveRule)r, language); if ( fitsPattern ) leftRecursiveRuleNames.add(r.name); } @@ -131,11 +130,15 @@ public class LeftRecursiveRuleTransformer { } if ( !isLeftRec ) return false; - // replace old rule's AST + // replace old rule's AST; first create text of altered rule GrammarAST RULES = (GrammarAST)ast.getFirstChildWithType(ANTLRParser.RULES); String newRuleText = leftRecursiveRuleWalker.getArtificialOpPrecRule(); // System.out.println("created: "+newRuleText); - RuleAST t = parseArtificialRule(g, newRuleText); + // now parse within the context of the grammar that originally created + // the AST we are transforming. This could be an imported grammar so + // we cannot just reference this.g because the role might come from + // the imported grammar and not the root grammar (this.g) + RuleAST t = parseArtificialRule(prevRuleAST.g, newRuleText); // reuse the name token from the original AST since it refers to the proper source location in the original grammar ((GrammarAST)t.getChild(0)).token = ((GrammarAST)prevRuleAST.getChild(0)).getToken(); diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index 53ca3f29f..01ebdba38 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -155,10 +155,19 @@ public class Grammar implements AttributeResolver { public String name; public GrammarRootAST ast; - /** Track stream used to create this grammar */ + + /** Track token stream used to create this grammar */ @NotNull public final org.antlr.runtime.TokenStream tokenStream; - /** If we transform grammar, track original unaltered token stream */ + + /** If we transform grammar, track original unaltered token stream. + * This is set to the same value as tokenStream when tokenStream is + * initially set. + * + * If this field differs from tokenStream, then we have transformed + * the grammar. + */ + @NotNull public org.antlr.runtime.TokenStream originalTokenStream; public String text; // testing only @@ -288,6 +297,7 @@ public class Grammar implements AttributeResolver { this.ast = ast; this.name = (ast.getChild(0)).getText(); this.tokenStream = ast.tokenStream; + this.originalTokenStream = this.tokenStream; initTokenSymbolTables(); } @@ -343,6 +353,7 @@ public class Grammar implements AttributeResolver { } this.tokenStream = ast.tokenStream; + this.originalTokenStream = this.tokenStream; // ensure each node has pointer to surrounding grammar final Grammar thiz = this;