diff options
author | Emmanuel Bourg <ebourg@apache.org> | 2016-03-22 17:34:38 +0100 |
---|---|---|
committer | Emmanuel Bourg <ebourg@apache.org> | 2016-03-22 17:34:38 +0100 |
commit | f1e1398c68195f255332e40060950fbc3dc3985a (patch) | |
tree | 0a9da5c8d6048e763b0d3814f38dbdbef7854fdb | |
parent | 8f26ca6983190b53e7667d2cbf5344de1d87d51c (diff) | |
parent | 1a7b7906cbb3c334e0e8fe1dfdb68f16fefa8555 (diff) |
Merge tag 'upstream/4.5.2'
Upstream version 4.5.2
33 files changed, 337 insertions, 120 deletions
@@ -2,6 +2,8 @@ **ANTLR** (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files. It's widely used to build languages, tools, and frameworks. From a grammar, ANTLR generates a parser that can build parse trees and also generates a listener interface (or visitor) that makes it easy to respond to the recognition of phrases of interest. +*Given day-job constraints, my time working on this project is limited so I'll have to focus first on fixing bugs rather than changing/improving the feature set. Likely I'll do it in bursts every few months. Please do not be offended if your bug or pull request does not yield a response! --parrt* + ## Authors and major contributors * [Terence Parr](http://www.cs.usfca.edu/~parrt/), parrt@cs.usfca.edu @@ -13,18 +15,18 @@ ANTLR project lead and supreme dictator for life ## Useful information * [Release notes](https://github.com/antlr/antlr4/releases) -* [Getting started with v4](https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Getting+Started+with+ANTLR+v4) +* [Getting started with v4](https://raw.githubusercontent.com/antlr/antlr4/master/doc/getting-started.md) * [Official site](http://www.antlr.org/) -* [Documentation](https://theantlrguy.atlassian.net/wiki/display/ANTLR4/ANTLR+4+Documentation) -* [FAQ](https://theantlrguy.atlassian.net/wiki/display/ANTLR4/ANTLR+v4+FAQ) +* [Documentation](https://raw.githubusercontent.com/antlr/antlr4/master/doc/index.md) +* [FAQ](https://raw.githubusercontent.com/antlr/antlr4/master/doc/faq/index.md) * [API](http://www.antlr.org/api/Java/index.html) * [ANTLR v3](http://www.antlr3.org/) -* [v3 to v4 Migration guide, differences](https://theantlrguy.atlassian.net/wiki/pages/viewpage.action?pageId=1900596) +* [v3 to v4 Migration, differences](https://raw.githubusercontent.com/antlr/antlr4/master/doc/faq/general.md) -You might also find the following wiki pages useful, particularly if you want to mess around with the various target languages. +You might also find the following pages useful, particularly if you want to mess around with the various target languages. -* [How to build ANTLR itself](https://github.com/antlr/antlr4/wiki/How-to-build-ANTLR-itself) -* [How we create and deploy an ANTLR release](https://github.com/antlr/antlr4/wiki/Cutting-an-ANTLR-4-release) +* [How to build ANTLR itself](https://raw.githubusercontent.com/antlr/antlr4/master/doc/building-antlr.md) +* [How we create and deploy an ANTLR release](https://raw.githubusercontent.com/antlr/antlr4/master/doc/releasing-antlr.md) ## The Definitive ANTLR 4 Reference @@ -34,8 +36,12 @@ You can buy the book [The Definitive ANTLR 4 Reference](http://amzn.com/19343569 You will find the [Book source code](http://pragprog.com/titles/tpantlr2/source_code) useful. - ## Additional grammars [This repository](https://github.com/antlr/grammars-v4) is a collection of grammars without actions where the root directory name is the all-lowercase name of the language parsed by the grammar. For example, java, cpp, csharp, c, etc... + +Travis Status +--------- + +<a href="https://travis-ci.org/antlr/antlr4"><img src="https://api.travis-ci.org/antlr/antlr4.png"></a> diff --git a/antlr4-maven-plugin/pom.xml b/antlr4-maven-plugin/pom.xml index 88ce4bf..c525628 100644 --- a/antlr4-maven-plugin/pom.xml +++ b/antlr4-maven-plugin/pom.xml @@ -34,7 +34,7 @@ <parent> <groupId>org.antlr</groupId> <artifactId>antlr4-master</artifactId> - <version>4.5.1</version> + <version>4.5.2-1</version> </parent> <artifactId>antlr4-maven-plugin</artifactId> <packaging>maven-plugin</packaging> diff --git a/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java b/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java index e7eb2d8..d8712ee 100644 --- a/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java +++ b/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java @@ -372,6 +372,22 @@ public class Antlr4Mojo extends AbstractMojo { scan.addSourceMapping(mapping); Set<File> grammarFiles = scan.getIncludedSources(sourceDirectory, null); + // We don't want the plugin to run for every grammar, regardless of whether + // it's changed since the last compilation. Check the mtime of the tokens vs + // the grammar file mtime to determine whether we even need to execute. + Set<File> grammarFilesToProcess = new HashSet<File>(); + + for (File grammarFile : grammarFiles) { + String tokensFileName = grammarFile.getName().split("\\.")[0] + ".tokens"; + File outputFile = new File(outputDirectory, tokensFileName); + if ( (! outputFile.exists()) || + outputFile.lastModified() < grammarFile.lastModified() ) { + grammarFilesToProcess.add(grammarFile); + } + } + + grammarFiles = grammarFilesToProcess; + if (grammarFiles.isEmpty()) { getLog().info("No grammars to process"); return Collections.emptyList(); diff --git a/contributors.txt b/contributors.txt index 75e3b8b..7d3b44a 100644 --- a/contributors.txt +++ b/contributors.txt @@ -74,4 +74,17 @@ YYYY/MM/DD, github id, Full name, email 2015/05/12, Pursuit92, Josh Chase, jcjoshuachase@gmail.com 2015/05/20, peturingi, Pétur Ingi Egilsson, petur@petur.eu 2015/05/27, jcbrinfo, Jean-Christophe Beaupré, jcbrinfo@users.noreply.github.com -2015/06/29, jvanzyl, Jason van Zyl, jason@takari.io
\ No newline at end of file +2015/06/29, jvanzyl, Jason van Zyl, jason@takari.io +2015/08/18, krzkaczor, Krzysztof Kaczor, krzysztof@kaczor.io +2015/09/18, worsht, Rajiv Subrahmanyam, rajiv.public@gmail.com +2015/09/24, HSorensen, Henrik Sorensen, henrik.b.sorensen@gmail.com +2015/10/06, brwml, Bryan Wilhelm, bryan.wilhelm@microsoft.com +2015/10/08, fedotovalex, Alex Fedotov, me@alexfedotov.com +2015/10/12, KvanTTT, Ivan Kochurkin, ivan.kochurkin@gmail.com +2015/10/21, martin-probst, Martin Probst, martin-probst@web.de +2015/10/21, hkff, Walid Benghabrit, walid.benghabrit@mines-nantes.fr +2015/11/12, cooperra, Robbie Cooper, cooperra@users.noreply.github.com +2015/11/25, abego, Udo Borkowski, ub@abego.org +2015/12/17, sebadur, Sebastian Badur, sebadur@users.noreply.github.com +2015/12/23, pboyer, Peter Boyer, peter.b.boyer@gmail.com +2015/12/24, dtymon, David Tymon, david.tymon@gmail.com @@ -7,7 +7,7 @@ </parent> <groupId>org.antlr</groupId> <artifactId>antlr4-master</artifactId> - <version>4.5.1</version> + <version>4.5.2-1</version> <packaging>pom</packaging> <name>ANTLR 4</name> @@ -118,9 +118,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> - <configuration> - <additionalparam>-Xdoclint:none</additionalparam> - </configuration> </plugin> </plugins> </pluginManagement> diff --git a/runtime-testsuite/pom.xml b/runtime-testsuite/pom.xml index 0d29b7e..08cdde4 100644 --- a/runtime-testsuite/pom.xml +++ b/runtime-testsuite/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>org.antlr</groupId> <artifactId>antlr4-master</artifactId> - <version>4.5.1</version> + <version>4.5.2-1</version> </parent> <artifactId>antlr4-runtime-testsuite</artifactId> <name>ANTLR 4 Runtime Test Generator</name> @@ -41,7 +41,7 @@ <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> - <version>2.44.0</version> + <version>2.46.0</version> <scope>test</scope> </dependency> <dependency> @@ -67,15 +67,21 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> + <version>2.12.4</version> <configuration> <includes> + <include>**/csharp/Test*.java</include> <include>**/java/Test*.java</include> + <include>**/javascript/node/Test*.java</include> + <include>**/python2/Test*.java</include> + <include>**/python3/Test*.java</include> </includes> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> <executions> <execution> <goals> @@ -106,8 +112,8 @@ <mainClass>org.antlr.v4.testgen.TestGenerator</mainClass> <arguments> <argument>-root</argument> - <argument>${basedir}/resources</argument> - <argument>-o</argument> + <argument>${basedir}</argument> + <argument>-outdir</argument> <argument>${basedir}/test</argument> <argument>-templates</argument> <argument>${basedir}/resources/org/antlr/v4/test/runtime/templates</argument> diff --git a/runtime/Java/pom.xml b/runtime/Java/pom.xml index 7a59f7f..0a76da0 100644 --- a/runtime/Java/pom.xml +++ b/runtime/Java/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> <relativePath>../../pom.xml</relativePath> </parent> <artifactId>antlr4-runtime</artifactId> diff --git a/runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java b/runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java index bf67cf0..aa1375e 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java +++ b/runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java @@ -91,7 +91,7 @@ public class RuntimeMetaData { * omitted.</li> * </ul> */ - public static final String VERSION = "4.5.1"; + public static final String VERSION = "4.5.2"; /** * Gets the currently executing version of the ANTLR 4 runtime library. diff --git a/runtime/Java/src/org/antlr/v4/runtime/misc/Utils.java b/runtime/Java/src/org/antlr/v4/runtime/misc/Utils.java index 011e8f2..991ee2b 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/misc/Utils.java +++ b/runtime/Java/src/org/antlr/v4/runtime/misc/Utils.java @@ -30,9 +30,6 @@ package org.antlr.v4.runtime.misc; -import java.awt.*; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -151,38 +148,6 @@ public class Utils { return data; } - public static void waitForClose(final Window window) throws InterruptedException { - final Object lock = new Object(); - - Thread t = new Thread() { - @Override - public void run() { - synchronized (lock) { - while (window.isVisible()) { - try { - lock.wait(500); - } catch (InterruptedException e) { - } - } - } - } - }; - - t.start(); - - window.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent arg0) { - synchronized (lock) { - window.setVisible(false); - lock.notify(); - } - } - }); - - t.join(); - } - /** Convert array of strings to string→index map. Useful for * converting rulenames to name→ruleindex map. */ diff --git a/tool-testsuite/pom.xml b/tool-testsuite/pom.xml index e21d6f8..81b4525 100644 --- a/tool-testsuite/pom.xml +++ b/tool-testsuite/pom.xml @@ -4,7 +4,7 @@ <parent> <groupId>org.antlr</groupId> <artifactId>antlr4-master</artifactId> - <version>4.5.1</version> + <version>4.5.2-1</version> </parent> <artifactId>antlr4-tool-testsuite</artifactId> <name>ANTLR 4 Tool Tests</name> @@ -76,6 +76,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> + <version>2.12.4</version> <configuration> <systemPropertyVariables> <antlr-python2-runtime>../../antlr4-python2/src</antlr-python2-runtime> diff --git a/tool-testsuite/test/org/antlr/v4/test/tool/Java-LR.g4 b/tool-testsuite/test/org/antlr/v4/test/tool/JavaLR.g4 index 9d38d02..049e283 100644 --- a/tool-testsuite/test/org/antlr/v4/test/tool/Java-LR.g4 +++ b/tool-testsuite/test/org/antlr/v4/test/tool/JavaLR.g4 @@ -168,7 +168,7 @@ * letter-or-digit is a character for which the method * Character.isJavaIdentifierPart(int) returns true." */ -grammar Java; +grammar JavaLR; // starting point for parsing a java file /* The annotations are separated out to make parsing faster, but must be associated with diff --git a/tool-testsuite/test/org/antlr/v4/test/tool/TestATNSerialization.java b/tool-testsuite/test/org/antlr/v4/test/tool/TestATNSerialization.java index 5aaede3..2c1a2b0 100644 --- a/tool-testsuite/test/org/antlr/v4/test/tool/TestATNSerialization.java +++ b/tool-testsuite/test/org/antlr/v4/test/tool/TestATNSerialization.java @@ -632,7 +632,7 @@ public class TestATNSerialization extends BaseTest { "lexer grammar L;\n"+ "A : 'a'\n ;\n" + "B : 'b';\n" + - "mode A;\n" + + "mode M;\n" + "C : 'c';\n"+ "D : 'd';\n"); String expecting = diff --git a/tool-testsuite/test/org/antlr/v4/test/tool/TestPerformance.java b/tool-testsuite/test/org/antlr/v4/test/tool/TestPerformance.java index 63a9c40..990cac6 100644 --- a/tool-testsuite/test/org/antlr/v4/test/tool/TestPerformance.java +++ b/tool-testsuite/test/org/antlr/v4/test/tool/TestPerformance.java @@ -153,7 +153,7 @@ public class TestPerformance extends BaseTest { /** * {@code true} to use the Java grammar with expressions in the v4 - * left-recursive syntax (Java-LR.g4). {@code false} to use the standard + * left-recursive syntax (JavaLR.g4). {@code false} to use the standard * grammar (Java.g4). In either case, the grammar is renamed in the * temporary directory to Java.g4 before compiling. */ @@ -415,10 +415,10 @@ public class TestPerformance extends BaseTest { assertTrue("The JDK_SOURCE_ROOT environment variable must be set for performance testing.", jdkSourceRoot != null && !jdkSourceRoot.isEmpty()); compileJavaParser(USE_LR_GRAMMAR); - final String lexerName = "JavaLexer"; - final String parserName = "JavaParser"; - final String listenerName = "JavaBaseListener"; - final String entryPoint = "compilationUnit"; + final String lexerName = USE_LR_GRAMMAR ? "JavaLRLexer" : "JavaLexer"; + final String parserName = USE_LR_GRAMMAR ? "JavaLRParser" : "JavaParser"; + final String listenerName = USE_LR_GRAMMAR ? "JavaLRBaseListener" : "JavaBaseListener"; + final String entryPoint = "compilationUnit"; final ParserFactory factory = getParserFactory(lexerName, parserName, listenerName, entryPoint); if (!TOP_PACKAGE.isEmpty()) { @@ -1108,9 +1108,10 @@ public class TestPerformance extends BaseTest { } protected void compileJavaParser(boolean leftRecursive) throws IOException { - String grammarFileName = "Java.g4"; - String sourceName = leftRecursive ? "Java-LR.g4" : "Java.g4"; - String body = load(sourceName, null); + String grammarFileName = leftRecursive ? "JavaLR.g4" : "Java.g4"; + String parserName = leftRecursive ? "JavaLRParser" : "JavaParser"; + String lexerName = leftRecursive ? "JavaLRLexer" : "JavaLexer"; + String body = load(grammarFileName, null); List<String> extraOptions = new ArrayList<String>(); extraOptions.add("-Werror"); if (FORCE_ATN) { @@ -1127,7 +1128,7 @@ public class TestPerformance extends BaseTest { } extraOptions.add("-visitor"); String[] extraOptionsArray = extraOptions.toArray(new String[extraOptions.size()]); - boolean success = rawGenerateAndBuildRecognizer(grammarFileName, body, "JavaParser", "JavaLexer", true, extraOptionsArray); + boolean success = rawGenerateAndBuildRecognizer(grammarFileName, body, parserName, lexerName, true, extraOptionsArray); assertTrue(success); } diff --git a/tool-testsuite/test/org/antlr/v4/test/tool/TestSymbolIssues.java b/tool-testsuite/test/org/antlr/v4/test/tool/TestSymbolIssues.java index 6934f2c..1c68ba3 100644 --- a/tool-testsuite/test/org/antlr/v4/test/tool/TestSymbolIssues.java +++ b/tool-testsuite/test/org/antlr/v4/test/tool/TestSymbolIssues.java @@ -116,10 +116,25 @@ public class TestSymbolIssues extends BaseTest { "warning(" + ErrorType.TOKEN_NAME_REASSIGNMENT.code + "): E.g4:3:4: token name A is already defined\n" }; + static String[] F = { + // INPUT + "lexer grammar F;\n" + + "A: 'a';\n" + + "mode M1;\n" + + "A1: 'a';\n" + + "mode M2;\n" + + "A2: 'a';\n" + + "M1: 'b';\n", + + // YIELDS + "error(" + ErrorType.MODE_CONFLICTS_WITH_TOKEN.code + "): F.g4:3:0: mode M1 conflicts with token with same name\n" + }; + @Test public void testA() { super.testErrors(A, false); } @Test public void testB() { super.testErrors(B, false); } @Test public void testD() { super.testErrors(D, false); } @Test public void testE() { super.testErrors(E, false); } + @Test public void testF() { super.testErrors(F, false); } @Test public void testStringLiteralRedefs() throws Exception { String grammar = @@ -169,4 +184,43 @@ public class TestSymbolIssues extends BaseTest { testErrors(test, false); } + + @Test public void testTokensModesChannelsDeclarationConflictsWithReserved() throws Exception { + String[] test = { + "lexer grammar L;\n" + + "channels { SKIP, HIDDEN, channel0 }\n" + + "A: 'a';\n" + + "mode MAX_CHAR_VALUE;\n" + + "MIN_CHAR_VALUE: 'a';\n" + + "mode DEFAULT_MODE;\n" + + "B: 'b';\n" + + "mode M;\n" + + "C: 'c';", + + "error(" + ErrorType.RESERVED_RULE_NAME.code + "): L.g4:5:0: cannot declare a rule with reserved name MIN_CHAR_VALUE\n" + + "error(" + ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:4:0: cannot use or declare mode with reserved name MAX_CHAR_VALUE\n" + + "error(" + ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:2:11: cannot use or declare channel with reserved name SKIP\n" + + "error(" + ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:2:17: cannot use or declare channel with reserved name HIDDEN\n" + }; + + testErrors(test, false); + } + + @Test public void testTokensModesChannelsUsingConflictsWithReserved() throws Exception { + String[] test = { + "lexer grammar L;\n" + + "A: 'a' -> channel(SKIP);\n" + + "B: 'b' -> type(MORE);\n" + + "C: 'c' -> mode(SKIP);\n" + + "D: 'd' -> channel(HIDDEN);\n" + + "E: 'e' -> type(EOF);\n" + + "F: 'f' -> pushMode(DEFAULT_MODE);", + + "error(" + ErrorType.CHANNEL_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:2:18: cannot use or declare channel with reserved name SKIP\n" + + "error(" + ErrorType.TOKEN_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:3:15: cannot use or declare token with reserved name MORE\n" + + "error(" + ErrorType.MODE_CONFLICTS_WITH_COMMON_CONSTANTS.code + "): L.g4:4:15: cannot use or declare mode with reserved name SKIP\n" + }; + + testErrors(test, false); + } } diff --git a/tool-testsuite/test/org/antlr/v4/test/tool/TestToolSyntaxErrors.java b/tool-testsuite/test/org/antlr/v4/test/tool/TestToolSyntaxErrors.java index ceaa570..c411434 100644 --- a/tool-testsuite/test/org/antlr/v4/test/tool/TestToolSyntaxErrors.java +++ b/tool-testsuite/test/org/antlr/v4/test/tool/TestToolSyntaxErrors.java @@ -455,6 +455,33 @@ public class TestToolSyntaxErrors extends BaseTest { } /** + * This is a regression test for antlr/antlr4#959 "NullPointerException". + * https://github.com/antlr/antlr4/issues/959 + */ + @Test public void testNotAllowedEmptyStrings() { + String grammar = + "lexer grammar T;\n" + + "Error0: '''test''';\n" + + "Error1: '' 'test';\n" + + "Error2: 'test' '';\n" + + "Error3: '';\n" + + "NotError: ' ';"; + String expected = + "error(" + ErrorType.EMPTY_STRINGS_NOT_ALLOWED.code + "): T.g4:2:8: string literals cannot be empty\n" + + "error(" + ErrorType.EMPTY_STRINGS_NOT_ALLOWED.code + "): T.g4:2:16: string literals cannot be empty\n" + + "error(" + ErrorType.EMPTY_STRINGS_NOT_ALLOWED.code + "): T.g4:3:8: string literals cannot be empty\n" + + "error(" + ErrorType.EMPTY_STRINGS_NOT_ALLOWED.code + "): T.g4:4:15: string literals cannot be empty\n" + + "error(" + ErrorType.EMPTY_STRINGS_NOT_ALLOWED.code + "): T.g4:5:8: string literals cannot be empty\n"; + + String[] pair = new String[] { + grammar, + expected + }; + + super.testErrors(pair, true); + } + + /** * This test ensures the {@link ErrorType#UNRECOGNIZED_ASSOC_OPTION} warning * is produced as described in the documentation. */ 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 |