diff --git a/runtime/Java/src/org/antlr/v4/runtime/DefaultANTLRErrorStrategy.java b/runtime/Java/src/org/antlr/v4/runtime/DefaultANTLRErrorStrategy.java index dadabeee7..04648ed4a 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/DefaultANTLRErrorStrategy.java +++ b/runtime/Java/src/org/antlr/v4/runtime/DefaultANTLRErrorStrategy.java @@ -204,9 +204,12 @@ public class DefaultANTLRErrorStrategy implements ANTLRErrorStrategy { throws RecognitionException { String ruleName = recognizer.getRuleNames()[recognizer._ctx.getRuleIndex()]; - String msg = "rule "+ruleName+" failed predicate: {"+ - e.predicateText+"}?"; - recognizer.notifyListeners(e.offendingToken, msg, e); + String msg = "rule "+ruleName+" "+e.msg; + recognizer.notifyListeners(curToken(recognizer), msg, e); + } + + private Token curToken(BaseRecognizer recognizer) { + return ((TokenStream)recognizer.getInputStream()).LT(1); } public void reportUnwantedToken(BaseRecognizer recognizer) { diff --git a/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java b/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java index b70e6e4bb..0c0510e3b 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java +++ b/runtime/Java/src/org/antlr/v4/runtime/FailedPredicateException.java @@ -28,31 +28,29 @@ */ package org.antlr.v4.runtime; +import com.sun.istack.internal.Nullable; +import org.antlr.v4.runtime.atn.*; + /** A semantic predicate failed during validation. Validation of predicates * occurs when normally parsing the alternative just like matching a token. - * Disambiguating predicate evaluation occurs when we hoist a predicate into - * a prediction decision. + * Disambiguating predicate evaluation occurs when we test a predicate during + * prediction. */ public class FailedPredicateException extends RecognitionException { - public String ruleName; - public String predicateText; + public int ruleIndex; + public int predIndex; + public String msg; - public FailedPredicateException(BaseRecognizer recognizer, String predText) { - super(recognizer, recognizer.getInputStream(), recognizer._ctx); - this.predicateText = predText; + public FailedPredicateException(BaseRecognizer recognizer) { + this(recognizer, null); } -// public FailedPredicateException(BaseRecognizer recognizer, -// IntStream input, -// String ruleName, -// String predicateText) -// { -// super(recognizer, input, recognizer._ctx); -// this.ruleName = ruleName; -// this.predicateText = predicateText; -// } - - public String toString() { - return "FailedPredicateException("+ruleName+",{"+predicateText+"}?)"; + public FailedPredicateException(BaseRecognizer recognizer, @Nullable String msg) { + super(recognizer, recognizer.getInputStream(), recognizer._ctx); + ATNState s = recognizer._interp.atn.states.get(recognizer._ctx.s); + PredicateTransition trans = (PredicateTransition)s.transition(0); + ruleIndex = trans.ruleIndex; + predIndex = trans.predIndex; + this.msg = msg; } } diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg index bcdaaac8b..73f0ff8d1 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg @@ -447,7 +447,8 @@ ForcedAction(a, chunks) ::= "" ArgAction(a, chunks) ::= "" SemPred(p, chunks) ::= << -if (!()) throw new FailedPredicateException(this, ""); +setState(); +if (!()) throw new FailedPredicateException(this, ""); >> ActionText(t) ::= "" diff --git a/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g b/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g index 94e217082..5cb35b7cb 100644 --- a/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g +++ b/tool/src/org/antlr/v4/codegen/SourceGenTriggers.g @@ -109,6 +109,8 @@ element returns [List omos] | subrule {$omos = $subrule.omos;} | ACTION {$omos = controller.action($ACTION);} | SEMPRED {$omos = controller.sempred($SEMPRED);} + | ^(ACTION elementOptions) {$omos = controller.action($ACTION);} + | ^(SEMPRED elementOptions) {$omos = controller.sempred($SEMPRED);} | treeSpec {$omos = DefaultOutputModelFactory.list($treeSpec.treeMatch);} ; @@ -209,6 +211,7 @@ elementOption : ID | ^(ASSIGN ID ID) | ^(ASSIGN ID STRING_LITERAL) + | ^(ASSIGN ID DOUBLE_QUOTE_STRING_LITERAL) ; // R E W R I T E S T U F F diff --git a/tool/src/org/antlr/v4/codegen/model/SemPred.java b/tool/src/org/antlr/v4/codegen/model/SemPred.java index a50e0bbb3..5722d3ae5 100644 --- a/tool/src/org/antlr/v4/codegen/model/SemPred.java +++ b/tool/src/org/antlr/v4/codegen/model/SemPred.java @@ -30,9 +30,17 @@ package org.antlr.v4.codegen.model; import org.antlr.v4.codegen.OutputModelFactory; -import org.antlr.v4.tool.ast.GrammarAST; +import org.antlr.v4.tool.ast.*; /** */ public class SemPred extends Action { - public SemPred(OutputModelFactory factory, GrammarAST ast) { super(factory,ast); } + public String msg; // user-specified in grammar option + + public SemPred(OutputModelFactory factory, GrammarAST ast) { + super(factory,ast); + this.msg = ((PredAST)ast).getOption("msg"); + if ( msg==null ) { + msg = "failed predicate: "+ast.getText(); + } + } } diff --git a/tool/src/org/antlr/v4/parse/ANTLRParser.g b/tool/src/org/antlr/v4/parse/ANTLRParser.g index b5356b7bc..2a0038330 100644 --- a/tool/src/org/antlr/v4/parse/ANTLRParser.g +++ b/tool/src/org/antlr/v4/parse/ANTLRParser.g @@ -276,8 +276,10 @@ optionValue | // The value is a long string // - STRING_LITERAL + STRING_LITERAL + | DOUBLE_QUOTE_STRING_LITERAL + | // The value was an integer number // INT @@ -594,8 +596,7 @@ element | -> atom ) | ebnf - | ACTION - | SEMPRED -> SEMPRED + | actionElement | treeSpec ( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK[$treeSpec.start,"BLOCK"] ^(ALT treeSpec ) ) ) | -> treeSpec @@ -628,20 +629,24 @@ element recover(input,re); } +actionElement +@after { + GrammarAST options = (GrammarAST)$tree.getFirstChildWithType(ANTLRParser.ELEMENT_OPTIONS); + if ( options!=null ) { + Grammar.setNodeOptions($tree, options); + } +} + : ACTION + | ACTION elementOptions -> ^(ACTION elementOptions) + | SEMPRED + | SEMPRED elementOptions -> ^(SEMPRED elementOptions) + ; + labeledElement : id (ass=ASSIGN|ass=PLUS_ASSIGN) ( atom -> ^($ass id atom) | block (op=ROOT|op=BANG)? -> {$op!=null}? ^($ass id ^($op block)) -> ^($ass id block) -/* - | {buildAST}? blockSet - { - RecognitionException e = - new v4ParserException("can't '"+ - input.LT(1).getText()+" "+input.LT(2).getText()+"'", input); - reportError(missingSemi); - } -*/ ) ; @@ -710,14 +715,6 @@ ebnfSuffix ; atom -@after { - if ( $tree.getType()==DOT ) { - GrammarAST options = (GrammarAST)$tree.getFirstChildWithType(ANTLRParser.OPTIONS); - if ( options!=null ) { - Grammar.setNodeOptions($tree, options); - } - } -} : // Qualified reference delegate.rule. This must be // lexically contiguous (no spaces either side of the DOT) // otherwise it is two references with a wildcard in between @@ -736,7 +733,18 @@ atom | terminal (ROOT^ | BANG^)? | ruleref | notSet (ROOT^|BANG^)? - | // Wildcard '.' means any character in a lexer, any + | wildcard + ; + catch [RecognitionException re] { throw re; } // pass upwards to element + +wildcard +@after { + GrammarAST options = (GrammarAST)$tree.getFirstChildWithType(ANTLRParser.ELEMENT_OPTIONS); + if ( options!=null ) { + Grammar.setNodeOptions($tree, options); + } +} + : // Wildcard '.' means any character in a lexer, any // token in parser and any node or subtree in a tree parser // Because the terminal rule is allowed to be the node // specification for the start of a tree rule, we must @@ -744,9 +752,8 @@ atom DOT elementOptions? (astop=ROOT|astop=BANG)? -> {astop!=null}? ^($astop ^(WILDCARD[$DOT] elementOptions?)) -> ^(WILDCARD[$DOT] elementOptions?) - ; - catch [RecognitionException re] { throw re; } // pass upwards to element - + ; + // -------------------- // Inverted element set // @@ -827,7 +834,7 @@ if ( options!=null ) { Grammar.setNodeOptions($tree, options); } } - : TOKEN_REF elementOptions? -> ^(TOKEN_REF elementOptions?) + : TOKEN_REF elementOptions? -> ^(TOKEN_REF elementOptions?) | STRING_LITERAL elementOptions? -> ^(STRING_LITERAL elementOptions?) ; @@ -837,14 +844,14 @@ elementOptions : LT elementOption (COMMA elementOption)* GT -> ^(ELEMENT_OPTIONS[$LT,"ELEMENT_OPTIONS"] elementOption+) ; -// WHen used with elements we can specify what the tree node type can +// When used with elements we can specify what the tree node type can // be and also assign settings of various options (which we do not check here) elementOption - : // This format indicates the default node option + : // This format indicates the default element option qid | // This format indicates option assignment - id ASSIGN^ (qid | STRING_LITERAL) + id ASSIGN^ (qid | STRING_LITERAL | DOUBLE_QUOTE_STRING_LITERAL) ; rewrite @@ -897,7 +904,7 @@ rewriteTreeElement rewriteTreeAtom @after { -GrammarAST options = (GrammarAST)$tree.getFirstChildWithType(ANTLRParser.OPTIONS); +GrammarAST options = (GrammarAST)$tree.getFirstChildWithType(ANTLRParser.ELEMENT_OPTIONS); if ( options!=null ) { Grammar.setNodeOptions($tree, options); } diff --git a/tool/src/org/antlr/v4/parse/ATNBuilder.g b/tool/src/org/antlr/v4/parse/ATNBuilder.g index a75256ec5..64bd1ad0e 100644 --- a/tool/src/org/antlr/v4/parse/ATNBuilder.g +++ b/tool/src/org/antlr/v4/parse/ATNBuilder.g @@ -95,6 +95,8 @@ element returns [ATNFactory.Handle p] | subrule {$p = $subrule.p;} | ACTION {$p = factory.action((ActionAST)$ACTION);} | SEMPRED {$p = factory.sempred((PredAST)$SEMPRED);} + | ^(ACTION .) {$p = factory.action((ActionAST)$ACTION);} + | ^(SEMPRED .) {$p = factory.sempred((PredAST)$SEMPRED);} | treeSpec {$p = $treeSpec.p;} | ^(ROOT a=astOperand) {$p = $a.p;} | ^(BANG a=astOperand) {$p = $a.p;} diff --git a/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g b/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g index 7ec6d86ed..97d890769 100644 --- a/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g +++ b/tool/src/org/antlr/v4/parse/GrammarTreeVisitor.g @@ -152,10 +152,10 @@ public void discoverSTRewrite(GrammarAST rew) { } public void discoverTreeRewrite(GrammarAST rew) { } public void ruleRef(GrammarAST ref, ActionAST arg) { } -public void tokenRef(TerminalAST ref, GrammarAST options) { } -public void terminalOption(TerminalAST t, GrammarAST ID, GrammarAST value) { } -public void stringRef(TerminalAST ref, GrammarAST options) { } -public void wildcardRef(GrammarAST ref, GrammarAST options) { } +public void tokenRef(TerminalAST ref) { } +public void elementOption(GrammarASTWithOptions t, GrammarAST ID, GrammarAST value) { } +public void stringRef(TerminalAST ref) { } +public void wildcardRef(GrammarAST ref) { } public void actionInAlt(ActionAST action) { } public void sempredInAlt(PredAST pred) { } public void label(GrammarAST op, GrammarAST ID, GrammarAST element) { } @@ -165,9 +165,9 @@ public void bangOp(GrammarAST op, GrammarAST opnd) { } public void discoverRewrites(GrammarAST result) { } public void finishRewrites(GrammarAST result) { } -public void rewriteTokenRef(TerminalAST ast, GrammarAST options, ActionAST arg) { } +public void rewriteTokenRef(TerminalAST ast, ActionAST arg) { } public void rewriteTerminalOption(TerminalAST t, GrammarAST ID, GrammarAST value) { } -public void rewriteStringRef(TerminalAST ast, GrammarAST options) { } +public void rewriteStringRef(TerminalAST ast) { } public void rewriteRuleRef(GrammarAST ast) { } public void rewriteLabelRef(GrammarAST ast) { } public void rewriteAction(ActionAST ast) { } @@ -224,6 +224,7 @@ optionValue returns [String v] @init {$v = $start.token.getText();} : ID | STRING_LITERAL + | DOUBLE_QUOTE_STRING_LITERAL | INT | STAR ; @@ -352,11 +353,14 @@ element : labeledElement | atom | subrule - | ACTION {actionInAlt((ActionAST)$ACTION);} - | SEMPRED {sempredInAlt((PredAST)$SEMPRED);} + | ACTION {actionInAlt((ActionAST)$ACTION);} + | SEMPRED {sempredInAlt((PredAST)$SEMPRED);} + | ^(ACTION elementOptions) {actionInAlt((ActionAST)$ACTION);} + | ^(SEMPRED elementOptions) {sempredInAlt((PredAST)$SEMPRED);} + | treeSpec - | ^(ROOT astOperand) {rootOp($ROOT, $astOperand.start);} - | ^(BANG astOperand) {bangOp($BANG, $astOperand.start);} + | ^(ROOT astOperand) {rootOp($ROOT, $astOperand.start);} + | ^(BANG astOperand) {bangOp($BANG, $astOperand.start);} | ^(NOT blockSet) | ^(NOT block) | DOWN_TOKEN @@ -398,8 +402,8 @@ ebnfSuffix atom: range | ^(DOT ID terminal) | ^(DOT ID ruleref) - | ^(WILDCARD elementOptions) {wildcardRef($WILDCARD, $elementOptions.start);} - | WILDCARD {wildcardRef($WILDCARD, null);} + | ^(WILDCARD elementOptions) {wildcardRef($WILDCARD);} + | WILDCARD {wildcardRef($WILDCARD);} | terminal | blockSet | ruleref @@ -410,12 +414,12 @@ blockSet ; setElement - : STRING_LITERAL {stringRef((TerminalAST)$STRING_LITERAL, null);} - | TOKEN_REF {tokenRef((TerminalAST)$TOKEN_REF, null);} + : STRING_LITERAL {stringRef((TerminalAST)$STRING_LITERAL);} + | TOKEN_REF {tokenRef((TerminalAST)$TOKEN_REF);} | ^(RANGE a=STRING_LITERAL b=STRING_LITERAL) { - stringRef((TerminalAST)$a, null); - stringRef((TerminalAST)$b, null); + stringRef((TerminalAST)$a); + stringRef((TerminalAST)$b); } ; @@ -437,20 +441,21 @@ range terminal : ^(STRING_LITERAL elementOptions) - {stringRef((TerminalAST)$STRING_LITERAL, $elementOptions.start);} - | STRING_LITERAL {stringRef((TerminalAST)$STRING_LITERAL, null);} - | ^(TOKEN_REF elementOptions) {tokenRef((TerminalAST)$TOKEN_REF, $elementOptions.start);} - | TOKEN_REF {tokenRef((TerminalAST)$TOKEN_REF, null);} + {stringRef((TerminalAST)$STRING_LITERAL);} + | STRING_LITERAL {stringRef((TerminalAST)$STRING_LITERAL);} + | ^(TOKEN_REF elementOptions) {tokenRef((TerminalAST)$TOKEN_REF);} + | TOKEN_REF {tokenRef((TerminalAST)$TOKEN_REF);} ; elementOptions - : ^(ELEMENT_OPTIONS elementOption[(TerminalAST)$start.getParent()]+) + : ^(ELEMENT_OPTIONS elementOption[(GrammarASTWithOptions)$start.getParent()]+) ; -elementOption[TerminalAST t] - : ID {terminalOption(t, $ID, null);} - | ^(ASSIGN id=ID v=ID) {terminalOption(t, $id, $v);} - | ^(ASSIGN ID v=STRING_LITERAL) {terminalOption(t, $ID, $v);} +elementOption[GrammarASTWithOptions t] + : 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=DOUBLE_QUOTE_STRING_LITERAL) {elementOption(t, $ID, $v);} ; rewrite @@ -487,16 +492,16 @@ rewriteTreeElement rewriteTreeAtom : ^(TOKEN_REF rewriteElementOptions ARG_ACTION) - {rewriteTokenRef((TerminalAST)$start,$rewriteElementOptions.start,(ActionAST)$ARG_ACTION);} + {rewriteTokenRef((TerminalAST)$start,(ActionAST)$ARG_ACTION);} | ^(TOKEN_REF rewriteElementOptions) - {rewriteTokenRef((TerminalAST)$start,$rewriteElementOptions.start,null);} + {rewriteTokenRef((TerminalAST)$start,null);} | ^(TOKEN_REF ARG_ACTION) - {rewriteTokenRef((TerminalAST)$start,null,(ActionAST)$ARG_ACTION);} - | TOKEN_REF {rewriteTokenRef((TerminalAST)$start,null,null);} + {rewriteTokenRef((TerminalAST)$start,(ActionAST)$ARG_ACTION);} + | TOKEN_REF {rewriteTokenRef((TerminalAST)$start,null);} | RULE_REF {rewriteRuleRef($start);} | ^(STRING_LITERAL rewriteElementOptions) - {rewriteStringRef((TerminalAST)$start,$rewriteElementOptions.start);} - | STRING_LITERAL {rewriteStringRef((TerminalAST)$start,null);} + {rewriteStringRef((TerminalAST)$start);} + | STRING_LITERAL {rewriteStringRef((TerminalAST)$start);} | LABEL {rewriteLabelRef($start);} | ACTION {rewriteAction((ActionAST)$start);} ; diff --git a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java index 8ef08d401..f87d0e980 100644 --- a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java +++ b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java @@ -31,11 +31,8 @@ package org.antlr.v4.semantics; import org.antlr.runtime.Token; import org.antlr.v4.misc.Utils; -import org.antlr.v4.parse.ANTLRParser; -import org.antlr.v4.parse.GrammarTreeVisitor; -import org.antlr.v4.tool.ErrorManager; -import org.antlr.v4.tool.ErrorType; -import org.antlr.v4.tool.Grammar; +import org.antlr.v4.parse.*; +import org.antlr.v4.tool.*; import org.antlr.v4.tool.ast.*; import org.stringtemplate.v4.misc.MultiMap; @@ -130,6 +127,13 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { } }; + public static final Set legalSemPredOptions = + new HashSet() { + { + add("msg"); + } + }; + /** Set of valid imports. E.g., can only import a tree parser into * another tree parser. Maps delegate to set of delegator grammar types. * validDelegations.get(LEXER) gives list of the kinds of delegators @@ -225,10 +229,10 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { } @Override - public void terminalOption(TerminalAST t, GrammarAST ID, GrammarAST value) { + public void elementOption(GrammarASTWithOptions elem, GrammarAST ID, GrammarAST value) { String v = null; if ( value!=null ) v = value.getText(); - boolean ok = checkTokenOptions(ID, v); + boolean ok = checkElementOptions(elem, ID, v); // if ( ok ) { // if ( v!=null ) { // t.setOption(ID.getText(), v); @@ -268,7 +272,7 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { } @Override - public void wildcardRef(GrammarAST ref, GrammarAST options) { + public void wildcardRef(GrammarAST ref) { checkWildcardRoot(ref); } @@ -400,8 +404,30 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { return ok; } - /** Check option is appropriate for token; parent is ELEMENT_OPTIONS */ - boolean checkTokenOptions(GrammarAST ID, String value) { + /** Check option is appropriate for elem; parent of ID is ELEMENT_OPTIONS */ + boolean checkElementOptions(GrammarASTWithOptions elem, GrammarAST ID, String value) { + if ( elem instanceof TerminalAST ) { + return checkTokenOptions((TerminalAST)elem, ID, value); + } + if ( elem.getType()==ANTLRParser.ACTION ) { + return false; + } + if ( elem.getType()==ANTLRParser.SEMPRED ) { + Token optionID = ID.token; + String fileName = optionID.getInputStream().getSourceName(); + if ( value!=null && !legalSemPredOptions.contains(optionID.getText()) ) { + g.tool.errMgr.grammarError(ErrorType.ILLEGAL_OPTION, + fileName, + optionID, + optionID.getText()); + return false; + } + } + return false; + } + + + boolean checkTokenOptions(TerminalAST elem, GrammarAST ID, String value) { Token optionID = ID.token; String fileName = optionID.getInputStream().getSourceName(); // don't care about ID options diff --git a/tool/src/org/antlr/v4/semantics/RewriteRefs.java b/tool/src/org/antlr/v4/semantics/RewriteRefs.java index bd3e6a75f..5f7d4d7c7 100644 --- a/tool/src/org/antlr/v4/semantics/RewriteRefs.java +++ b/tool/src/org/antlr/v4/semantics/RewriteRefs.java @@ -30,12 +30,9 @@ package org.antlr.v4.semantics; import org.antlr.v4.parse.GrammarTreeVisitor; -import org.antlr.v4.tool.ast.ActionAST; -import org.antlr.v4.tool.ast.GrammarAST; -import org.antlr.v4.tool.ast.TerminalAST; +import org.antlr.v4.tool.ast.*; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class RewriteRefs extends GrammarTreeVisitor { List shallow = new ArrayList(); @@ -52,12 +49,12 @@ public class RewriteRefs extends GrammarTreeVisitor { } @Override - public void rewriteTokenRef(TerminalAST ast, GrammarAST options, ActionAST arg) { + public void rewriteTokenRef(TerminalAST ast, ActionAST arg) { track(ast); } @Override - public void rewriteStringRef(TerminalAST ast, GrammarAST options) { + public void rewriteStringRef(TerminalAST ast) { track(ast); } diff --git a/tool/src/org/antlr/v4/semantics/SymbolCollector.java b/tool/src/org/antlr/v4/semantics/SymbolCollector.java index d759508a2..012ca3e84 100644 --- a/tool/src/org/antlr/v4/semantics/SymbolCollector.java +++ b/tool/src/org/antlr/v4/semantics/SymbolCollector.java @@ -29,18 +29,11 @@ package org.antlr.v4.semantics; -import org.antlr.v4.parse.GrammarTreeVisitor; -import org.antlr.v4.parse.ScopeParser; -import org.antlr.v4.tool.AttributeDict; -import org.antlr.v4.tool.Grammar; -import org.antlr.v4.tool.LabelElementPair; -import org.antlr.v4.tool.Rule; +import org.antlr.v4.parse.*; +import org.antlr.v4.tool.*; import org.antlr.v4.tool.ast.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** Collects (create) rules, terminals, strings, actions, scopes etc... from AST * side-effects: sets resolver field of asts for actions and @@ -178,7 +171,7 @@ public class SymbolCollector extends GrammarTreeVisitor { } @Override - public void stringRef(TerminalAST ref, GrammarAST options) { + public void stringRef(TerminalAST ref) { terminals.add(ref); strings.add(ref.getText()); if ( currentRule!=null ) { @@ -187,7 +180,7 @@ public class SymbolCollector extends GrammarTreeVisitor { } @Override - public void tokenRef(TerminalAST ref, GrammarAST options) { + public void tokenRef(TerminalAST ref) { terminals.add(ref); tokenIDRefs.add(ref); if ( currentRule!=null ) { @@ -211,12 +204,12 @@ public class SymbolCollector extends GrammarTreeVisitor { public void rewriteRuleRef(GrammarAST ast) { rewriteElements.add(ast); } @Override - public void rewriteStringRef(TerminalAST ast, GrammarAST options) { + public void rewriteStringRef(TerminalAST ast) { rewriteElements.add(ast); } @Override - public void rewriteTokenRef(TerminalAST ast, GrammarAST options, ActionAST arg) { + public void rewriteTokenRef(TerminalAST ast, ActionAST arg) { rewriteElements.add(ast); if ( arg!=null ) arg.resolver = currentRule.alt[currentOuterAltNumber]; } diff --git a/tool/src/org/antlr/v4/tool/Grammar.java b/tool/src/org/antlr/v4/tool/Grammar.java index 396eeee14..f14f6bd34 100644 --- a/tool/src/org/antlr/v4/tool/Grammar.java +++ b/tool/src/org/antlr/v4/tool/Grammar.java @@ -29,26 +29,17 @@ package org.antlr.v4.tool; -import org.antlr.runtime.tree.TreeVisitor; -import org.antlr.runtime.tree.TreeVisitorAction; -import org.antlr.runtime.tree.TreeWizard; +import org.antlr.runtime.tree.*; import org.antlr.v4.Tool; -import org.antlr.v4.misc.CharSupport; -import org.antlr.v4.misc.OrderedHashMap; -import org.antlr.v4.parse.ANTLRParser; -import org.antlr.v4.parse.GrammarASTAdaptor; -import org.antlr.v4.parse.GrammarTreeVisitor; -import org.antlr.v4.parse.TokenVocabParser; -import org.antlr.v4.runtime.Lexer; -import org.antlr.v4.runtime.Token; +import org.antlr.v4.misc.*; +import org.antlr.v4.parse.*; +import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.atn.ATN; import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.misc.IntSet; -import org.antlr.v4.runtime.misc.IntervalSet; +import org.antlr.v4.runtime.misc.*; import org.antlr.v4.tool.ast.*; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.util.*; public class Grammar implements AttributeResolver { @@ -756,7 +747,7 @@ public class Grammar implements AttributeResolver { final Set strings = new HashSet(); GrammarTreeVisitor collector = new GrammarTreeVisitor() { @Override - public void stringRef(TerminalAST ref, GrammarAST options) { + public void stringRef(TerminalAST ref) { strings.add(ref.getText()); } }; diff --git a/tool/src/org/antlr/v4/tool/ast/ActionAST.java b/tool/src/org/antlr/v4/tool/ast/ActionAST.java index 47a625942..4e94d3b95 100644 --- a/tool/src/org/antlr/v4/tool/ast/ActionAST.java +++ b/tool/src/org/antlr/v4/tool/ast/ActionAST.java @@ -35,7 +35,7 @@ import org.antlr.v4.tool.AttributeResolver; import java.util.List; -public class ActionAST extends GrammarAST implements RuleElementAST { +public class ActionAST extends GrammarASTWithOptions implements RuleElementAST { // Alt, rule, grammar space public AttributeResolver resolver; public List chunks; // useful for ANTLR IDE developers diff --git a/tool/src/org/antlr/v4/tool/ast/GrammarASTWithOptions.java b/tool/src/org/antlr/v4/tool/ast/GrammarASTWithOptions.java index c039c9a90..1b9850ba5 100644 --- a/tool/src/org/antlr/v4/tool/ast/GrammarASTWithOptions.java +++ b/tool/src/org/antlr/v4/tool/ast/GrammarASTWithOptions.java @@ -30,9 +30,9 @@ package org.antlr.v4.tool.ast; import org.antlr.runtime.Token; +import org.antlr.v4.misc.CharSupport; -import java.util.HashMap; -import java.util.Map; +import java.util.*; public abstract class GrammarASTWithOptions extends GrammarAST { protected Map options; @@ -49,6 +49,9 @@ public abstract class GrammarASTWithOptions extends GrammarAST { public void setOption(String key, String value) { if ( options==null ) options = new HashMap(); + if ( value.startsWith("'") || value.startsWith("\"") ) { + value = CharSupport.getStringFromGrammarStringLiteral(value); + } options.put(key, value); }