summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuel Bourg <ebourg@apache.org>2016-03-22 17:34:38 +0100
committerEmmanuel Bourg <ebourg@apache.org>2016-03-22 17:34:38 +0100
commitf1e1398c68195f255332e40060950fbc3dc3985a (patch)
tree0a9da5c8d6048e763b0d3814f38dbdbef7854fdb
parent8f26ca6983190b53e7667d2cbf5344de1d87d51c (diff)
parent1a7b7906cbb3c334e0e8fe1dfdb68f16fefa8555 (diff)
Merge tag 'upstream/4.5.2'
Upstream version 4.5.2
-rw-r--r--README.md22
-rw-r--r--antlr4-maven-plugin/pom.xml2
-rw-r--r--antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java16
-rw-r--r--contributors.txt15
-rw-r--r--pom.xml5
-rw-r--r--runtime-testsuite/pom.xml14
-rw-r--r--runtime/Java/pom.xml2
-rw-r--r--runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java2
-rw-r--r--runtime/Java/src/org/antlr/v4/runtime/misc/Utils.java35
-rw-r--r--tool-testsuite/pom.xml3
-rw-r--r--tool-testsuite/test/org/antlr/v4/test/tool/JavaLR.g4 (renamed from tool-testsuite/test/org/antlr/v4/test/tool/Java-LR.g4)2
-rw-r--r--tool-testsuite/test/org/antlr/v4/test/tool/TestATNSerialization.java2
-rw-r--r--tool-testsuite/test/org/antlr/v4/test/tool/TestPerformance.java19
-rw-r--r--tool-testsuite/test/org/antlr/v4/test/tool/TestSymbolIssues.java54
-rw-r--r--tool-testsuite/test/org/antlr/v4/test/tool/TestToolSyntaxErrors.java27
-rw-r--r--tool/pom.xml9
-rw-r--r--tool/resources/org/antlr/v4/tool/templates/codegen/CSharp/CSharp.stg41
-rw-r--r--tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg7
-rw-r--r--tool/resources/org/antlr/v4/tool/templates/codegen/JavaScript/JavaScript.stg15
-rw-r--r--tool/resources/org/antlr/v4/tool/templates/codegen/Python2/Python2.stg7
-rw-r--r--tool/resources/org/antlr/v4/tool/templates/codegen/Python3/Python3.stg7
-rw-r--r--tool/src/org/antlr/v4/automata/LexerATNFactory.java31
-rw-r--r--tool/src/org/antlr/v4/codegen/ActionTranslator.java6
-rw-r--r--tool/src/org/antlr/v4/codegen/target/CSharpTarget.java2
-rw-r--r--tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java2
-rw-r--r--tool/src/org/antlr/v4/codegen/target/Python2Target.java2
-rw-r--r--tool/src/org/antlr/v4/codegen/target/Python3Target.java2
-rw-r--r--tool/src/org/antlr/v4/gui/TestRig.java5
-rw-r--r--tool/src/org/antlr/v4/gui/TreeViewer.java8
-rw-r--r--tool/src/org/antlr/v4/semantics/BasicSemanticChecks.java10
-rw-r--r--tool/src/org/antlr/v4/semantics/SemanticPipeline.java7
-rw-r--r--tool/src/org/antlr/v4/semantics/SymbolChecks.java22
-rw-r--r--tool/src/org/antlr/v4/tool/ErrorType.java54
33 files changed, 337 insertions, 120 deletions
diff --git a/README.md b/README.md
index 731a877..c1d6902 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/pom.xml b/pom.xml
index c29dd26..4f64284 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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&rarr;index map. Useful for
* converting rulenames to name&rarr;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