diff options
Diffstat (limited to 'tool')
18 files changed, 184 insertions, 53 deletions
diff --git a/tool/pom.xml b/tool/pom.xml index 0ae4fa8..d762947 100644 --- a/tool/pom.xml +++ b/tool/pom.xml @@ -3,7 +3,7 @@ <parent> <groupId>org.antlr</groupId> <artifactId>antlr4-master</artifactId> - <version>4.5.1</version> + <version>4.5.2-1</version> </parent> <artifactId>antlr4</artifactId> <name>ANTLR 4 Tool</name> @@ -98,6 +98,13 @@ <phase>package</phase> <configuration> <dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <manifestEntries> + <Main-Class>org.antlr.v4.Tool</Main-Class> + </manifestEntries> + </transformer> + </transformers> </configuration> <goals> <goal>shade</goal> diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/CSharp/CSharp.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/CSharp/CSharp.stg index 81eb912..0617385 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/CSharp/CSharp.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/CSharp/CSharp.stg @@ -119,13 +119,23 @@ using ParserRuleContext = Antlr4.Runtime.ParserRuleContext; public partial class <file.grammarName>BaseListener : I<file.grammarName>Listener { <file.listenerNames:{lname | /// \<summary> -/// Enter a parse tree produced by \<see cref="<csIdentifier.(file.parserName)>.<csIdentifier.(lname)>"/>. +<if(file.listenerLabelRuleNames.(lname))> +/// Enter a parse tree produced by the \<c><lname>\</c> +/// labeled alternative in \<see cref="<file.parserName>.<file.listenerLabelRuleNames.(lname)>"/>. +<else> +/// Enter a parse tree produced by \<see cref="<file.parserName>.<lname>"/>. +<endif> /// \<para>The default implementation does nothing.\</para> /// \</summary> /// \<param name="context">The parse tree.\</param> public virtual void Enter<lname; format="cap">([NotNull] <csIdentifier.(file.parserName)>.<lname; format="cap">Context context) { \} /// \<summary> -/// Exit a parse tree produced by \<see cref="<csIdentifier.(file.parserName)>.<csIdentifier.(lname)>"/>. +<if(file.listenerLabelRuleNames.(lname))> +/// Exit a parse tree produced by the \<c><lname>\</c> +/// labeled alternative in \<see cref="<file.parserName>.<file.listenerLabelRuleNames.(lname)>"/>. +<else> +/// Exit a parse tree produced by \<see cref="<file.parserName>.<lname>"/>. +<endif> /// \<para>The default implementation does nothing.\</para> /// \</summary> /// \<param name="context">The parse tree.\</param> @@ -207,7 +217,12 @@ using ParserRuleContext = Antlr4.Runtime.ParserRuleContext; public partial class <file.grammarName>BaseVisitor\<Result> : AbstractParseTreeVisitor\<Result>, I<file.grammarName>Visitor\<Result> { <file.visitorNames:{lname | /// \<summary> -/// Visit a parse tree produced by \<see cref="<csIdentifier.(file.parserName)>.<csIdentifier.(lname)>"/>. +<if(file.visitorLabelRuleNames.(lname))> +/// Visit a parse tree produced by the \<c><lname>\</c> +/// labeled alternative in \<see cref="<file.parserName>.<file.visitorLabelRuleNames.(lname)>"/>. +<else> +/// Visit a parse tree produced by \<see cref="<file.parserName>.<lname>"/>. +<endif> /// \<para> /// The default implementation returns the result of calling \<see cref="AbstractParseTreeVisitor{Result\}.VisitChildren(IRuleNode)"/> /// on \<paramref name="context"/>. @@ -241,6 +256,8 @@ fileHeader(grammarFileName, ANTLRVersion) ::= << #pragma warning disable 0219 // Missing XML comment for publicly visible type or member '...' #pragma warning disable 1591 +// Ambiguous reference in cref attribute +#pragma warning disable 419 >> @@ -520,7 +537,6 @@ CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= << LL1AltBlock(choice, preamble, alts, error) ::= << State = <choice.stateNumber>; -<!ErrorHandler.sync(this);!> <if(choice.label)><labelref(choice.label)> = TokenStream.Lt(1);<endif> <preamble; separator="\n"> switch (TokenStream.La(1)) { @@ -534,7 +550,6 @@ default: LL1OptionalBlock(choice, alts, error) ::= << State = <choice.stateNumber>; -<!ErrorHandler.sync(this);!> switch (TokenStream.La(1)) { <choice.altLook,alts:{look,alt| <cases(ttypes=look)> <alt> @@ -546,7 +561,6 @@ default: LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= << State = <choice.stateNumber>; -<!ErrorHandler.sync(this);!> <preamble; separator="\n"> if (<expr>) { <alts; separator="\n"> @@ -582,7 +596,7 @@ do { AltBlock(choice, preamble, alts, error) ::= << State = <choice.stateNumber>; -<!ErrorHandler.sync(this);!> +ErrorHandler.Sync(this); <if(choice.label)><labelref(choice.label)> = TokenStream.Lt(1);<endif> <preamble; separator="\n"> switch ( Interpreter.AdaptivePredict(TokenStream,<choice.decision>,Context) ) { @@ -595,7 +609,7 @@ case <i>: OptionalBlock(choice, alts, error) ::= << State = <choice.stateNumber>; -<!ErrorHandler.sync(this);!> +ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,<choice.decision>,Context) ) { <alts:{alt | case <i><if(!choice.ast.greedy)>+1<endif>: @@ -931,6 +945,7 @@ namespace <file.genPackage> { <endif> <namedActions.header> using System; +using System.Text; using Antlr4.Runtime; using Antlr4.Runtime.Atn; using Antlr4.Runtime.Misc; @@ -986,8 +1001,14 @@ public partial class <csIdentifier.(lexer.name)> : <superClass; null="Lexer"> { SerializedATN(model) ::= << -public static readonly string _serializedATN = - "<model.serialized; wrap={"+<\n><\t>"}>"; +private static string _serializedATN = _serializeATN(); +private static string _serializeATN() +{ + StringBuilder sb = new StringBuilder(); + sb.Append("<model.serialized; wrap={");<\n><\t>sb.Append("}>"); + return sb.ToString(); +} + public static readonly ATN _ATN = new ATNDeserializer().Deserialize(_serializedATN.ToCharArray()); >> 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 5bec6c5..8bd429a 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 @@ -469,7 +469,6 @@ CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= << LL1AltBlock(choice, preamble, alts, error) ::= << setState(<choice.stateNumber>); -<!_errHandler.sync(this);!> <if(choice.label)><labelref(choice.label)> = _input.LT(1);<endif> <preamble; separator="\n"> switch (_input.LA(1)) { @@ -483,7 +482,6 @@ default: LL1OptionalBlock(choice, alts, error) ::= << setState(<choice.stateNumber>); -<!_errHandler.sync(this);!> switch (_input.LA(1)) { <choice.altLook,alts:{look,alt| <cases(ttypes=look)> <alt> @@ -495,7 +493,6 @@ default: LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= << setState(<choice.stateNumber>); -<!_errHandler.sync(this);!> <preamble; separator="\n"> if (<expr>) { <alts; separator="\n"> @@ -531,7 +528,7 @@ do { AltBlock(choice, preamble, alts, error) ::= << setState(<choice.stateNumber>); -<!_errHandler.sync(this);!> +_errHandler.sync(this); <if(choice.label)><labelref(choice.label)> = _input.LT(1);<endif> <preamble; separator="\n"> switch ( getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx) ) { @@ -544,7 +541,7 @@ case <i>: OptionalBlock(choice, alts, error) ::= << setState(<choice.stateNumber>); -<!_errHandler.sync(this);!> +_errHandler.sync(this); switch ( getInterpreter().adaptivePredict(_input,<choice.decision>,_ctx) ) { <alts:{alt | case <i><if(!choice.ast.greedy)>+1<endif>: diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/JavaScript/JavaScript.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/JavaScript/JavaScript.stg index a9cfef1..b015c0b 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/JavaScript/JavaScript.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/JavaScript/JavaScript.stg @@ -134,9 +134,9 @@ var decisionsToDFA = atn.decisionToState.map( function(ds, index) { return new a var sharedContextCache = new antlr4.PredictionContextCache(); -var literalNames = [ <parser.literalNames:{t | <t>}; null="'null'", separator=", ", wrap, anchor> ]; +var literalNames = [ <parser.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ]; -var symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="'null'", separator=", ", wrap, anchor> ]; +var symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ]; var ruleNames = [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ]; @@ -340,7 +340,6 @@ CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= << LL1AltBlock(choice, preamble, alts, error) ::= << this.state = <choice.stateNumber>; -<!_errHandler.sync(this);!> <if(choice.label)><labelref(choice.label)> = this._input.LT(1);<endif> <preamble; separator="\n"> switch(this._input.LA(1)) { @@ -354,7 +353,6 @@ default: LL1OptionalBlock(choice, alts, error) ::= << this.state = <choice.stateNumber>; -<!_errHandler.sync(this);!> switch (this._input.LA(1)) { <choice.altLook,alts:{look,alt| <cases(ttypes=look)> <alt> @@ -366,7 +364,6 @@ default: LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= << this.state = <choice.stateNumber>; -<!_errHandler.sync(this);!> <preamble; separator="\n"> if(<expr>) { <alts; separator="\n"> @@ -402,7 +399,7 @@ do { AltBlock(choice, preamble, alts, error) ::= << this.state = <choice.stateNumber>; -<!_errHandler.sync(this);!> +this._errHandler.sync(this); <if(choice.label)><labelref(choice.label)> = _input.LT(1)<endif> <preamble; separator="\n"> var la_ = this._interp.adaptivePredict(this._input,<choice.decision>,this._ctx); @@ -417,7 +414,7 @@ case <i>: OptionalBlock(choice, alts, error) ::= << this.state = <choice.stateNumber>; -<!_errHandler.sync(this);!> +this._errHandler.sync(this); var la_ = this._interp.adaptivePredict(this._input,<choice.decision>,this._ctx); <alts:{alt | if(la_===<i><if(!choice.ast.greedy)>+1<endif>) { @@ -825,9 +822,9 @@ function <lexer.name>(input) { <lexer.name>.modeNames = [ <lexer.modes:{m| "<m>"}; separator=", ", wrap, anchor> ]; -<lexer.name>.literalNames = [ <lexer.literalNames:{t | <t>}; null="'null'", separator=", ", wrap, anchor> ]; +<lexer.name>.literalNames = [ <lexer.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ]; -<lexer.name>.symbolicNames = [ <lexer.symbolicNames:{t | <t>}; null="'null'", separator=", ", wrap, anchor> ]; +<lexer.name>.symbolicNames = [ <lexer.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ]; <lexer.name>.ruleNames = [ <lexer.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ]; diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Python2/Python2.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Python2/Python2.stg index b4e66eb..66d84e6 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Python2/Python2.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Python2/Python2.stg @@ -314,7 +314,6 @@ CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= << LL1AltBlock(choice, preamble, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> <if(choice.label)><labelref(choice.label)> = _input.LT(1)<endif> <preamble; separator="\n"> token = self._input.LA(1) @@ -328,7 +327,6 @@ else: LL1OptionalBlock(choice, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> token = self._input.LA(1) <choice.altLook,alts:{look,alt| <cases(ttypes=look)> <alt> @@ -339,7 +337,6 @@ else: LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> <preamble; separator="\n"> if <expr>: <alts; separator="\n"> @@ -378,7 +375,7 @@ while True: AltBlock(choice, preamble, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> +self._errHandler.sync(self); <if(choice.label)><labelref(choice.label)> = _input.LT(1)<endif> <preamble; separator="\n"> la_ = self._interp.adaptivePredict(self._input,<choice.decision>,self._ctx) @@ -392,7 +389,7 @@ if la_ == <i>: OptionalBlock(choice, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> +self._errHandler.sync(self); la_ = self._interp.adaptivePredict(self._input,<choice.decision>,self._ctx) <alts:{alt | if la_ == <i><if(!choice.ast.greedy)>+1<endif>: diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Python3/Python3.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Python3/Python3.stg index 4ba1e38..515cf65 100644 --- a/tool/resources/org/antlr/v4/tool/templates/codegen/Python3/Python3.stg +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Python3/Python3.stg @@ -322,7 +322,6 @@ CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= << LL1AltBlock(choice, preamble, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> <if(choice.label)><labelref(choice.label)> = _input.LT(1)<endif> <preamble; separator="\n"> token = self._input.LA(1) @@ -336,7 +335,6 @@ else: LL1OptionalBlock(choice, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> token = self._input.LA(1) <choice.altLook,alts:{look,alt| <cases(ttypes=look)> <alt> @@ -347,7 +345,6 @@ else: LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> <preamble; separator="\n"> if <expr>: <alts; separator="\n"> @@ -386,7 +383,7 @@ while True: AltBlock(choice, preamble, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> +self._errHandler.sync(self); <if(choice.label)><labelref(choice.label)> = _input.LT(1)<endif> <preamble; separator="\n"> la_ = self._interp.adaptivePredict(self._input,<choice.decision>,self._ctx) @@ -400,7 +397,7 @@ if la_ == <i>: OptionalBlock(choice, alts, error) ::= << self.state = <choice.stateNumber> -<!_errHandler.sync(this);!> +self._errHandler.sync(self); la_ = self._interp.adaptivePredict(self._input,<choice.decision>,self._ctx) <alts:{alt | if la_ == <i><if(!choice.ast.greedy)>+1<endif>: diff --git a/tool/src/org/antlr/v4/automata/LexerATNFactory.java b/tool/src/org/antlr/v4/automata/LexerATNFactory.java index 4feff0a..a5e80e4 100644 --- a/tool/src/org/antlr/v4/automata/LexerATNFactory.java +++ b/tool/src/org/antlr/v4/automata/LexerATNFactory.java @@ -83,7 +83,7 @@ public class LexerATNFactory extends ParserATNFactory { * actions, but are required during code generation for creating * {@link LexerAction} instances that are usable by a lexer interpreter. */ - protected static final Map<String, Integer> COMMON_CONSTANTS = new HashMap<String, Integer>(); + public static final Map<String, Integer> COMMON_CONSTANTS = new HashMap<String, Integer>(); static { COMMON_CONSTANTS.put("HIDDEN", Lexer.HIDDEN); COMMON_CONSTANTS.put("DEFAULT_TOKEN_CHANNEL", Lexer.DEFAULT_TOKEN_CHANNEL); @@ -112,6 +112,10 @@ public class LexerATNFactory extends ParserATNFactory { codegenTemplates = gen.getTemplates(); } + public static Set<String> getCommonConstants() { + return COMMON_CONSTANTS.keySet(); + } + @Override public ATN createATN() { // BUILD ALL START STATES (ONE PER MODE) @@ -243,8 +247,8 @@ public class LexerATNFactory extends ParserATNFactory { // fall back to standard action generation for the command ST cmdST = codegenTemplates.getInstanceOf("Lexer" + - CharSupport.capitalize(ID.getText())+ - "Command"); + CharSupport.capitalize(ID.getText()) + + "Command"); if (cmdST == null) { g.tool.errMgr.grammarError(ErrorType.INVALID_LEXER_COMMAND, g.fileName, ID.token, ID.getText()); return epsilon(ID); @@ -407,6 +411,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("mode".equals(command) && arg != null) { String modeName = arg.getText(); + checkMode(modeName, arg.token); Integer mode = getConstantValue(modeName, arg.getToken()); if (mode == null) { return null; @@ -416,6 +421,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("pushMode".equals(command) && arg != null) { String modeName = arg.getText(); + checkMode(modeName, arg.token); Integer mode = getConstantValue(modeName, arg.getToken()); if (mode == null) { return null; @@ -425,6 +431,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("type".equals(command) && arg != null) { String typeName = arg.getText(); + checkToken(typeName, arg.token); Integer type = getConstantValue(typeName, arg.getToken()); if (type == null) { return null; @@ -434,6 +441,7 @@ public class LexerATNFactory extends ParserATNFactory { } else if ("channel".equals(command) && arg != null) { String channelName = arg.getText(); + checkChannel(channelName, arg.token); Integer channel = getConstantValue(channelName, arg.getToken()); if (channel == null) { return null; @@ -446,6 +454,23 @@ public class LexerATNFactory extends ParserATNFactory { } } + protected void checkMode(String modeName, Token token) { + if (!modeName.equals("DEFAULT_MODE") && COMMON_CONSTANTS.containsKey(modeName)) { + g.tool.errMgr.grammarError(ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, token, token.getText()); + } + } + + protected void checkToken(String tokenName, Token token) { + if (!tokenName.equals("EOF") && COMMON_CONSTANTS.containsKey(tokenName)) { + g.tool.errMgr.grammarError(ErrorType.TOKEN_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, token, token.getText()); + } + } + + protected void checkChannel(String channelName, Token token) { + if (!channelName.equals("HIDDEN") && !channelName.equals("DEFAULT_TOKEN_CHANNEL") && COMMON_CONSTANTS.containsKey(channelName)) { + g.tool.errMgr.grammarError(ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, token, token.getText()); + } + } protected Integer getConstantValue(String name, Token token) { if (name == null) { diff --git a/tool/src/org/antlr/v4/codegen/ActionTranslator.java b/tool/src/org/antlr/v4/codegen/ActionTranslator.java index 2a12e8e..f1e5452 100644 --- a/tool/src/org/antlr/v4/codegen/ActionTranslator.java +++ b/tool/src/org/antlr/v4/codegen/ActionTranslator.java @@ -158,8 +158,10 @@ public class ActionTranslator implements ActionSplitterListener { translator.rf = rf; factory.getGrammar().tool.log("action-translator", "translate " + action); String altLabel = node.getAltLabel(); - if ( rf!=null ) translator.nodeContext = rf.ruleCtx; - if ( altLabel!=null ) translator.nodeContext = rf.altLabelCtxs.get(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()); diff --git a/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java b/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java index 09df962..bfebe4b 100644 --- a/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/CSharpTarget.java @@ -51,7 +51,7 @@ public class CSharpTarget extends Target { @Override public String getVersion() { - return "4.5.1"; // crossing fingers that it's close enough. + return "4.5.2"; // crossing fingers that it's close enough. } @Override diff --git a/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java b/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java index 26fa4fe..71926ac 100644 --- a/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java +++ b/tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java @@ -74,7 +74,7 @@ public class JavaScriptTarget extends Target { @Override public String getVersion() { - return "4.5.1"; + return "4.5.2"; } public Set<String> getBadWords() { diff --git a/tool/src/org/antlr/v4/codegen/target/Python2Target.java b/tool/src/org/antlr/v4/codegen/target/Python2Target.java index 36249d5..efa5d2c 100644 --- a/tool/src/org/antlr/v4/codegen/target/Python2Target.java +++ b/tool/src/org/antlr/v4/codegen/target/Python2Target.java @@ -117,7 +117,7 @@ public class Python2Target extends Target { @Override public String getVersion() { - return "4.5.2"; + return "4.5.2.1"; } public Set<String> getBadWords() { diff --git a/tool/src/org/antlr/v4/codegen/target/Python3Target.java b/tool/src/org/antlr/v4/codegen/target/Python3Target.java index d07247f..68d7a16 100644 --- a/tool/src/org/antlr/v4/codegen/target/Python3Target.java +++ b/tool/src/org/antlr/v4/codegen/target/Python3Target.java @@ -119,7 +119,7 @@ public class Python3Target extends Target { @Override public String getVersion() { - return "4.5.2"; + return "4.5.2.1"; } /** Avoid grammar symbols in this set to prevent conflicts in gen'd code. */ diff --git a/tool/src/org/antlr/v4/gui/TestRig.java b/tool/src/org/antlr/v4/gui/TestRig.java index 4812e5c..e81a54c 100644 --- a/tool/src/org/antlr/v4/gui/TestRig.java +++ b/tool/src/org/antlr/v4/gui/TestRig.java @@ -80,7 +80,7 @@ public class TestRig { public TestRig(String[] args) throws Exception { if ( args.length < 2 ) { - System.err.println("java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName\n" + + System.err.println("java org.antlr.v4.gui.TestRig GrammarName startRuleName\n" + " [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]\n" + " [-trace] [-diagnostics] [-SLL]\n"+ " [input-filename(s)]"); @@ -172,9 +172,6 @@ public class TestRig { if ( !startRuleName.equals(LEXER_START_RULE_NAME) ) { String parserName = grammarName+"Parser"; parserClass = cl.loadClass(parserName).asSubclass(Parser.class); - if ( parserClass==null ) { - System.err.println("Can't load "+parserName); - } Constructor<? extends Parser> parserCtor = parserClass.getConstructor(TokenStream.class); parser = parserCtor.newInstance((TokenStream)null); } diff --git a/tool/src/org/antlr/v4/gui/TreeViewer.java b/tool/src/org/antlr/v4/gui/TreeViewer.java index 0ca15f3..3cfd5e5 100644 --- a/tool/src/org/antlr/v4/gui/TreeViewer.java +++ b/tool/src/org/antlr/v4/gui/TreeViewer.java @@ -372,10 +372,12 @@ public class TreeViewer extends JComponent { JTree selectedTree = (JTree) e.getSource(); TreePath path = selectedTree.getSelectionPath(); - TreeNodeWrapper treeNode = (TreeNodeWrapper) path.getLastPathComponent(); + if (path!=null) { + TreeNodeWrapper treeNode = (TreeNodeWrapper) path.getLastPathComponent(); - // Set the clicked AST. - viewer.setTree((Tree) treeNode.getUserObject()); + // Set the clicked AST. + viewer.setTree((Tree) treeNode.getUserObject()); + } } }); diff --git a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java index a578a66..4853c37 100644 --- a/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java +++ b/tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java @@ -349,7 +349,7 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { GrammarAST root = (GrammarAST)rulesNode.getParent(); GrammarAST IDNode = (GrammarAST)root.getChild(0); g.tool.errMgr.grammarError(ErrorType.NO_RULES, g.fileName, - null, IDNode.getText(), g); + null, IDNode.getText(), g); } } @@ -491,6 +491,14 @@ public class BasicSemanticChecks extends GrammarTreeVisitor { label.getText()); } + @Override + protected void enterTerminal(GrammarAST tree) { + String text = tree.getText(); + if (text.equals("''")) { + g.tool.errMgr.grammarError(ErrorType.EMPTY_STRINGS_NOT_ALLOWED, g.fileName, tree.token); + } + } + /** Check option is appropriate for grammar, rule, subrule */ boolean checkOptions(GrammarAST parent, Token optionID, diff --git a/tool/src/org/antlr/v4/semantics/SemanticPipeline.java b/tool/src/org/antlr/v4/semantics/SemanticPipeline.java index 3561f91..ada4324 100644 --- a/tool/src/org/antlr/v4/semantics/SemanticPipeline.java +++ b/tool/src/org/antlr/v4/semantics/SemanticPipeline.java @@ -31,6 +31,7 @@ package org.antlr.v4.semantics; import org.antlr.v4.analysis.LeftRecursiveRuleTransformer; +import org.antlr.v4.automata.LexerATNFactory; import org.antlr.v4.parse.ANTLRParser; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.misc.Pair; @@ -128,6 +129,8 @@ public class SemanticPipeline { collector.tokenIDRefs, collector.terminals); } + symcheck.checkForModeConflicts(g); + assignChannelTypes(g, collector.channelDefs); // CHECK RULE REFS NOW (that we've defined rules in grammar) @@ -287,6 +290,10 @@ public class SemanticPipeline { g.tool.errMgr.grammarError(ErrorType.CHANNEL_CONFLICTS_WITH_TOKEN, g.fileName, channel.token, channelName); } + if (LexerATNFactory.COMMON_CONSTANTS.containsKey(channelName)) { + g.tool.errMgr.grammarError(ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, channel.token, channelName); + } + if (outermost instanceof LexerGrammar) { LexerGrammar lexerGrammar = (LexerGrammar)outermost; if (lexerGrammar.modes.containsKey(channelName)) { diff --git a/tool/src/org/antlr/v4/semantics/SymbolChecks.java b/tool/src/org/antlr/v4/semantics/SymbolChecks.java index b280f40..999d9f0 100644 --- a/tool/src/org/antlr/v4/semantics/SymbolChecks.java +++ b/tool/src/org/antlr/v4/semantics/SymbolChecks.java @@ -30,7 +30,9 @@ package org.antlr.v4.semantics; +import org.antlr.v4.automata.LexerATNFactory; import org.antlr.v4.parse.ANTLRParser; +import org.antlr.v4.runtime.Token; import org.antlr.v4.tool.Alternative; import org.antlr.v4.tool.Attribute; import org.antlr.v4.tool.AttributeDict; @@ -38,6 +40,7 @@ import org.antlr.v4.tool.ErrorManager; import org.antlr.v4.tool.ErrorType; import org.antlr.v4.tool.Grammar; import org.antlr.v4.tool.LabelElementPair; +import org.antlr.v4.tool.LexerGrammar; import org.antlr.v4.tool.Rule; import org.antlr.v4.tool.ast.GrammarAST; @@ -67,7 +70,7 @@ public class SymbolChecks { protected final Set<String> reservedNames = new HashSet<String>(); { - reservedNames.add("EOF"); + reservedNames.addAll(LexerATNFactory.getCommonConstants()); } public SymbolChecks(Grammar g, SymbolCollector collector) { @@ -269,6 +272,23 @@ public class SymbolChecks { } } + public void checkForModeConflicts(Grammar g) { + if (g.isLexer()) { + LexerGrammar lexerGrammar = (LexerGrammar)g; + for (String modeName : lexerGrammar.modes.keySet()) { + if (!modeName.equals("DEFAULT_MODE") && reservedNames.contains(modeName)) { + Rule rule = lexerGrammar.modes.get(modeName).iterator().next(); + g.tool.errMgr.grammarError(ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS, g.fileName, rule.ast.parent.getToken(), modeName); + } + + if (g.getTokenType(modeName) != Token.INVALID_TYPE) { + Rule rule = lexerGrammar.modes.get(modeName).iterator().next(); + g.tool.errMgr.grammarError(ErrorType.MODE_CONFLICTS_WITH_TOKEN, g.fileName, rule.ast.parent.getToken(), modeName); + } + } + } + } + // CAN ONLY CALL THE TWO NEXT METHODS AFTER GRAMMAR HAS RULE DEFS (see semanticpipeline) public void checkRuleArgs(Grammar g, List<GrammarAST> rulerefs) { diff --git a/tool/src/org/antlr/v4/tool/ErrorType.java b/tool/src/org/antlr/v4/tool/ErrorType.java index 4868931..0fedfc4 100644 --- a/tool/src/org/antlr/v4/tool/ErrorType.java +++ b/tool/src/org/antlr/v4/tool/ErrorType.java @@ -957,6 +957,60 @@ public enum ErrorType { CHANNELS_BLOCK_IN_COMBINED_GRAMMAR(164, "custom channels are not supported in combined grammars", ErrorSeverity.ERROR), NONCONFORMING_LR_RULE(169, "rule <arg> is left recursive but doesn't conform to a pattern ANTLR can handle", ErrorSeverity.ERROR), + /** + * Compiler Error 170. + * + * <pre> + * mode M1; + * A1: 'a'; // ok + * mode M2; + * A2: 'a'; // ok + * M1: 'b'; // error 170 + * </pre> + * + * <p>mode <em>name</em> conflicts with token with same name</p> + */ + MODE_CONFLICTS_WITH_TOKEN(170, "mode <arg> conflicts with token with same name", ErrorSeverity.ERROR), + /** + * Compiler Error 171. + * + * <p>can not use or declare token with reserved name</p> + * + * <p>Reserved names: HIDDEN, DEFAULT_TOKEN_CHANNEL, SKIP, MORE, MAX_CHAR_VALUE, MIN_CHAR_VALUE. + * + * <p>Can be used but cannot be declared: EOF</p> + */ + TOKEN_CONFLICTS_WITH_COMMON_CONSTANTS(171, "cannot use or declare token with reserved name <arg>", ErrorSeverity.ERROR), + /** + * Compiler Error 172. + * + * <p>can not use or declare channel with reserved name</p> + * + * <p>Reserved names: DEFAULT_MODE, SKIP, MORE, EOF, MAX_CHAR_VALUE, MIN_CHAR_VALUE. + * + * <p>Can be used but cannot be declared: HIDDEN, DEFAULT_TOKEN_CHANNEL</p> + */ + CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS(172, "cannot use or declare channel with reserved name <arg>", ErrorSeverity.ERROR), + /** + * Compiler Error 173. + * + * <p>can not use or declare mode with reserved name</p> + * + * <p>Reserved names: HIDDEN, DEFAULT_TOKEN_CHANNEL, SKIP, MORE, MAX_CHAR_VALUE, MIN_CHAR_VALUE. + * + * <p>Can be used and cannot declared: DEFAULT_MODE</p> + */ + MODE_CONFLICTS_WITH_COMMON_CONSTANTS(173, "cannot use or declare mode with reserved name <arg>", ErrorSeverity.ERROR), + /** + * Compiler Error 174. + * + * <p>empty strings not allowed</p> + * + * <pre>A: '''test''';</pre> + * <pre>B: '';</pre> + * <pre>C: 'test' '';</pre> + */ + EMPTY_STRINGS_NOT_ALLOWED(174, "string literals cannot be empty", ErrorSeverity.ERROR), /* * Backward incompatibility errors |