diff --git a/tool/nb-configuration.xml b/tool/nb-configuration.xml index 2d74a8819..4e1d86b58 100644 --- a/tool/nb-configuration.xml +++ b/tool/nb-configuration.xml @@ -32,5 +32,17 @@ Any value defined here will override the pom.xml file value but is only applicab false *;java test + 4 + 4 + 4 + false + 80 + none + 4 + 4 + 4 + false + 80 + none diff --git a/tool/src/org/antlr/v4/codegen/model/RuleFunction.java b/tool/src/org/antlr/v4/codegen/model/RuleFunction.java index 6cddce32a..39aaa1150 100644 --- a/tool/src/org/antlr/v4/codegen/model/RuleFunction.java +++ b/tool/src/org/antlr/v4/codegen/model/RuleFunction.java @@ -29,6 +29,9 @@ package org.antlr.v4.codegen.model; +import org.antlr.runtime.RecognitionException; +import org.antlr.runtime.tree.CommonTreeNodeStream; +import org.antlr.runtime.tree.TreeNodeStream; import org.antlr.v4.codegen.OutputModelFactory; import org.antlr.v4.codegen.model.decl.AltLabelStructDecl; import org.antlr.v4.codegen.model.decl.ContextRuleGetterDecl; @@ -40,27 +43,32 @@ import org.antlr.v4.codegen.model.decl.ContextTokenListIndexedGetterDecl; import org.antlr.v4.codegen.model.decl.Decl; import org.antlr.v4.codegen.model.decl.StructDecl; import org.antlr.v4.misc.FrequencySet; +import org.antlr.v4.misc.MutableInt; import org.antlr.v4.misc.Utils; +import org.antlr.v4.parse.GrammarASTAdaptor; +import org.antlr.v4.parse.GrammarTreeVisitor; import org.antlr.v4.runtime.atn.ATNState; import org.antlr.v4.runtime.misc.IntervalSet; import org.antlr.v4.runtime.misc.OrderedHashSet; import org.antlr.v4.runtime.misc.Triple; import org.antlr.v4.tool.Attribute; +import org.antlr.v4.tool.ErrorType; import org.antlr.v4.tool.Rule; import org.antlr.v4.tool.ast.ActionAST; import org.antlr.v4.tool.ast.AltAST; import org.antlr.v4.tool.ast.GrammarAST; +import org.antlr.v4.tool.ast.TerminalAST; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; +import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import static org.antlr.v4.parse.ANTLRParser.CLOSURE; -import static org.antlr.v4.parse.ANTLRParser.POSITIVE_CLOSURE; import static org.antlr.v4.parse.ANTLRParser.RULE_REF; import static org.antlr.v4.parse.ANTLRParser.TOKEN_REF; @@ -181,19 +189,9 @@ public class RuleFunction extends OutputModelObject { FrequencySet altFreq = getElementFrequenciesForAlt(ast); for (GrammarAST t : refs) { String refLabelName = t.getText(); - if (needsList.contains(refLabelName)) { - continue; - } - - if ( altFreq.count(t.getText())>1 ) { + if ( altFreq.count(refLabelName)>1 ) { needsList.add(refLabelName); } - else { - boolean inLoop = t.hasAncestor(CLOSURE) || t.hasAncestor(POSITIVE_CLOSURE); - if (inLoop) { - needsList.add(refLabelName); - } - } } } Set decls = new HashSet(); @@ -209,14 +207,19 @@ public class RuleFunction extends OutputModelObject { /** Given list of X and r refs in alt, compute how many of each there are */ protected FrequencySet getElementFrequenciesForAlt(AltAST ast) { - IntervalSet reftypes = new IntervalSet(RULE_REF, TOKEN_REF); - List refs = ast.getNodesWithType(reftypes); - FrequencySet altFreq = new FrequencySet(); - for (GrammarAST t : refs) { - String refLabelName = t.getText(); - altFreq.add(refLabelName); + try { + ElementFrequenciesVisitor visitor = new ElementFrequenciesVisitor(new CommonTreeNodeStream(new GrammarASTAdaptor(), ast)); + visitor.outerAlternative(); + if (visitor.frequencies.size() != 1) { + factory.getGrammar().tool.errMgr.toolError(ErrorType.INTERNAL_ERROR); + return new FrequencySet(); + } + + return visitor.frequencies.peek(); + } catch (RecognitionException ex) { + factory.getGrammar().tool.errMgr.toolError(ErrorType.INTERNAL_ERROR, ex); + return new FrequencySet(); } - return altFreq; } /** Get list of decls for token/rule refs. @@ -231,14 +234,10 @@ public class RuleFunction extends OutputModelObject { TOKEN_REF); List refs = altAST.getNodesWithType(reftypes); Set decls = new HashSet(); - FrequencySet freq = new FrequencySet(); - for (GrammarAST t : refs) freq.add(t.getText()); + FrequencySet freq = getElementFrequenciesForAlt(altAST); for (GrammarAST t : refs) { String refLabelName = t.getText(); - boolean inLoop = t.hasAncestor(CLOSURE) || t.hasAncestor(POSITIVE_CLOSURE); - boolean multipleRefs = freq.count(refLabelName)>1; - boolean needList = inLoop || multipleRefs; -// System.out.println(altAST.toStringTree()+" "+t+" inLoop? "+inLoop); + boolean needList = freq.count(refLabelName)>1; List d = getDeclForAltElement(t, refLabelName, needList); decls.addAll(d); } @@ -293,4 +292,129 @@ public class RuleFunction extends OutputModelObject { } ruleCtx.addDecl(d); // stick in overall rule's ctx } + + protected static class ElementFrequenciesVisitor extends GrammarTreeVisitor { + final Deque> frequencies; + + public ElementFrequenciesVisitor(TreeNodeStream input) { + super(input); + frequencies = new ArrayDeque>(); + frequencies.push(new FrequencySet()); + } + + /* + * Common + */ + + protected static FrequencySet combineMax(FrequencySet a, FrequencySet b) { + FrequencySet result = combineAndClip(a, b, 1); + for (Map.Entry entry : a.entrySet()) { + result.get(entry.getKey()).v = entry.getValue().v; + } + + for (Map.Entry entry : a.entrySet()) { + MutableInt slot = result.get(entry.getKey()); + slot.v = Math.max(slot.v, entry.getValue().v); + } + + return result; + } + + protected static FrequencySet combineAndClip(FrequencySet a, FrequencySet b, int clip) { + FrequencySet result = new FrequencySet(); + for (Map.Entry entry : a.entrySet()) { + for (int i = 0; i < entry.getValue().v; i++) { + result.add(entry.getKey()); + } + } + + for (Map.Entry entry : b.entrySet()) { + for (int i = 0; i < entry.getValue().v; i++) { + result.add(entry.getKey()); + } + } + + for (Map.Entry entry : result.entrySet()) { + entry.getValue().v = Math.min(entry.getValue().v, clip); + } + + return result; + } + + @Override + public void tokenRef(TerminalAST ref) { + frequencies.peek().add(ref.getText()); + } + + @Override + public void ruleRef(GrammarAST ref, ActionAST arg) { + frequencies.peek().add(ref.getText()); + } + + /* + * Parser rules + */ + + @Override + protected void enterAlternative(AltAST tree) { + frequencies.push(new FrequencySet()); + } + + @Override + protected void exitAlternative(AltAST tree) { + frequencies.push(combineMax(frequencies.pop(), frequencies.pop())); + } + + @Override + protected void enterElement(GrammarAST tree) { + frequencies.push(new FrequencySet()); + } + + @Override + protected void exitElement(GrammarAST tree) { + frequencies.push(combineAndClip(frequencies.pop(), frequencies.pop(), 2)); + } + + @Override + protected void exitSubrule(GrammarAST tree) { + if (tree.getType() == CLOSURE || tree.getType() == POSITIVE_CLOSURE) { + for (Map.Entry entry : frequencies.peek().entrySet()) { + entry.getValue().v = 2; + } + } + } + + /* + * Lexer rules + */ + + @Override + protected void enterLexerAlternative(GrammarAST tree) { + frequencies.push(new FrequencySet()); + } + + @Override + protected void exitLexerAlternative(GrammarAST tree) { + frequencies.push(combineMax(frequencies.pop(), frequencies.pop())); + } + + @Override + protected void enterLexerElement(GrammarAST tree) { + frequencies.push(new FrequencySet()); + } + + @Override + protected void exitLexerElement(GrammarAST tree) { + frequencies.push(combineAndClip(frequencies.pop(), frequencies.pop(), 2)); + } + + @Override + protected void exitLexerSubrule(GrammarAST tree) { + if (tree.getType() == CLOSURE || tree.getType() == POSITIVE_CLOSURE) { + for (Map.Entry entry : frequencies.peek().entrySet()) { + entry.getValue().v = 2; + } + } + } + } } diff --git a/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g b/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g index f41ac29e8..43dbc2bb0 100644 --- a/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g +++ b/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g @@ -96,7 +96,7 @@ public ErrorManager getErrorManager() { return null; } public void visitGrammar(GrammarAST t) { visit(t, "grammarSpec"); } public void visit(GrammarAST t, String ruleName) { - CommonTreeNodeStream nodes = new CommonTreeNodeStream(t); + CommonTreeNodeStream nodes = new CommonTreeNodeStream(new GrammarASTAdaptor(), t); setTreeNodeStream(nodes); try { Method m = getClass().getMethod(ruleName); @@ -156,6 +156,165 @@ public void label(GrammarAST op, GrammarAST ID, GrammarAST element) { } public void lexerCallCommand(int outerAltNumber, GrammarAST ID, GrammarAST arg) { } public void lexerCommand(int outerAltNumber, GrammarAST ID) { } +protected void enterGrammarSpec(GrammarAST tree) { } +protected void exitGrammarSpec(GrammarAST tree) { } + +protected void enterPrequelConstructs(GrammarAST tree) { } +protected void exitPrequelConstructs(GrammarAST tree) { } + +protected void enterPrequelConstruct(GrammarAST tree) { } +protected void exitPrequelConstruct(GrammarAST tree) { } + +protected void enterOptionsSpec(GrammarAST tree) { } +protected void exitOptionsSpec(GrammarAST tree) { } + +protected void enterOption(GrammarAST tree) { } +protected void exitOption(GrammarAST tree) { } + +protected void enterOptionValue(GrammarAST tree) { } +protected void exitOptionValue(GrammarAST tree) { } + +protected void enterDelegateGrammars(GrammarAST tree) { } +protected void exitDelegateGrammars(GrammarAST tree) { } + +protected void enterDelegateGrammar(GrammarAST tree) { } +protected void exitDelegateGrammar(GrammarAST tree) { } + +protected void enterTokensSpec(GrammarAST tree) { } +protected void exitTokensSpec(GrammarAST tree) { } + +protected void enterTokenSpec(GrammarAST tree) { } +protected void exitTokenSpec(GrammarAST tree) { } + +protected void enterAction(GrammarAST tree) { } +protected void exitAction(GrammarAST tree) { } + +protected void enterRules(GrammarAST tree) { } +protected void exitRules(GrammarAST tree) { } + +protected void enterMode(GrammarAST tree) { } +protected void exitMode(GrammarAST tree) { } + +protected void enterLexerRule(GrammarAST tree) { } +protected void exitLexerRule(GrammarAST tree) { } + +protected void enterRule(GrammarAST tree) { } +protected void exitRule(GrammarAST tree) { } + +protected void enterExceptionGroup(GrammarAST tree) { } +protected void exitExceptionGroup(GrammarAST tree) { } + +protected void enterExceptionHandler(GrammarAST tree) { } +protected void exitExceptionHandler(GrammarAST tree) { } + +protected void enterFinallyClause(GrammarAST tree) { } +protected void exitFinallyClause(GrammarAST tree) { } + +protected void enterLocals(GrammarAST tree) { } +protected void exitLocals(GrammarAST tree) { } + +protected void enterRuleReturns(GrammarAST tree) { } +protected void exitRuleReturns(GrammarAST tree) { } + +protected void enterThrowsSpec(GrammarAST tree) { } +protected void exitThrowsSpec(GrammarAST tree) { } + +protected void enterRuleAction(GrammarAST tree) { } +protected void exitRuleAction(GrammarAST tree) { } + +protected void enterRuleModifier(GrammarAST tree) { } +protected void exitRuleModifier(GrammarAST tree) { } + +protected void enterLexerRuleBlock(GrammarAST tree) { } +protected void exitLexerRuleBlock(GrammarAST tree) { } + +protected void enterRuleBlock(GrammarAST tree) { } +protected void exitRuleBlock(GrammarAST tree) { } + +protected void enterLexerOuterAlternative(AltAST tree) { } +protected void exitLexerOuterAlternative(AltAST tree) { } + +protected void enterOuterAlternative(AltAST tree) { } +protected void exitOuterAlternative(AltAST tree) { } + +protected void enterLexerAlternative(GrammarAST tree) { } +protected void exitLexerAlternative(GrammarAST tree) { } + +protected void enterLexerElements(GrammarAST tree) { } +protected void exitLexerElements(GrammarAST tree) { } + +protected void enterLexerElement(GrammarAST tree) { } +protected void exitLexerElement(GrammarAST tree) { } + +protected void enterLabeledLexerElement(GrammarAST tree) { } +protected void exitLabeledLexerElement(GrammarAST tree) { } + +protected void enterLexerBlock(GrammarAST tree) { } +protected void exitLexerBlock(GrammarAST tree) { } + +protected void enterLexerAtom(GrammarAST tree) { } +protected void exitLexerAtom(GrammarAST tree) { } + +protected void enterActionElement(GrammarAST tree) { } +protected void exitActionElement(GrammarAST tree) { } + +protected void enterAlternative(AltAST tree) { } +protected void exitAlternative(AltAST tree) { } + +protected void enterLexerCommand(GrammarAST tree) { } +protected void exitLexerCommand(GrammarAST tree) { } + +protected void enterLexerCommandExpr(GrammarAST tree) { } +protected void exitLexerCommandExpr(GrammarAST tree) { } + +protected void enterElement(GrammarAST tree) { } +protected void exitElement(GrammarAST tree) { } + +protected void enterAstOperand(GrammarAST tree) { } +protected void exitAstOperand(GrammarAST tree) { } + +protected void enterLabeledElement(GrammarAST tree) { } +protected void exitLabeledElement(GrammarAST tree) { } + +protected void enterSubrule(GrammarAST tree) { } +protected void exitSubrule(GrammarAST tree) { } + +protected void enterLexerSubrule(GrammarAST tree) { } +protected void exitLexerSubrule(GrammarAST tree) { } + +protected void enterBlockSuffix(GrammarAST tree) { } +protected void exitBlockSuffix(GrammarAST tree) { } + +protected void enterEbnfSuffix(GrammarAST tree) { } +protected void exitEbnfSuffix(GrammarAST tree) { } + +protected void enterAtom(GrammarAST tree) { } +protected void exitAtom(GrammarAST tree) { } + +protected void enterBlockSet(GrammarAST tree) { } +protected void exitBlockSet(GrammarAST tree) { } + +protected void enterSetElement(GrammarAST tree) { } +protected void exitSetElement(GrammarAST tree) { } + +protected void enterBlock(GrammarAST tree) { } +protected void exitBlock(GrammarAST tree) { } + +protected void enterRuleref(GrammarAST tree) { } +protected void exitRuleref(GrammarAST tree) { } + +protected void enterRange(GrammarAST tree) { } +protected void exitRange(GrammarAST tree) { } + +protected void enterTerminal(GrammarAST tree) { } +protected void exitTerminal(GrammarAST tree) { } + +protected void enterElementOptions(GrammarAST tree) { } +protected void exitElementOptions(GrammarAST tree) { } + +protected void enterElementOption(GrammarAST tree) { } +protected void exitElementOption(GrammarAST tree) { } + public void traceIn(String ruleName, int ruleIndex) { System.err.println("enter "+ruleName+": "+input.LT(1)); } @@ -166,6 +325,12 @@ public void lexerCommand(int outerAltNumber, GrammarAST ID) { } } grammarSpec +@init { + enterGrammarSpec($start); +} +@after { + exitGrammarSpec($start); +} : ^( GRAMMAR ID {grammarName=$ID.text;} DOC_COMMENT? {discoverGrammar((GrammarRootAST)$GRAMMAR, $ID);} prequelConstructs @@ -176,11 +341,23 @@ grammarSpec ; prequelConstructs returns [GrammarAST firstOne=null] +@init { + enterPrequelConstructs($start); +} +@after { + exitPrequelConstructs($start); +} : {$firstOne=$start;} prequelConstruct+ | ; prequelConstruct +@init { + enterPrequelConstructs($start); +} +@after { + exitPrequelConstructs($start); +} : optionsSpec | delegateGrammars | tokensSpec @@ -188,13 +365,23 @@ prequelConstruct ; optionsSpec +@init { + enterOptionsSpec($start); +} +@after { + exitOptionsSpec($start); +} : ^(OPTIONS option*) ; option @init { -boolean rule = inContext("RULE ..."); -boolean block = inContext("BLOCK ..."); + enterOption($start); + boolean rule = inContext("RULE ..."); + boolean block = inContext("BLOCK ..."); +} +@after { + exitOption($start); } : ^(a=ASSIGN ID v=optionValue) { @@ -205,34 +392,76 @@ boolean block = inContext("BLOCK ..."); ; optionValue returns [String v] -@init {$v = $start.token.getText();} +@init { + enterOptionValue($start); + $v = $start.token.getText(); +} +@after { + exitOptionValue($start); +} : ID | STRING_LITERAL | INT ; delegateGrammars +@init { + enterDelegateGrammars($start); +} +@after { + exitDelegateGrammars($start); +} : ^(IMPORT delegateGrammar+) ; delegateGrammar +@init { + enterDelegateGrammar($start); +} +@after { + exitDelegateGrammar($start); +} : ^(ASSIGN label=ID id=ID) {importGrammar($label, $id);} | id=ID {importGrammar(null, $id);} ; tokensSpec +@init { + enterTokensSpec($start); +} +@after { + exitTokensSpec($start); +} : ^(TOKENS_SPEC tokenSpec+) ; tokenSpec +@init { + enterTokenSpec($start); +} +@after { + exitTokenSpec($start); +} : ID {defineToken($ID);} ; action +@init { + enterAction($start); +} +@after { + exitAction($start); +} : ^(AT sc=ID? name=ID ACTION) {globalNamedAction($sc, $name, (ActionAST)$ACTION);} ; rules +@init { + enterRules($start); +} +@after { + exitRules($start); +} : ^(RULES {discoverRules($RULES);} (rule|lexerRule)* {finishRules($RULES);}) ; @@ -240,8 +469,12 @@ mode : ^( MODE ID {currentModeName=$ID.text; modeDef($MODE, $ID);} lexerRule+ ) lexerRule @init { -List mods = new ArrayList(); -currentOuterAltNumber=0; + enterLexerRule($start); + List mods = new ArrayList(); + currentOuterAltNumber=0; +} +@after { + exitLexerRule($start); } : ^( RULE TOKEN_REF {currentRuleName=$TOKEN_REF.text; currentRuleAST=$RULE;} @@ -257,9 +490,13 @@ currentOuterAltNumber=0; rule @init { -List mods = new ArrayList(); -List actions = new ArrayList(); // track roots -currentOuterAltNumber=0; + enterRule($start); + List mods = new ArrayList(); + List actions = new ArrayList(); // track roots + currentOuterAltNumber=0; +} +@after { + exitRule($start); } : ^( RULE RULE_REF {currentRuleName=$RULE_REF.text; currentRuleAST=$RULE;} DOC_COMMENT? (^(RULEMODIFIERS (m=ruleModifier{mods.add($m.start);})+))? @@ -281,33 +518,82 @@ currentOuterAltNumber=0; ; exceptionGroup +@init { + enterExceptionGroup($start); +} +@after { + exitExceptionGroup($start); +} : exceptionHandler* finallyClause? ; exceptionHandler +@init { + enterExceptionHandler($start); +} +@after { + exitExceptionHandler($start); +} : ^(CATCH ARG_ACTION ACTION) {ruleCatch($ARG_ACTION, (ActionAST)$ACTION);} ; finallyClause +@init { + enterFinallyClause($start); +} +@after { + exitFinallyClause($start); +} : ^(FINALLY ACTION) {finallyAction((ActionAST)$ACTION);} ; locals +@init { + enterLocals($start); +} +@after { + exitLocals($start); +} : ^(LOCALS ARG_ACTION) ; ruleReturns +@init { + enterRuleReturns($start); +} +@after { + exitRuleReturns($start); +} : ^(RETURNS ARG_ACTION) ; + throwsSpec +@init { + enterThrowsSpec($start); +} +@after { + exitThrowsSpec($start); +} : ^(THROWS ID+) ; ruleAction +@init { + enterRuleAction($start); +} +@after { + exitRuleAction($start); +} : ^(AT ID ACTION) ; ruleModifier +@init { + enterRuleModifier($start); +} +@after { + exitRuleModifier($start); +} : PUBLIC | PRIVATE | PROTECTED @@ -315,6 +601,12 @@ ruleModifier ; lexerRuleBlock +@init { + enterLexerRuleBlock($start); +} +@after { + exitLexerRuleBlock($start); +} : ^( BLOCK ( { currentOuterAltRoot = (GrammarAST)input.LT(1); @@ -326,6 +618,12 @@ lexerRuleBlock ; ruleBlock +@init { + enterRuleBlock($start); +} +@after { + exitRuleBlock($start); +} : ^( BLOCK ( { currentOuterAltRoot = (GrammarAST)input.LT(1); @@ -338,10 +636,12 @@ ruleBlock lexerOuterAlternative @init { + enterLexerOuterAlternative((AltAST)$start); discoverOuterAlt((AltAST)$start); } @after { finishOuterAlt((AltAST)$start); + exitLexerOuterAlternative((AltAST)$start); } : lexerAlternative ; @@ -349,24 +649,44 @@ lexerOuterAlternative outerAlternative @init { + enterOuterAlternative((AltAST)$start); discoverOuterAlt((AltAST)$start); } @after { finishOuterAlt((AltAST)$start); + exitOuterAlternative((AltAST)$start); } : alternative ; lexerAlternative +@init { + enterLexerAlternative($start); +} +@after { + exitLexerAlternative($start); +} : ^(LEXER_ALT_ACTION lexerElements lexerCommand+) | lexerElements ; lexerElements +@init { + enterLexerElements($start); +} +@after { + exitLexerElements($start); +} : ^(ALT lexerElement+) ; lexerElement +@init { + enterLexerElement($start); +} +@after { + exitLexerElement($start); +} : labeledLexerElement | lexerAtom | lexerSubrule @@ -377,14 +697,32 @@ lexerElement ; labeledLexerElement +@init { + enterLabeledLexerElement($start); +} +@after { + exitLabeledLexerElement($start); +} : ^((ASSIGN|PLUS_ASSIGN) ID (lexerAtom|block)) ; lexerBlock +@init { + enterLexerBlock($start); +} +@after { + exitLexerBlock($start); +} : ^(BLOCK optionsSpec? lexerAlternative+) ; lexerAtom +@init { + enterLexerAtom($start); +} +@after { + exitLexerAtom($start); +} : terminal | ^(NOT blockSet) | blockSet @@ -395,6 +733,12 @@ lexerAtom ; actionElement +@init { + enterActionElement($start); +} +@after { + exitActionElement($start); +} : ACTION | ^(ACTION elementOptions) | SEMPRED @@ -403,16 +747,24 @@ actionElement alternative @init { + enterAlternative((AltAST)$start); discoverAlt((AltAST)$start); } @after { finishAlt((AltAST)$start); + exitAlternative((AltAST)$start); } : ^(ALT element+) | ^(ALT EPSILON) ; lexerCommand +@init { + enterLexerCommand($start); +} +@after { + exitLexerCommand($start); +} : ^(LEXER_ACTION_CALL ID lexerCommandExpr) {lexerCallCommand(currentOuterAltNumber, $ID, $lexerCommandExpr.start);} | ID @@ -420,11 +772,23 @@ lexerCommand ; lexerCommandExpr +@init { + enterLexerCommandExpr($start); +} +@after { + exitLexerCommandExpr($start); +} : ID | INT ; element +@init { + enterElement($start); +} +@after { + exitElement($start); +} : labeledElement | atom | subrule @@ -438,36 +802,79 @@ element ; astOperand +@init { + enterAstOperand($start); +} +@after { + exitAstOperand($start); +} : atom | ^(NOT blockSet) | ^(NOT block) ; labeledElement +@init { + enterLabeledElement($start); +} +@after { + exitLabeledElement($start); +} : ^((ASSIGN|PLUS_ASSIGN) ID element) {label($start, $ID, $element.start);} ; subrule +@init { + enterSubrule($start); +} +@after { + exitSubrule($start); +} : ^(blockSuffix block) | block ; lexerSubrule +@init { + enterLexerSubrule($start); +} +@after { + exitLexerSubrule($start); +} : ^(blockSuffix lexerBlock) | lexerBlock ; blockSuffix +@init { + enterBlockSuffix($start); +} +@after { + exitBlockSuffix($start); +} : ebnfSuffix ; ebnfSuffix +@init { + enterEbnfSuffix($start); +} +@after { + exitEbnfSuffix($start); +} : OPTIONAL | CLOSURE | POSITIVE_CLOSURE ; -atom: ^(DOT ID terminal) +atom +@init { + enterAtom($start); +} +@after { + exitAtom($start); +} + : ^(DOT ID terminal) | ^(DOT ID ruleref) | ^(WILDCARD elementOptions) {wildcardRef($WILDCARD);} | WILDCARD {wildcardRef($WILDCARD);} @@ -477,10 +884,22 @@ atom: ^(DOT ID terminal) ; blockSet +@init { + enterBlockSet($start); +} +@after { + exitBlockSet($start); +} : ^(SET setElement+) ; setElement +@init { + enterSetElement($start); +} +@after { + exitSetElement($start); +} : STRING_LITERAL {stringRef((TerminalAST)$STRING_LITERAL);} | TOKEN_REF {tokenRef((TerminalAST)$TOKEN_REF);} | ^(RANGE a=STRING_LITERAL b=STRING_LITERAL) @@ -492,10 +911,22 @@ setElement ; block +@init { + enterBlock($start); +} +@after { + exitBlock($start); +} : ^(BLOCK optionsSpec? ruleAction* ACTION? alternative+) ; ruleref +@init { + enterRuleref($start); +} +@after { + exitRuleref($start); +} : ^(RULE_REF arg=ARG_ACTION?) { ruleRef($RULE_REF, (ActionAST)$ARG_ACTION); @@ -504,6 +935,12 @@ ruleref ; range +@init { + enterRange($start); +} +@after { + exitRange($start); +} : ^(RANGE STRING_LITERAL STRING_LITERAL) ; @@ -516,12 +953,24 @@ terminal ; elementOptions +@init { + enterElementOptions($start); +} +@after { + exitElementOptions($start); +} : ^(ELEMENT_OPTIONS elementOption[(GrammarASTWithOptions)$start.getParent()]+) ; elementOption[GrammarASTWithOptions t] +@init { + enterElementOption($start); +} +@after { + exitElementOption($start); +} : ID {elementOption(t, $ID, null);} | ^(ASSIGN id=ID v=ID) {elementOption(t, $id, $v);} | ^(ASSIGN ID v=STRING_LITERAL) {elementOption(t, $ID, $v);} | ^(ASSIGN ID v=ACTION) {elementOption(t, $ID, $v);} - ; \ No newline at end of file + ; diff --git a/tool/src/org/antlr/v4/tool/GrammarTransformPipeline.java b/tool/src/org/antlr/v4/tool/GrammarTransformPipeline.java index 69dc0f0ae..19360914e 100644 --- a/tool/src/org/antlr/v4/tool/GrammarTransformPipeline.java +++ b/tool/src/org/antlr/v4/tool/GrammarTransformPipeline.java @@ -30,6 +30,7 @@ package org.antlr.v4.tool; import org.antlr.runtime.CommonToken; +import org.antlr.runtime.tree.CommonTreeNodeStream; import org.antlr.runtime.tree.Tree; import org.antlr.runtime.tree.TreeVisitor; import org.antlr.runtime.tree.TreeVisitorAction; @@ -76,8 +77,7 @@ public class GrammarTransformPipeline { } public void reduceBlocksToSets(GrammarAST root) { - org.antlr.runtime.tree.CommonTreeNodeStream nodes = - new org.antlr.runtime.tree.CommonTreeNodeStream(root); + CommonTreeNodeStream nodes = new CommonTreeNodeStream(new GrammarASTAdaptor(), root); GrammarASTAdaptor adaptor = new GrammarASTAdaptor(); BlockSetTransformer transformer = new BlockSetTransformer(nodes, g); transformer.setTreeAdaptor(adaptor);