Merge branch 'master' into LR-loop-fix

This commit is contained in:
Mike Lischke 2016-12-19 16:48:10 +01:00
commit d324e9a46b
76 changed files with 1188 additions and 635 deletions

View File

@ -1,5 +1,5 @@
[cut]
Thank you for proposing a contribution to the ANTLR project. In order to accept changes from the outside world, all contributors most "sign" the [contributors.txt](https://github.com/antlr/antlr4/blob/master/contributors.txt) contributors certificate of origin. It's an unfortunate reality of today's fuzzy and bizarre world of open-source ownership.
Thank you for proposing a contribution to the ANTLR project. In order to accept changes from the outside world, all contributors must "sign" the [contributors.txt](https://github.com/antlr/antlr4/blob/master/contributors.txt) contributors certificate of origin. It's an unfortunate reality of today's fuzzy and bizarre world of open-source ownership.
Make sure you are already in the contributors.txt file or add a commit to this pull request with the appropriate change. Thanks!
[/cut]

View File

@ -6,6 +6,8 @@
*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*
[![Donate](https://www.paypal.com/en_US/i/btn/x-click-butcc-donate.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=BF92STRXT8F8Q)
## Authors and major contributors
* [Terence Parr](http://www.cs.usfca.edu/~parrt/), parrt@cs.usfca.edu

View File

@ -8,7 +8,7 @@
<parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
</parent>
<artifactId>antlr4-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>

View File

@ -174,13 +174,20 @@ At this point, you should have an editor which displays an error icon next to th
What remains to be done is have our validate function actually validate the input. Finally ANTLR comes in the picture!
To start with, let's load ANTLR and your parser, listener etc.. Easy, since you could write:
To start with, let's load ANTLR and your parser, listener etc..
The preferred approach for loading parser code is to bundle your parser, [as described here](javascript-target.md).
You can then load it as part of the importScripts instruction at the start of your worker code.
Another approach is to load it using 'require'. Easy, since you could write:
```js
var antlr4 = require('antlr4/index');
```
This may work, but it's actually unreliable. The reason is that the require function used by ANTLR, which exactly mimics the NodeJS require function, uses a different syntax than the require function that comes with ACE. So we need to bring in a require function that conforms to the NodeJS syntax. I personally use one that comes from Torben Haase's Honey project, which you can find here. But hey, now we're going to have 2 'require' functions not compatible with each other! Indeed, this is why you need to take special care, as follows:
This may work, but it's actually unreliable. The reason is that the 'require' function that comes with ACE uses a different syntax than the 'require' function used by ANTLR, which follows the NodeJS 'require' convention.
So we need to bring in a NodeJS compatible 'require' function that conforms to the NodeJS syntax. I personally use one that comes from Torben Haase's Honey project, which you can find in li/require.js.
But hey, now we're going to have 2 'require' functions not compatible with each other! Indeed, this is why you need to take special care, as follows:
```js
// load nodejs compatible require
@ -191,7 +198,8 @@ importScripts("../lib/require.js");
var antlr4_require = require;
require = ace_require;
```
Now it's safe to load antlr, and the parsers generated for your language. Assuming that your language files (generated or hand-built) are in a folder with an index.js file that calls require for each file, your parser loading code can be as simple as follows:
Now it's safe to load antlr and the parsers generated for your language.
Assuming that your language files (generated or hand-built) are in a folder with an index.js file that calls require for each file, your parser loading code can be as simple as follows:
```js
// load antlr4 and myLanguage
var antlr4, mylanguage;
@ -204,6 +212,7 @@ try {
}
```
Please note the try-finally construct. ANTLR uses 'require' synchronously so it's perfectly safe to ignore the ACE 'require' while running ANTLR code. ACE itself does not guarantee synchronous execution, so you are much safer always switching 'require' back to 'ace_require'.
Now detecting deep syntax errors in your code is a task for your ANTLR listener or visitor or whatever piece of code you've delegated this to. We're not going to describe this here, since it would require some knowledge of your language. However, detecting grammar syntax errors is something ANTLR does beautifully (isn't that why you went for ANTLR in the first place?). So what we will illustrate here is how to report grammar syntax errors. I have no doubt that from there, you will be able to extend the validator to suit your specific needs.
Whenever ANTLR encounters an unexpected token, it fires an error. By default, the error is routed to an error listener which simply writes to the console.
What we need to do is replace this listener by our own listener, se we can route errors to the ACE editor. First, let's create such a listener:
@ -243,5 +252,4 @@ var validate = function(input) {
};
```
You know what? That's it! You now have an ACE editor that does syntax validation using ANTLR! I hope you find this useful, and simple enough to get started.
What I did not address here is packaging, not something I'm an expert at. The good news is that it makes development simple, since I don't have to run any compilation process. I just edit my code, reload my editor page, and check how it goes.
Now wait, hey! How do you debug this? Well, as usual, using Chrome, since neither Firefox or Safari are able to debug worker code. What a shame...
WNow wait, hey! How do you debug this? Well, as usual, using Chrome, since no other browser is able to debug worker code. What a shame...

View File

@ -1,4 +1,4 @@
# Adding unit tests
# ANTLR project unit tests
## Introduction
@ -35,6 +35,39 @@ The mysterious `@CommentHasStringValue` annotation is a bit of a hack that allow
The grammars are strings representing StringTemplates (`ST` objects) so `<writeln("$text")>` will get replace when the unit test file is generated (`Test.java`, `Test.cs`, ...). The `writeln` template must be defined per target. Here are all of the
[Target templates for runtime tests](https://github.com/antlr/antlr4/tree/master/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates).
## Requirements
In order to perform the tests on all target languages, you need to have the following languages installed:
* `mono` (e.g., `brew install mono`) on non-Windows boxes (on Windows it uses the Microsoft .net stack). Also must [`xbuild` the runtime](https://github.com/antlr/antlr4/blob/master/doc/releasing-antlr.md) before tests will run; see below
* `nodejs`
* Python 2.7
* Python 3.5
* Go
* Swift 3 (via XCode 8.x) tested currently only osx
* clang (for C++ target)
*
To **install into local repository** `~/.m2/repository/org/antlr`, do this:
```bash
$ export MAVEN_OPTS="-Xmx1G" # don't forget this on linux
$ mvn install -DskipTests=true # make sure all artifacts are visible on this machine
```
Now, make sure C# runtime is built and installed locally.
```bash
cd ~/antlr/code/antlr4/runtime/CSharp/runtime/CSharp
# kill previous ones manually as "xbuild /t:Clean" didn't seem to do it
rm Antlr4.Runtime/bin/net20/Release/Antlr4.Runtime.dll
rm Antlr4.Runtime/obj/net20/Release/Antlr4.Runtime.dll
# build
xbuild /p:Configuration=Release Antlr4.Runtime/Antlr4.Runtime.mono.csproj
```
C++ test rig automatically builds C++ runtime during tests. Others don't need a prebuilt lib.
## Running the runtime tests
A single test rig is sufficient to test all targets against all descriptors using the [junit parameterized tests](https://github.com/junit-team/junit4/wiki/parameterized-tests) mechanism. But, that is inconvenient because we often want to test just a single target or perhaps even just a single test within a single group of a single target. I have automatically generated a bunch of
@ -49,26 +82,128 @@ And the result of testing the entire subdirectory:
From `mvn`, on the commandline, you will see:
```bash
$ cd antlr4
$ mvn test
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.javascript.node.TestCompositeLexers
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.581 sec
Running org.antlr.v4.test.runtime.javascript.node.TestLexerErrors
Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.721 sec
Running org.antlr.v4.test.runtime.javascript.node.TestSemPredEvalParser
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.084 sec
Running org.antlr.v4.test.runtime.javascript.node.TestSets
Tests run: 23, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.798 sec
Running org.antlr.v4.test.runtime.javascript.node.TestPerformance
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.505 sec
Running org.antlr.v4.test.runtime.javascript.node.TestSemPredEvalLexer
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.994 sec
Running org.antlr.v4.test.runtime.javascript.node.TestLexerExec
Tests run: 38, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 8.433 sec
Running org.antlr.v4.test.runtime.csharp.TestCompositeLexers
dir /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068612451
Starting build /usr/bin/xbuild /p:Configuration=Release /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068612451/Antlr4.Test.mono.csproj
dir /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068615081
Starting build /usr/bin/xbuild /p:Configuration=Release /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068615081/Antlr4.Test.mono.csproj
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.451 sec
Running org.antlr.v4.test.runtime.csharp.TestCompositeParsers
dir /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864
antlr reports warnings from [-visitor, -Dlanguage=CSharp, -o, /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864, -lib, /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864, -encoding, UTF-8, /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864/M.g4]
...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] ANTLR 4 ............................................ SUCCESS [ 0.445 s]
[INFO] ANTLR 4 Runtime .................................... SUCCESS [ 3.392 s]
[INFO] ANTLR 4 Tool ....................................... SUCCESS [ 1.373 s]
[INFO] ANTLR 4 Maven plugin ............................... SUCCESS [ 1.519 s]
[INFO] ANTLR 4 Runtime Test Annotations ................... SUCCESS [ 0.086 s]
[INFO] ANTLR 4 Runtime Test Processors .................... SUCCESS [ 0.014 s]
[INFO] ANTLR 4 Runtime Tests (2nd generation) ............. SUCCESS [06:39 min]
[INFO] ANTLR 4 Tool Tests ................................. SUCCESS [ 6.922 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 06:53 min
[INFO] Finished at: 2016-11-16T15:36:56-08:00
[INFO] Final Memory: 44M/458M
[INFO] ------------------------------------------------------------------------
```
Note: That is actually result of running the much faster:
```bash
mvn -Dparallel=methods -DthreadCount=4 install
```
## Running test subsets
*From the `runtime-testsuite` dir*
### Run one test group across targets
```bash
$ cd runtime-testsuite
$ export MAVEN_OPTS="-Xmx1G" # don't forget this on linux
$ mvn -Dtest=TestParserExec test
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.cpp.TestParserExec
...
Tests run: 32, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 114.283 sec
Running org.antlr.v4.test.runtime.csharp.TestParserExec
...
```
Or run all lexer related tests:
```
$ cd runtime-testsuite
$ mvn -Dtest=Test*Lexer* test
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.cpp.TestCompositeLexers
...
```
### Run all tests for a single target
```bash
$ cd runtime-testsuite
$ mvn -Dtest=java.* test
...
```
Or run all lexer related tests in Java target only:
```bash
$ cd runtime-testsuite
$ mvn -Dtest=java.*Lexer* test
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.java.TestCompositeLexers
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.277 sec
Running org.antlr.v4.test.runtime.java.TestLexerErrors
Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.376 sec
Running org.antlr.v4.test.runtime.java.TestLexerExec
Tests run: 38, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.07 sec
Running org.antlr.v4.test.runtime.java.TestSemPredEvalLexer
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.255 sec
Results :
Tests run: 59, Failures: 0, Errors: 0, Skipped: 0
```
## Testing in parallel
Use this to run tests in parallel:
```bash
$ export MAVEN_OPTS="-Xmx1G"
$ mvn -Dparallel=methods -DthreadCount=4 test
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Concurrency config is parallel='methods', perCoreThreadCount=true, threadCount=4, useUnlimitedThreads=false
...
```
This can be combined with other `-D` above.
## Adding a runtime test
To add a new runtime test, first determine which [group of tests](https://github.com/antlr/antlr4/blob/master/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors) it belongs to. Then, add a new [RuntimeTestDescriptor](https://github.com/antlr/antlr4/blob/master/runtime-testsuite/test/org/antlr/v4/test/runtime/RuntimeTestDescriptor.java) implementation by subclassing one of:

View File

@ -38,6 +38,7 @@ Receiving objects: 100% (59858/59858), 31.10 MiB | 819.00 KiB/s, done.
Resolving deltas: 100% (31898/31898), done.
Checking connectivity... done.
$ cd antlr4
$ export MAVEN_OPTS="-Xmx1G" # don't forget this on linux
$ mvn -DskipTests install
...
[INFO] ------------------------------------------------------------------------
@ -67,65 +68,10 @@ We do `install` not `compile` as tool tests and such refer to modules that must
To skip the tests (which require all the target languages be installed) and **install into local repository** `~/.m2/repository/org/antlr`, do this:
```bash
$ export MAVEN_OPTS="-Xmx1G" # don't forget this on linux
$ mvn install -DskipTests=true # make sure all artifacts are visible on this machine
```
# Testing tool and targets
In order to perform the tests on all target languages, you need to have the following languages installed:
* `mono` (e.g., `brew install mono`)
* `nodejs`
* Python 2.7
* Python 3.5
* Go
* Swift 3 (via XCode 8.x) tested currently only osx
* clang (for C++ target)
To run the tests and **install into local repository** `~/.m2/repository/org/antlr`, do this:
```bash
$ mvn install -DskipTests=true # make sure all artifacts are visible on this machine
$ mvn install # now "do it with feeling"
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.csharp.TestCompositeLexers
dir /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068612451
Starting build /usr/bin/xbuild /p:Configuration=Release /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068612451/Antlr4.Test.mono.csproj
dir /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068615081
Starting build /usr/bin/xbuild /p:Configuration=Release /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeLexers-1446068615081/Antlr4.Test.mono.csproj
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.451 sec
Running org.antlr.v4.test.runtime.csharp.TestCompositeParsers
dir /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864
antlr reports warnings from [-visitor, -Dlanguage=CSharp, -o, /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864, -lib, /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864, -encoding, UTF-8, /var/folders/s1/h3qgww1x0ks3pb30l8t1wgd80000gn/T/TestCompositeParsers-1446068615864/M.g4]
...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] ANTLR 4 ............................................ SUCCESS [ 0.445 s]
[INFO] ANTLR 4 Runtime .................................... SUCCESS [ 3.392 s]
[INFO] ANTLR 4 Tool ....................................... SUCCESS [ 1.373 s]
[INFO] ANTLR 4 Maven plugin ............................... SUCCESS [ 1.519 s]
[INFO] ANTLR 4 Runtime Test Annotations ................... SUCCESS [ 0.086 s]
[INFO] ANTLR 4 Runtime Test Processors .................... SUCCESS [ 0.014 s]
[INFO] ANTLR 4 Runtime Tests (2nd generation) ............. SUCCESS [06:39 min]
[INFO] ANTLR 4 Tool Tests ................................. SUCCESS [ 6.922 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 06:53 min
[INFO] Finished at: 2016-11-16T15:36:56-08:00
[INFO] Final Memory: 44M/458M
[INFO] ------------------------------------------------------------------------
```
Note: That is actually result of running the much faster:
`mvn -Dparallel=methods -DthreadCount=4 install`
You should see these jars (when building 4.6-SNAPSHOT):
```bash
@ -143,87 +89,17 @@ antlr4/4.6-SNAPSHOT/antlr4-4.6-SNAPSHOT.jar
Note that ANTLR is written in itself, which is why maven downloads antlr4-4.5.jar for boostrapping 4.6-SNAPSHOT purposes.
## Running test subsets
# Testing tool and targets
*From the `runtime-testsuite` dir*
See [ANTLR project unit tests](antlr-project-testing.md).
### Run one test group across targets
```bash
$ cd runtime-testsuite
$ mvn -Dtest=TestParserExec test
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.cpp.TestParserExec
...
Tests run: 32, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 114.283 sec
Running org.antlr.v4.test.runtime.csharp.TestParserExec
...
```
Or run all lexer related tests:
```
$ mvn -Dtest=Test*Lexer* test
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.cpp.TestCompositeLexers
...
```
### Run all tests for a single target
```bash
$ mvn -Dtest=java.* test
...
```
Or run all lexer related tests in Java target only:
```bash
$ mvn -Dtest=java.*Lexer* test
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running org.antlr.v4.test.runtime.java.TestCompositeLexers
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.277 sec
Running org.antlr.v4.test.runtime.java.TestLexerErrors
Tests run: 12, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.376 sec
Running org.antlr.v4.test.runtime.java.TestLexerExec
Tests run: 38, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.07 sec
Running org.antlr.v4.test.runtime.java.TestSemPredEvalLexer
Tests run: 7, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.255 sec
Results :
Tests run: 59, Failures: 0, Errors: 0, Skipped: 0
```
## Testing in parallel
Use this to run tests in parallel:
```bash
$ mvn -Dparallel=methods -DthreadCount=4 test
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Concurrency config is parallel='methods', perCoreThreadCount=true, threadCount=4, useUnlimitedThreads=false
...
```
This can be combined with other `-D` above.
## Building without testing
# Building without testing
To build without running the tests (saves a lot of time), do this:
```bash
mvn -DskipTests install
$ mvn -DskipTests install
```
## Building ANTLR in Intellij IDE

View File

@ -20,11 +20,13 @@ You will see that there are a whole bunch of files generated by this call. If vi
## Where can I get the runtime?
Once you've generated the lexer and/or parser code, you need to download or build the runtime. Prebuilt C++ runtime binaries for Windows (VS 2013 runtime), OSX and iOS are available on the ANTLR web site:
Once you've generated the lexer and/or parser code, you need to download or build the runtime. Prebuilt C++ runtime binaries for Windows (Visual Studio 2013/2015), OSX/macOS and iOS are available on the ANTLR web site:
* http://www.antlr.org
Use CMake to build a Linux library (works also on OSX, however not for the iOS library). Building your own library on OSX or Windows is trivial, however. Just open the VS or XCode project, select target + arch and build it. Should work out of the box without any additional dependency.
Use CMake to build a Linux library (works also on OSX, however not for the iOS library).
Instead of downloading a prebuilt binary you can also easily build your own library on OSX or Windows. Just use the provided projects for XCode or Visual Studio and build it. Should work out of the box without any additional dependency.
## How do I run the generated lexer and/or parser?
@ -76,6 +78,29 @@ This example assumes your grammar contains a parser rule named `key` for which t
There are a couple of things that only the C++ ANTLR target has to deal with. They are described here.
### Build Aspects
The code generation (by running the ANTLR4 jar) allows to specify 2 values you might find useful for better integration of the generated files into your application (both are optional):
* A **namespace**: use the **`-package`** parameter to specify the namespace you want.
* An **export macro**: especially in VC++ extra work is required to export your classes from a DLL. This is usually accomplished by a macro that has different values depending on whether you are creating the DLL or import it. The ANTLR4 runtime itself also uses one for its classes:
```c++
#ifdef ANTLR4CPP_EXPORTS
#define ANTLR4CPP_PUBLIC __declspec(dllexport)
#else
#ifdef ANTLR4CPP_STATIC
#define ANTLR4CPP_PUBLIC
#else
#define ANTLR4CPP_PUBLIC __declspec(dllimport)
#endif
#endif
```
Just like the `ANTLR4CPP_PUBLIC` macro here you can specify your own one for the generated classes using the **`-export-macro`** parameter.
In order to create a static lib in Visual Studio define the `ANTLR4CPP_STATIC` macro in addition to the project settings that must be set for a static library (if you compile the runtime yourself).
For gcc and clang it is possible to use the `-fvisibility=hidden` setting to hide all symbols except those that are made default-visible (which has been defined for all public classes in the runtime).
### Memory Management
Since C++ has no built-in memory management we need to take extra care. For that we rely mostly on smart pointers, which however might cause time penalties or memory side effects (like cyclic references) if not used with care. Currently however the memory household looks very stable. Generally, when you see a raw pointer in code consider this as being managed elsewehere. You should never try to manage such a pointer (delete, assign to smart pointer etc.).

View File

@ -1,8 +1,6 @@
# C&sharp;
See also [Sam Harwell's Alternative C# target](https://github.com/tunnelvisionlabs/antlr4cs)
### Which frameworks are supported?
## Which frameworks are supported?
The C# runtime is CLS compliant, and only requires a corresponding 3.5 .Net framework.
@ -13,19 +11,15 @@ In practice, the runtime has been extensively tested against:
No issue was found, so you should find that the runtime works pretty much against any recent .Net framework.
### How do I get started?
## How do I get started?
You will find full instructions on the Git web page for ANTLR C# runtime.
You will find full instructions on the [Git repo page for ANTLR C# runtime](https://github.com/antlr/antlr4/tree/master/runtime/CSharp).
### How do I use the runtime from my project?
## How do I use the runtime from my project?
(i.e., How do I run the generated lexer and/or parser?)
Let's suppose that your grammar is named, as above, "MyGrammar".
Let's suppose this parser comprises a rule named "StartRule"
The tool will have generated for you the following files:
Let's suppose that your grammar is named `MyGrammar`. The tool will generate for you the following files:
* MyGrammarLexer.cs
* MyGrammarParser.cs
@ -34,7 +28,7 @@ The tool will have generated for you the following files:
* MyGrammarVisitor.js (if you have activated the -visitor option)
* MyGrammarBaseVisitor.js (if you have activated the -visitor option)
Now a fully functioning code might look like the following:
Now a fully functioning code might look like the following for start rule `StartRule`:
```
using Antlr4.Runtime;
@ -58,7 +52,7 @@ This program will work. But it won't be useful unless you do one of the followin
(please note that production code is target specific, so you can't have multi target grammars that include production code)
### How do I create and run a custom listener?
## How do I create and run a custom listener?
Let's suppose your MyGrammar grammar comprises 2 rules: "key" and "value".
@ -96,4 +90,5 @@ ParseTreeWalker.DEFAULT.walk(printer, tree);
Further information can be found from The Definitive ANTLR Reference book.
The C# implementation of ANTLR is as close as possible to the Java one, so you shouldn't find it difficult to adapt the examples for C#.
The C# implementation of ANTLR is as close as possible to the Java one, so you shouldn't find it difficult to adapt the examples for C#. See also [Sam Harwell's alternative C# target](https://github.com/tunnelvisionlabs/antlr4cs)

BIN
doc/images/dragfile.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
doc/images/xcodedep.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 KiB

BIN
doc/images/xcodenav.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@ -63,6 +63,6 @@ This documentation is a reference and summarizes grammar syntax and the key sema
* [Cutting an ANTLR Release](releasing-antlr.md)
* [Adding ANTLR unit tests](adding-tests.md)
* [ANTLR project unit tests](antlr-project-testing.md)
* [Creating an ANTLR Language Target](creating-a-language-target.md)

View File

@ -15,7 +15,7 @@ The tests were conducted using Selenium. No issue was found, so you should find
## Is NodeJS supported?
The runtime has also been extensively tested against Node.js 0.10.33. No issue was found.
The runtime has also been extensively tested against Node.js 0.12.7. No issue was found.
## How to create a JavaScript lexer or parser?
@ -31,7 +31,9 @@ For a full list of antlr4 tool options, please visit the [tool documentation pag
Once you've generated the lexer and/or parser code, you need to download the runtime.
The JavaScript runtime is available from the ANTLR web site [download section](http://www.antlr.org/download/index.html). The runtime is provided in the form of source code, so no additional installation is required.
The JavaScript runtime is [available from npm](https://www.npmjs.com/package/antlr4).
If you can't use npm, the JavaScript runtime is also available from the ANTLR web site [download section](http://www.antlr.org/download/index.html). The runtime is provided in the form of source code, so no additional installation is required.
We will not document here how to refer to the runtime from your project, since this would differ a lot depending on your project type and IDE.
@ -47,11 +49,28 @@ However, it would be a bit of a problem when it comes to get it into a browser.
<script src='lib/myscript.js'>
```
In order to avoid having to do this, and also to have the exact same code for browsers and Node.js, we rely on a script which provides the equivalent of the Node.js 'require' function.
To avoid having doing this, the preferred approach is to bundle antlr4 with your parser code, using webpack.
This script is provided by Torben Haase, and is NOT part of ANTLR JavaScript runtime, although the runtime heavily relies on it. Please note that syntax for 'require' in NodeJS is different from the one implemented by RequireJS and similar frameworks.
You can get [information on webpack here](https://webpack.github.io).
So in short, assuming you have at the root of your web site, both the 'antlr4' directory and a 'lib' directory with 'require.js' inside it, all you need to put in your HTML header is the following:
The steps to create your parsing code are the following:
- generate your lexer, parser, listener and visitor using the antlr tool
- write your parse tree handling code by providig your custom listener or visitor, and associated code, using 'require' to load antlr.
- create an index.js file with the entry point to your parsing code (or several if required).
- test your parsing logic thoroughly using node.js
You are now ready to bundle your parsing code as follows:
- following webpack specs, create a webpack.config file
- in the webpack.config file, exclude node.js only modules using: node: { module: "empty", net: "empty", fs: "empty" }
- from the cmd line, nag-vigate to the directory containing webpack.config and type: webpack
This will produce a single js file containing all your parsing code. Easy to include in your web pages!
If you can't use webpack, you can use the lib/require.js script which implements the Node.js 'require' function in brwsers.
This script is provided by Torben Haase, and is NOT part of ANTLR JavaScript runtime.
Assuming you have, at the root of your web site, both the 'antlr4' directory and a 'lib' directory with 'require.js' inside it, all you need to put in your HTML header is the following:
```xml
<script src='lib/require.js'>
@ -62,16 +81,6 @@ So in short, assuming you have at the root of your web site, both the 'antlr4' d
This will load the runtime asynchronously.
## How do I get the runtime in Node.js?
Right now, there is no npm package available, so you need to register a link instead. This can be done by running the following command from the antlr4 directory:
```bash
$ npm link antlr4
```
This will install antlr4 using the package.json descriptor that comes with the script.
## How do I run the generated lexer and/or parser?
Let's suppose that your grammar is named, as above, "MyGrammar". Let's suppose this parser comprises a rule named "StartRule". The tool will have generated for you the following files:

View File

@ -4,12 +4,22 @@
Create a pre-release or full release at github; [Example 4.5-rc-1](https://github.com/antlr/antlr4/releases/tag/4.5-rc-1).
### Delete existing release tag
Wack any existing tag as mvn will create one and it fails if already there.
```
$ git tag -d 4.5.2
$ git push origin :refs/tags/4.5.2
$ git push upstream :refs/tags/4.5.2
$ git tag -d 4.6
$ git push origin :refs/tags/4.6
$ git push upstream :refs/tags/4.6
```
### Create release candidate tag
```bash
$ git tag -a 4.6-rc1 -m 'heading towards 4.6'
$ git push origin 4.6-rc1
$ git push upstream 4.6-rc1
```
## Bump version
@ -22,15 +32,17 @@ Edit the repository looking for 4.5 or whatever and update it. Bump version in t
* runtime/Python3/setup.py
* runtime/Python3/src/antlr4/Recognizer.py
* runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Properties/AssemblyInfo.cs
* runtime/CSharp/build/version.ps1
* runtime/JavaScript/src/antlr4/package.json
* runtime/JavaScript/src/antlr4/Recognizer.js
* runtime/Cpp/VERSION
* runtime/Cpp/runtime/src/RuntimeMetaData.cpp
* runtime/Cpp/cmake/ExternalAntlr4Cpp.cmake
* tool/src/org/antlr/v4/codegen/target/CppTarget.java
* tool/src/org/antlr/v4/codegen/target/CSharpTarget.java
* tool/src/org/antlr/v4/codegen/target/JavaScriptTarget.java
* tool/src/org/antlr/v4/codegen/target/Python2Target.java
* tool/src/org/antlr/v4/codegen/target/Python3Target.java
* runtime/Cpp/VERSION
* runtime/Cpp/RuntimeMetaData.cpp
Here is a simple script to display any line from the critical files with, say, `4.5` in it:
@ -144,24 +156,24 @@ It will start out by asking you the version number:
```
...
What is the release version for "ANTLR 4"? (org.antlr:antlr4-master) 4.5.2: : 4.5.2
What is the release version for "ANTLR 4 Runtime"? (org.antlr:antlr4-runtime) 4.5.2: :
What is the release version for "ANTLR 4 Tool"? (org.antlr:antlr4) 4.5.2: :
What is the release version for "ANTLR 4 Maven plugin"? (org.antlr:antlr4-maven-plugin) 4.5.2: :
What is the release version for "ANTLR 4 Runtime Test Generator"? (org.antlr:antlr4-runtime-testsuite) 4.5.2: :
What is the release version for "ANTLR 4 Tool Tests"? (org.antlr:antlr4-tool-testsuite) 4.5.2: :
What is SCM release tag or label for "ANTLR 4"? (org.antlr:antlr4-master) antlr4-master-4.5.2: : 4.5.2
What is the new development version for "ANTLR 4"? (org.antlr:antlr4-master) 4.5.3-SNAPSHOT:
What is the release version for "ANTLR 4"? (org.antlr:antlr4-master) 4.6: : 4.6
What is the release version for "ANTLR 4 Runtime"? (org.antlr:antlr4-runtime) 4.6: :
What is the release version for "ANTLR 4 Tool"? (org.antlr:antlr4) 4.6: :
What is the release version for "ANTLR 4 Maven plugin"? (org.antlr:antlr4-maven-plugin) 4.6: :
What is the release version for "ANTLR 4 Runtime Test Generator"? (org.antlr:antlr4-runtime-testsuite) 4.6: :
What is the release version for "ANTLR 4 Tool Tests"? (org.antlr:antlr4-tool-testsuite) 4.6: :
What is SCM release tag or label for "ANTLR 4"? (org.antlr:antlr4-master) antlr4-master-4.6: : 4.6
What is the new development version for "ANTLR 4"? (org.antlr:antlr4-master) 4.6.1-SNAPSHOT:
...
```
Maven will go through your pom.xml files to update versions from 4.5.2-SNAPSHOT to 4.5.2 for release and then to 4.5.3-SNAPSHOT after release, which is done with:
Maven will go through your pom.xml files to update versions from 4.6-SNAPSHOT to 4.6 for release and then to 4.6.1-SNAPSHOT after release, which is done with:
```bash
mvn release:perform -Darguments="-DskipTests"
```
Maven will use git to push pom.xml changes. (big smile)
Maven will use git to push pom.xml changes.
Now, go here:
@ -174,11 +186,11 @@ and on the left click "Staging Repositories". You click the staging repo and clo
Copy the jars to antlr.org site and update download/index.html
```bash
cp ~/.m2/repository/org/antlr/antlr4-runtime/4.5.2/antlr4-runtime-4.5.2.jar ~/antlr/sites/website-antlr4/download/antlr-runtime-4.5.2.jar
cp ~/.m2/repository/org/antlr/antlr4/4.5.2/antlr4-4.5.2.jar ~/antlr/sites/website-antlr4/download/antlr-4.5.2-complete.jar
cp ~/.m2/repository/org/antlr/antlr4-runtime/4.6/antlr4-runtime-4.6.jar ~/antlr/sites/website-antlr4/download/antlr-runtime-4.6.jar
cp ~/.m2/repository/org/antlr/antlr4/4.6/antlr4-4.6-complete.jar ~/antlr/sites/website-antlr4/download/antlr-4.6-complete.jar
cd ~/antlr/sites/website-antlr4/download
git add antlr-4.5.2-complete.jar
git add antlr-runtime-4.5.2.jar
git add antlr-4.6-complete.jar
git add antlr-runtime-4.6.jar
```
Update on site:
@ -190,7 +202,7 @@ Update on site:
* scripts/topnav.js
```
git commit -a -m 'add 4.5.2 jars'
git commit -a -m 'add 4.6 jars'
git push origin gh-pages
```
@ -200,8 +212,8 @@ git push origin gh-pages
```bash
cd runtime/JavaScript/src
zip -r /tmp/antlr-javascript-runtime-4.5.2.zip antlr4
cp /tmp/antlr-javascript-runtime-4.5.2.zip ~/antlr/sites/website-antlr4/download
zip -r /tmp/antlr-javascript-runtime-4.6.zip antlr4
cp /tmp/antlr-javascript-runtime-4.6.zip ~/antlr/sites/website-antlr4/download
# git add, commit, push
```
@ -209,7 +221,7 @@ Move target to website
```bash
pushd ~/antlr/sites/website-antlr4/download
git add antlr-javascript-runtime-4.5.2.zip
git add antlr-javascript-runtime-4.6.zip
git commit -a -m 'update JS runtime'
git push origin gh-pages
popd
@ -217,6 +229,70 @@ popd
### CSharp
*Publishing to Nuget from Linux/MacOSX*
**Getting ready to run Nuget**
Of course you need Mono and `nuget` to be installed. On mac:
```bash
brew install mono
brew install nuget
```
Or, you can [download nuget.exe](https://dist.nuget.org/win-x86-commandline/latest/nuget.exe).
From the shell on mac, you can check all is ok by typing
```bash
nuget
```
This should display the nuget help.
**Creating the assembly**
```bash
$ cd runtime/CSharp/runtime/CSharp/Antlr4.Runtime
$ xbuild /p:Configuration=Release Antlr4.Runtime.mono.csproj
...
Copying file from '/Users/parrt/antlr/code/antlr4/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/obj/net20/Release/Antlr4.Runtime.Standard.dll' to '/Users/parrt/antlr/code/antlr4/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/lib/Release/Antlr4.Runtime.Standard.dll'
Done building project "/Users/parrt/antlr/code/antlr4/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/Antlr4.Runtime.mono.csproj".
```
Alternately, you may want to build ANTLR using Xamarin Studio Community (free).
**Packaging for NuGet**
```bash
cd runtime/CSharp/runtime/CSharp
```
which is where the `Package.nuspec` file resides.
Type the following command:
```bash
$ nuget pack Package.nuspec
Attempting to build package from 'Package.nuspec'.
Successfully created package '/Users/parrt/antlr/code/antlr4/runtime/CSharp/runtime/CSharp/Antlr4.Runtime.Standard.4.6.0.nupkg'.
```
This should display: Successfully created package *&lt;package-path>*
**Publishing to NuGet**
You need to be a NuGet owner for "ANTLR 4 Standard Runtime"
As a registered NuGet user, you can then manually upload the package spec here (`runtime/CSharp/runtime/CSharp/Package.nuspec`): [https://www.nuget.org/packages/manage/upload](https://www.nuget.org/packages/manage/upload)
Alternately, you can publish from the cmd line. You need to get your NuGet key from [https://www.nuget.org/account#](https://www.nuget.org/account#) and then from the cmd line, you can then type:
```bash
nuget push Antlr4.Runtime.Standard.<version>.nupkg <your-key> -Source https://www.nuget.org/api/v2/package
```
**Creating DLLs**
```bash
cd ~/antlr/code/antlr4/runtime/CSharp/runtime/CSharp
# kill previous ones manually as "xbuild /t:Clean" didn't seem to do it
@ -225,15 +301,15 @@ rm Antlr4.Runtime/obj/net20/Release/Antlr4.Runtime.dll
# build
xbuild /p:Configuration=Release Antlr4.Runtime/Antlr4.Runtime.mono.csproj
# zip it up to get a version number on zip filename
zip --junk-paths /tmp/antlr-csharp-runtime-4.5.2.zip Antlr4.Runtime/bin/net35/Release/Antlr4.Runtime.dll
cp /tmp/antlr-csharp-runtime-4.5.2.zip ~/antlr/sites/website-antlr4/download
zip --junk-paths /tmp/antlr-csharp-runtime-4.6.zip Antlr4.Runtime/obj/net20/Release/Antlr4.Runtime.Standard.dll
cp /tmp/antlr-csharp-runtime-4.6.zip ~/antlr/sites/website-antlr4/download
```
Move target to website
```bash
pushd ~/antlr/sites/website-antlr4/download
git add antlr-csharp-runtime-4.5.2.zip
git add antlr-csharp-runtime-4.6.zip
git commit -a -m 'update C# runtime'
git push origin gh-pages
popd
@ -282,7 +358,7 @@ python setup.py register -r pypi
python setup.py sdist bdist_wininst upload -r pypi
```
Add links to the artifacts from download.html
There are links to the artifacts in [download.html](http://www.antlr.org/download.html) already.
### C++
@ -302,6 +378,7 @@ On a Mac (with XCode 7+ installed):
```bash
cd runtime/Cpp
./deploy-macos.sh
cp antlr4-cpp-runtime-macos.zip ~/antlr/sites/website-antlr4/download/antlr4-cpp-runtime-4.6-macos.zip
```
On any Mac or Linux machine:
@ -309,6 +386,7 @@ On any Mac or Linux machine:
```bash
cd runtime/Cpp
./deploy-source.sh
cp antlr4-cpp-runtime-source.zip ~/antlr/sites/website-antlr4/download/antlr4-cpp-runtime-4.6-source.zip
```
On a Windows machine the build scripts checks if VS 2013 and/or VS 2015 are installed and builds binaries for each, if found. This script requires 7z to be installed (http://7-zip.org).
@ -316,15 +394,17 @@ On a Windows machine the build scripts checks if VS 2013 and/or VS 2015 are inst
```bash
cd runtime/Cpp
deploy-windows.cmd
cp antlr4-cpp-runtime-vs2015.zip ~/antlr/sites/website-antlr4/download/antlr4-cpp-runtime-4.6-vs2015.zip
```
Move target to website (**_rename to a specific ANTLR version first if needed_**):
```bash
pushd ~/antlr/sites/website-antlr4/download
git add antlr4cpp-runtime-macos.zip
git add antlr4cpp-runtime-windows.zip
git add antlr4cpp-runtime-source.zip
# vi index.html
git add antlr4cpp-runtime-4.6-macos.zip
git add antlr4cpp-runtime-4.6-windows.zip
git add antlr4cpp-runtime-4.6-source.zip
git commit -a -m 'update C++ runtime'
git push origin gh-pages
popd
@ -332,7 +412,7 @@ popd
## Update javadoc for runtime and tool
First gen javadoc:
First, gen javadoc:
```bash
$ cd antlr4
@ -346,9 +426,9 @@ cd ~/antlr/sites/website-antlr4/api
git checkout gh-pages
git pull origin gh-pages
cd Java
jar xvf ~/.m2/repository/org/antlr/antlr4-runtime/4.5.2/antlr4-runtime-4.5.2-javadoc.jar
jar xvf ~/.m2/repository/org/antlr/antlr4-runtime/4.6/antlr4-runtime-4.6-javadoc.jar
cd ../JavaTool
jar xvf ~/.m2/repository/org/antlr/antlr4/4.5.2/antlr4-4.5.2-javadoc.jar
jar xvf ~/.m2/repository/org/antlr/antlr4/4.6/antlr4-4.6-javadoc.jar
git commit -a -m 'freshen api doc'
git push origin gh-pages
```

View File

@ -29,7 +29,7 @@ The underlying process of running the tests is quite a complicated setup to cate
## Generating JUnit Tests
The test specification part makes heavy use of the StringTemplate engine to allow defining target language agnostic tests. For that all tests are described in template (`stg`) files. You can find them in the [templates](../runtime-testsuite/resources/org/antlr/v4/test/runtime/templates) subfolder of the runtime tests folder. Read more about the folder structure in the [adding-tests.md](adding-tests.md) file. As lined out there you have to run
The test specification part makes heavy use of the StringTemplate engine to allow defining target language agnostic tests. For that all tests are described in template (`stg`) files. You can find them in the [templates](../runtime-testsuite/resources/org/antlr/v4/test/runtime/templates) subfolder of the runtime tests folder. Read more about the folder structure in the [antlr-project-testing.md](antlr-project-testing.md) file. As lined out there you have to run
```bash
$ mvn -Pgen generate-test-sources

View File

@ -1,47 +1,99 @@
# ANTLR4 Language Target, Runtime for Swift
### Usage
## Install ANTLR4
#### 1. Install ANTLR4
Make sure you have the ANTLR
installed.[The getting started guide](getting-started.md) should get
you started.
[The getting started guide](getting-started.md) should get you started.
## Create a Swift lexer or parser
This is pretty much the same as creating a Java lexer or parser,
except you need to specify the language target, for example:
#### 2. create a Swift lexer or parser
This is pretty much the same as creating a Java lexer or parser, except you need to specify the language target, for example:
```
$ antlr4 -Dlanguage=Swift MyGrammar.g4
```
For a full list of antlr4 tool options, please visit the
[tool documentation page](tool-options.md).
```
$ antlr4 -Dlanguage=Swift MyGrammar.g4
```
For a full list of antlr4 tool options, please visit the [tool documentation page](tool-options.md).
## Build your Swift project with ANTLR runtime
#### 3. Get the Swift ANTLR runtime
You will find Swift runtime (framework project) in
The following instructions are assuming Xcode as the IDE:
```
antlr4/runtime/Swift
```
* __Add parser/lexer to project__. Make sure the parsers/lexers
generated in __step 2__ are added to the project. To do this, you can
drag the generated files from Finder to the Xcode IDE. Remember to
check __Copy items if needed__ to make sure the files are actually
moved into the project folder instead of symbolic links (see the
screenshot below). After moving you will be able to see your files in
the project navigator. But when you open one of the files, you will
see Xcode complaining the module "Antlr4" could not be found at the
import statement. This is expected, since we still need the ANTLR
Swift runtime for those missing symbols.
#### 4. Example playground
<img src=images/dragfile.png width="500">
* __Download ANTLR runtime__. Due to unstable ABI of Swift language,
there will not be a single "library" for the Swift ANTLR runtime for
now. To get Swift ANTLR runtime, clone the ANTLR repository. Open it
in finder. From the root directory of the repo, go to runtime/Swift
folder. You will see the Xcode project manifest file:
__Antlr4.xcodeproj__.
* __Import ANTLR Swift runtime into project__. Drag Antlr4.xcodeproj
into your project, after this is done, your Xcode project navigator
will be something like the screenshot below. In this case, your own
project is "Smalltalk", and you will be able to see the
Antlr4.xcodeproj shown as a contained project. The error message will
still be there, that's because we still need to tell Xcode how to find
the runtime.
<img src=images/xcodenav.png width="300">
* __Build ANTLR runtime__. By expanding the "Products" folder in the
inner project (Antlr4.xcodeproj), you will see two Antlr4.framework
files. ".framework" file is the swift version of ".jar", ".a" as in
JAVA, C/C++ Initially those two files should be red, that's because
they are not built. To build, click the "target selection" button
right next to your Xcode run button. And in the drop down select the
target you want to build. And you will see the two Antlr4.framework
files are for iOS and OSX, as shown below. After target selection,
press "CMD+B", and Xcode will build the framework for you. Then you
will see one of the frameworks become black.
<img src=images/targetselection.png width="500">
* __Add dependencies__. Simply adding ANTLR Swift runtime and build
the artifact is not enough. You still need to specify
dependencies. Click your own project (Smalltalk), and you will see
project setting page. Go to "Build Phase", and inside it make sure
your ANTLR Swift runtime framework is added to both "__Target
Dependencies__" and "__Link Binary With Libraries__" sections, as
shown below. After correctly added dependencies, the error message for
importing library will be gone.
<img src=images/xcodedep.png width="800">
## Example playground
The Swift runtime includes an Xcode playground to get started with.
In Xcode, open `antlr4/runtime/Swift/Antlr4.xcworkspace`. Select
"Antlr4 OSX > My Mac" as the build target, and build the project as normal.
The playground should then be active.
First go to the ANTLR4 repository, and open
`runtime/Swift/Antlr4.xcworkspace` in Xcode. Select "Antlr4 OSX > My
Mac" as the build target, and build the project as normal. The
playground should then be active.
The playground includes a simple grammar called "Hello", and an example for
walking the parse tree. You should see in the playground output that it is
printing messages for each node in the parse tree as it walks.
The playground includes a simple grammar called "Hello", and an
example for walking the parse tree. You should see in the playground
output that it is printing messages for each node in the parse tree as
it walks.
The playground shows how to create a lexer, token stream, and parser, and
how to execute the parse.
The grammar is defined in the playground's `Resources/Hello.g4`. The
parser was generated from the grammar using ANTLR like this:
The grammar is defined in the playground's `Resources/Hello.g4`. The parser
was generated from the grammar using Antlr4 like this:
```
cd 'antlr4/runtime/Swift/Antlr4 playground.playground/Resources'
```
antlr4 -Dlanguage=Swift -visitor -o ../Sources/Autogen Hello.g4
```
The example tree walker is in `Sources/HelloWalker.swift`.
The example tree walker is in Sources/HelloWalker.swift.

View File

@ -14,7 +14,7 @@ This page lists the available and upcoming ANTLR runtimes. Please note that you
New features generally appear in the Java target and then migrate to the other targets, but these other targets don't always get updated in the same overall tool release. This section tries to identify features added to Java that have not been added to the other targets.
|Feature|Java|C&sharp;|JavaScript|Python2|Python3|Swift|C++|
|---|---|---|---|---|---|---|---|
|Ambiguous tree construction|4.5.1|-|-|-|-|-|-|
|Feature|Java|C&sharp;|Python2|Python3|JavaScript|Go|C++|Swift|
|---|---|---|---|---|---|---|---|---|
|Ambiguous tree construction|4.5.1|-|-|-|-|-|-|-|

View File

@ -13,7 +13,7 @@
</parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>ANTLR 4</name>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>antlr4-runtime-test-annotations</artifactId>

View File

@ -10,7 +10,7 @@
<parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
</parent>
<artifactId>antlr4-runtime-testsuite</artifactId>
<name>ANTLR 4 Runtime Tests (2nd generation)</name>
@ -79,107 +79,59 @@
</dependency>
</dependencies>
<build>
<testSourceDirectory>test</testSourceDirectory>
<resources>
<resource>
<directory>resources</directory>
</resource>
<resource>
<directory>../runtime</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>**/csharp/Test*.java</include>
<include>**/java/Test*.java</include>
<include>**/go/Test*.java</include>
<include>**/javascript/node/Test*.java</include>
<include>**/python2/Test*.java</include>
<include>**/python3/Test*.java</include>
<include>${antlr.tests.swift}</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<build>
<testSourceDirectory>test</testSourceDirectory>
<resources>
<resource>
<directory>resources</directory>
</resource>
<resource>
<directory>../runtime</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>**/csharp/Test*.java</include>
<include>**/java/Test*.java</include>
<include>**/go/Test*.java</include>
<include>**/javascript/node/Test*.java</include>
<include>**/python2/Test*.java</include>
<include>**/python3/Test*.java</include>
<include>${antlr.tests.swift}</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>includeSwiftTests</id>
<activation>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<antlr.tests.swift>**/swift/Test*.java</antlr.tests.swift>
</properties>
</profile>
<profile>
<id>gen</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<phase>generate-test-sources</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.antlr.v4.testgen.TestGenerator</mainClass>
<arguments>
<argument>-root</argument>
<argument>${basedir}</argument>
<argument>-outdir</argument>
<argument>${basedir}/test</argument>
<argument>-templates</argument>
<argument>${basedir}/resources/org/antlr/v4/test/runtime/templates</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/Test*.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<profiles>
<profile>
<id>includeSwiftTests</id>
<activation>
<os>
<family>mac</family>
</os>
</activation>
<properties>
<antlr.tests.swift>**/swift/Test*.java</antlr.tests.swift>
</properties>
</profile>
</profiles>
</project>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>antlr4-runtime-test-annotation-processors</artifactId>

View File

@ -55,7 +55,9 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -508,7 +510,7 @@ public class BaseCppTest implements RuntimeTestSupport {
return files;
}
private String runProcess(ProcessBuilder builder, String description) throws Exception {
private String runProcess(ProcessBuilder builder, String description, boolean showStderr) throws Exception {
// System.out.println("BUILDER: "+builder.command());
Process process = builder.start();
StreamVacuum stdoutVacuum = new StreamVacuum(process.getInputStream());
@ -521,10 +523,10 @@ public class BaseCppTest implements RuntimeTestSupport {
String output = stdoutVacuum.toString();
if ( stderrVacuum.toString().length()>0 ) {
this.stderrDuringParse = stderrVacuum.toString();
// System.err.println(this.stderrDuringParse);
if ( showStderr ) System.err.println(this.stderrDuringParse);
}
if (errcode != 0) {
String err = "execution failed with error code: "+errcode;
String err = "execution of '"+description+"' failed with error code: "+errcode;
if ( this.stderrDuringParse!=null ) {
this.stderrDuringParse += err;
}
@ -536,11 +538,11 @@ public class BaseCppTest implements RuntimeTestSupport {
return output;
}
private String runCommand(String command[], String workPath, String description) throws Exception {
private String runCommand(String command[], String workPath, String description, boolean showStderr) throws Exception {
ProcessBuilder builder = new ProcessBuilder(command);
builder.directory(new File(workPath));
return runProcess(builder, description);
return runProcess(builder, description, showStderr);
}
// TODO: add a buildRuntimeOnWindows variant.
@ -550,8 +552,9 @@ public class BaseCppTest implements RuntimeTestSupport {
try {
String command[] = { "cmake", ".", /*"-DCMAKE_CXX_COMPILER=clang++",*/ "-DCMAKE_BUILD_TYPE=release" };
if (runCommand(command, runtimePath, "antlr runtime cmake") == null)
if (runCommand(command, runtimePath, "antlr runtime cmake", false) == null) {
return false;
}
}
catch (Exception e) {
System.err.println("can't configure antlr cpp runtime cmake file");
@ -559,11 +562,21 @@ public class BaseCppTest implements RuntimeTestSupport {
try {
String command[] = { "make", "-j", "8" }; // Assuming a reasonable amount of available CPU cores.
if (runCommand(command, runtimePath, "building antlr runtime") == null)
if (runCommand(command, runtimePath, "building antlr runtime", true) == null)
return false;
}
catch (Exception e) {
System.err.println("can't compile antlr cpp runtime");
e.printStackTrace(System.err);
try {
String command[] = { "ls", "-la" };
String output = runCommand(command, runtimePath + "/dist/", "printing library folder content", true);
System.out.println(output);
}
catch (Exception e2) {
System.err.println("can't even list folder content");
e2.printStackTrace(System.err);
}
}
/* for debugging
@ -593,7 +606,7 @@ public class BaseCppTest implements RuntimeTestSupport {
if ( !runtimeBuiltOnce ) {
try {
String command[] = {"clang++", "--version"};
String output = runCommand(command, tmpdir, "printing compiler version");
String output = runCommand(command, tmpdir, "printing compiler version", false);
System.out.println("Compiler version is: "+output);
}
catch (Exception e) {
@ -613,7 +626,7 @@ public class BaseCppTest implements RuntimeTestSupport {
String libExtension = (getOS().equals("mac")) ? "dylib" : "so";
try {
String command[] = { "ln", "-s", runtimePath + "/dist/libantlr4-runtime." + libExtension };
if (runCommand(command, tmpdir, "sym linking C++ runtime") == null)
if (runCommand(command, tmpdir, "sym linking C++ runtime", true) == null)
return null;
}
catch (Exception e) {
@ -625,7 +638,7 @@ public class BaseCppTest implements RuntimeTestSupport {
try {
List<String> command2 = new ArrayList<String>(Arrays.asList("clang++", "-std=c++11", "-I", includePath, "-L.", "-lantlr4-runtime", "-o", "a.out"));
command2.addAll(allCppFiles(tmpdir));
if (runCommand(command2.toArray(new String[0]), tmpdir, "building test binary") == null) {
if (runCommand(command2.toArray(new String[0]), tmpdir, "building test binary", true) == null) {
return null;
}
}
@ -642,7 +655,7 @@ public class BaseCppTest implements RuntimeTestSupport {
builder.directory(new File(tmpdir));
Map<String, String> env = builder.environment();
env.put("LD_PRELOAD", runtimePath + "/dist/libantlr4-runtime." + libExtension);
String output = runProcess(builder, "running test binary");
String output = runProcess(builder, "running test binary", false);
if ( output.length()==0 ) {
output = null;
}
@ -664,11 +677,21 @@ public class BaseCppTest implements RuntimeTestSupport {
protected String locateRuntime() {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final URL runtimeSrc = loader.getResource("Cpp");
if (runtimeSrc == null) {
final URL runtimeURL = loader.getResource("Cpp");
if (runtimeURL == null) {
throw new RuntimeException("Cannot find runtime");
}
return runtimeSrc.getPath();
// Windows not getting runtime right. See:
// http://stackoverflow.com/questions/6164448/convert-url-to-normal-windows-filename-java
// it was coming back "/C:/projects/antlr4-l7imv/runtime-testsuite/target/classes/Cpp"
String p;
try {
p = Paths.get(runtimeURL.toURI()).toFile().toString();
}
catch (URISyntaxException use) {
p = "Can't find runtime";
}
return p;
}
List<ANTLRMessage> getMessagesOfType(List<ANTLRMessage> msgs, Class<? extends ANTLRMessage> c) {

View File

@ -302,30 +302,6 @@ public class LexerExecDescriptors {
}
public static class CharSetWithReversedRange extends BaseLexerTestDescriptor {
public String input = "9";
/**
A
[@0,0:0='9',<1>,1:0]
[@1,1:0='<EOF>',<-1>,1:1]
*/
@CommentHasStringValue
public String output;
public String errors = null;
public String startRule = "";
public String grammarName = "L";
/**
lexer grammar L;
A : [z-a9]+ {<writeln("\"A\"")>} ;
WS : [ \n]+ -> skip ;
*/
@CommentHasStringValue
public String grammar;
}
public static class EOFByItself extends BaseLexerTestDescriptor {
public String input = "";
/**

View File

@ -112,7 +112,7 @@ public class ParseTreesDescriptors {
@Override
public boolean ignore(String targetName) {
return !targetName.matches("Java|Python2|Python3|Node");
return !targetName.matches("Java|Python2|Python3|Node|Swift");
}
}

View File

@ -10,6 +10,30 @@ import org.antlr.v4.test.runtime.BaseLexerTestDescriptor;
import org.antlr.v4.test.runtime.CommentHasStringValue;
public class SemPredEvalLexerDescriptors {
// Test for https://github.com/antlr/antlr4/issues/958
public static class RuleSempredFunction extends BaseLexerTestDescriptor {
public String input = "aaa";
/**
[@0,0:0='a',<1>,1:0]
[@1,1:1='a',<1>,1:1]
[@2,2:2='a',<1>,1:2]
[@3,3:2='<EOF>',<-1>,1:3]
*/
@CommentHasStringValue
public String output;
public String errors = null;
public String startRule = "";
public String grammarName = "L";
/**
lexer grammar L;
T : 'a' {<True()>}? ;
*/
@CommentHasStringValue
public String grammar;
}
public static class DisableRule extends BaseLexerTestDescriptor {
public String input = "enum abc";
/**

View File

@ -1,11 +1,18 @@
# C# target for ANTLR 4
### Note to existing users
### Note to historical users
Versions of ANTLR 4.4.x and before managed the C# target as a [separate tool provided by Sam Harwell](https://github.com/tunnelvisionlabs/antlr4cs/releases/tag/v4.3.0). As of 4.5, we our releasing a (mono-compatible) C# target derived from Sam's with the main tool. ANTLR 4.5 is now able to generate C#, Java, Python 2, Python 3 and JavaScript. Sam continues to work on his version of the ANTLR tool and so a C# target is also available through that.
Versions of ANTLR 4.4.x and before managed the C#
target as part of a [separate tool provided by Sam Harwell](https://github.com/tunnelvisionlabs/antlr4cs/releases/tag/v4.3.0).
As of 4.5, we our releasing a (mono-compatible) C# target together
with the main tool.
This makes it possible to use ANTLR 4 in any C# development environment, including of course Microsoft Visual Studio, but also Xamarin Studio, which runs on MacOS X.
Given Microsoft's recent commitment to *cross-platform developer experiences*, we believe this is a great opportunity for C# developers.
Mono compatibility makes it possible to use ANTLR 4 in any C# development
environment, including of course Microsoft Visual Studio, but also Xamarin Studio, which runs on MacOS X.
Given Microsoft's recent commitment to *cross-platform developer experiences*,
we believe this is a great opportunity for C# developers.
Releasing the runtime with the tool ensures that you can get the exact same behavior across many languages: Java, C#, Python, JavaScript, Go, Swift and C++.
## Getting Started
@ -16,39 +23,37 @@ You can install *any* of the following versions of Java to use this target.
If you already have one of the following installed, you should check to make sure the installation is up-to-date.
* Java 8 runtime environment (x86 or x64)
* Java 8 development kit (x86 or x64, provided that the JRE option is also installed during the development kit installation)
* Java 7 runtime environment (x86 or x64)
* Java 7 development kit (x86 or x64, provided that the JRE option is also installed during the development kit installation)
* Java 6 runtime environment (x86 or x64)
* Java 6 development kit (x86 or x64, provided that the JRE option is also installed during the development kit installation)
### Step 2: Download the tool and runtime, and install the runtime
### Step 2: Download the tool
You need to download the following from the ANTLR web site:
You need to download the ANTLR tool from the ANTLR web site.
This is a Java archive (*.jar) used to generate the C# code from an ANTLR grammar.
1. The ANTLR tool. This is a Java archive (*.jar) used to generate the C# code from an ANTLR grammar.
2. The ANTLR runtime assembly. This is a regular .Net assembly (*.dll).
You then need to install the runtime assembly in the GAC.
This is required to easily reference the runtime from your project.
Go the the directory where you downloaded the runtime, and type the following command:
`gacutil -i Antlr4.Runtime.dll`
### Step 3: Add a reference to the ANTLR runtime in your project
We trust that you know how to do this :-).
### Step 4: Add or create a grammar file (*.g4) in your project
### Step 3: Add or create a grammar file (*.g4) in your project
To avoid confusing your IDE, we suggest setting the build action to None for this file.
See the docs and the book to learn about writing lexer and parser grammars.
### Step 5: Generate the C# code
This can be done either from the cmd line, or by adding a custom pre-build command.
At minimal, the cmd line should look as follows: ``java -jar antlr4-4.5.jar -Dlanguage=CSharp grammar.g4``
### Step 4: Generate the C# code
This can be done either from the cmd line, or by adding a custom pre-build command in your project.
At minimal, the cmd line should look as follows: ``java -jar antlr4-4.6.jar -Dlanguage=CSharp grammar.g4``
This will generate the files, which you can then integrate in your project.
This is just a quick start. The tool has many useful options to control generation, please refer to its documentation.
This is just a quick start. The tool has many useful options to control generation, please refer to its documentation.
### Step 5: Add a reference to the ANTLR runtime in your project
The Antlr 4 standard runtime for C# is now available from NuGet.
We trust that you know how to do add NuGet references to your project :-).
The package id is Antlr.4.Runtime. We do not support other packages.
### Step 6: You're done!
Of course, the generated code is not going to meet your requirement by magic.
@ -60,10 +65,10 @@ While the latter works, it is no longer the recommended approach, because it is
See the web site for examples of using the generated code.
To learn more about ANTLR 4, read the book.
To learn more about ANTLR 4, read [the book](http://a.co/2n4rJlb).
### Visual Studio integration
If you require tighter Visual Studio integration, you can use the tools from Tunnel Vision Labs.
If you require tighter Visual Studio integration, you can use the tools from [Tunnel Vision Labs](http://tunnelvisionlabs.com/).
(please note however that they use a different tool and runtime)

View File

@ -8,7 +8,7 @@
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Antlr4.Runtime</RootNamespace>
<AssemblyName>Antlr4.Runtime</AssemblyName>
<AssemblyName>Antlr4.Runtime.Standard</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<BaseIntermediateOutputPath>obj\net20\</BaseIntermediateOutputPath>
@ -21,7 +21,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\net35\Debug\</OutputPath>
<OutputPath>lib\Debug</OutputPath>
<DefineConstants>DEBUG;TRACE;NET35PLUS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -29,7 +29,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\net35\Release\</OutputPath>
<OutputPath>lib\Release</OutputPath>
<DefineConstants>TRACE;NET35PLUS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>

View File

@ -8,7 +8,7 @@
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Antlr4.Runtime</RootNamespace>
<AssemblyName>Antlr4.Runtime</AssemblyName>
<AssemblyName>Antlr4.Runtime.Standard</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<BaseIntermediateOutputPath>obj\net35\</BaseIntermediateOutputPath>

View File

@ -42,8 +42,8 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("4.5.3.0")]
[assembly: AssemblyVersion("4.6.0")]
#if !COMPACT
[assembly: AssemblyFileVersion("4.5.3.0")]
[assembly: AssemblyInformationalVersion("4.5.3.0")]
[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyInformationalVersion("4.6.0")]
#endif

View File

@ -5,8 +5,6 @@ VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{47C0086D-577C-43DA-ADC7-544F27656E45}"
ProjectSection(SolutionItems) = preProject
..\..\tool\resources\org\antlr\v4\tool\templates\codegen\CSharp\CSharp.stg = ..\..\tool\resources\org\antlr\v4\tool\templates\codegen\CSharp\CSharp.stg
..\..\tool\src\org\antlr\v4\codegen\CSharpTarget.java = ..\..\tool\src\org\antlr\v4\codegen\CSharpTarget.java
..\..\Readme.md = ..\..\Readme.md
EndProjectSection
EndProject

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>Antlr4.Runtime.Standard</id>
<version>4.6.0</version>
<language>en-us</language>
<title>ANTLR 4 Standard Runtime</title>
<description>The standard C# ANTLR 4 runtime from the ANTLR Organization</description>
<summary>The runtime library for parsers generated by the C# target of the standard ANTLR 4 tool.</summary>
<authors>Eric Vergnaud, Terence Parr, Sam Harwell</authors>
<owners>The ANTLR Organization</owners>
<releaseNotes>https://github.com/antlr/antlr4/releases</releaseNotes>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<licenseUrl>https://github.com/antlr/antlr4/blob/master/LICENSE.txt</licenseUrl>
<projectUrl>https://github.com/antlr/antlr4</projectUrl>
<iconUrl>https://raw.github.com/antlr/website-antlr4/master/images/icons/antlr.png</iconUrl>
<copyright>Copyright (c) 2012-2016 The ANTLR Project. All rights reserved.</copyright>
<tags>antlr parsing grammar</tags>
<dependencies />
</metadata>
<files>
<file src="Antlr4.Runtime/lib/Release/Antlr4.Runtime.Standard.dll" target="lib/net35/"/>
</files>
</package>

View File

@ -1 +1 @@
4.5.4
4.6

View File

@ -19,11 +19,11 @@
#
# next make a build folder e.g. ~/buildfolder/
# from the buildfolder, run cmake ~/srcfolder; make
#
#
###############################################################
# # minimum required CMAKE version
# CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.2 FATAL_ERROR)
#
#
# LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake )
#
# # compiler must be 11 or 14
@ -49,7 +49,7 @@
# add_executable(demo main.cpp ${antlr4cpp_src_files_antlrcpptest})
# add_dependencies(demo antlr4cpp antlr4cpp_generation_antlrcpptest)
# target_link_libraries(demo antlr4-runtime)
#
#
###############################################################
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12.2)
@ -65,8 +65,8 @@ set(ANTLR4CPP_EXTERNAL_ROOT ${CMAKE_BINARY_DIR}/externals/antlr4cpp)
# external repository
# GIT_REPOSITORY https://github.com/antlr/antlr4.git
set(ANTLR4CPP_EXTERNAL_REPO "https://github.com/DanMcLaughlin/antlr4.git")
set(ANTLR4CPP_EXTERNAL_TAG "v4.5.4")
set(ANTLR4CPP_EXTERNAL_REPO "https://github.com/antlr/antlr4.git")
set(ANTLR4CPP_EXTERNAL_TAG "4.6-rc1")
if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}")
message(FATAL_ERROR "Unable to find antlr tool. ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION}")
@ -81,13 +81,13 @@ endif()
# set(ANTLR4CPP_JAR_LOCATION ${ANTLR4CPP_EXTERNAL_ROOT}/${ANTLR4CPP_JAR_NAME})
#
# !TODO! Ensure Antlr tool available - copy from internet
#
#
# # !TODO! this shold be calculated based on the tags
# if (NOT ANTLR4CPP_JAR_NAME)
# # default location to find antlr Java binary
# set(ANTLR4CPP_JAR_NAME antlr4-4.5.4-SNAPSHOT.jar)
# endif()
#
#
# if(NOT EXISTS "${ANTLR4CPP_JAR_LOCATION}")
# # download Java tool if not installed
# ExternalProject_ADD(
@ -162,20 +162,20 @@ endforeach(src_path)
set(ANTLR4CPP_LIBS "${INSTALL_DIR}/lib")
# antlr4_shared ${INSTALL_DIR}/lib/libantlr4-runtime.so
# antlr4_static ${INSTALL_DIR}/lib/libantlr4-runtime.a
# antlr4_shared ${INSTALL_DIR}/lib/libantlr4-runtime.so
# antlr4_static ${INSTALL_DIR}/lib/libantlr4-runtime.a
############ Generate runtime #################
# macro to add dependencies to target
#
# Param 1 project name
# Param 1 project name
# Param 1 namespace (postfix for dependencies)
# Param 2 Lexer file (full path)
# Param 3 Parser File (full path)
#
# output
#
# antlr4cpp_src_files_{namespace} - src files for add_executable
# antlr4cpp_src_files_{namespace} - src files for add_executable
# antlr4cpp_include_dirs_{namespace} - include dir for generated headers
# antlr4cpp_generation_{namespace} - for add_dependencies tracking
@ -184,18 +184,18 @@ macro(antlr4cpp_process_grammar
antlr4cpp_project_namespace
antlr4cpp_grammar_lexer
antlr4cpp_grammar_parser)
if(EXISTS "${ANTLR4CPP_JAR_LOCATION}")
message(STATUS "Found antlr tool: ${ANTLR4CPP_JAR_LOCATION}")
else()
message(FATAL_ERROR "Unable to find antlr tool. ANTLR4CPP_JAR_LOCATION:${ANTLR4CPP_JAR_LOCATION}")
endif()
add_custom_target("antlr4cpp_generation_${antlr4cpp_project_namespace}"
COMMAND
COMMAND
${CMAKE_COMMAND} -E make_directory ${ANTLR4CPP_GENERATED_SRC_DIR}
COMMAND
"${Java_JAVA_EXECUTABLE}" -jar "${ANTLR4CPP_JAR_LOCATION}" -Werror -Dlanguage=Cpp -listener -visitor -o "${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}" -package ${antlr4cpp_project_namespace} "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}"
"${Java_JAVA_EXECUTABLE}" -jar "${ANTLR4CPP_JAR_LOCATION}" -Werror -Dlanguage=Cpp -listener -visitor -o "${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}" -package ${antlr4cpp_project_namespace} "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
DEPENDS "${antlr4cpp_grammar_lexer}" "${antlr4cpp_grammar_parser}"
)
@ -213,9 +213,9 @@ macro(antlr4cpp_process_grammar
)
endforeach(generated_file)
message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} Generated: ${generated_files}")
# export generated include directory
set(antlr4cpp_include_dirs_${antlr4cpp_project_namespace} ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace})
message(STATUS "Antlr4Cpp ${antlr4cpp_project_namespace} include: ${ANTLR4CPP_GENERATED_SRC_DIR}/${antlr4cpp_project_namespace}")
endmacro()

View File

@ -3,10 +3,14 @@
* can be found in the LICENSE.txt file in the project root.
*/
#include "misc/Interval.h"
#include "TokenSource.h"
#include "support/StringUtils.h"
#include "CharStream.h"
#include "Recognizer.h"
#include "Vocabulary.h"
#include "misc/Interval.h"
#include "support/StringUtils.h"
#include "support/CPPUtils.h"
#include "CommonToken.h"
@ -149,6 +153,10 @@ antlr4::CharStream *CommonToken::getInputStream() const {
}
std::string CommonToken::toString() const {
return toString(nullptr);
}
std::string CommonToken::toString(Recognizer *r) const {
std::stringstream ss;
std::string channelStr;
@ -164,8 +172,12 @@ std::string CommonToken::toString() const {
txt = "<no text>";
}
std::string typeString = std::to_string(symbolToNumeric(_type));
if (r != nullptr)
typeString = r->getVocabulary().getDisplayName(_type);
ss << "[@" << symbolToNumeric(getTokenIndex()) << "," << symbolToNumeric(_start) << ":" << symbolToNumeric(_stop)
<< "='" << txt << "',<" << symbolToNumeric(_type) << ">" << channelStr << "," << _line << ":"
<< "='" << txt << "',<" << typeString << ">" << channelStr << "," << _line << ":"
<< getCharPositionInLine() << "]";
return ss.str();

View File

@ -150,6 +150,7 @@ namespace antlr4 {
virtual std::string toString() const override;
virtual std::string toString(Recognizer *r) const;
private:
void InitializeInstanceFields();
};

View File

@ -41,7 +41,7 @@ std::map<std::string, size_t> Recognizer::getTokenTypeMap() {
if (iterator != _tokenTypeMapCache.end()) {
result = iterator->second;
} else {
for (size_t i = 0; i < getATN().maxTokenType; ++i) {
for (size_t i = 0; i <= getATN().maxTokenType; ++i) {
std::string literalName = vocabulary.getLiteralName(i);
if (!literalName.empty()) {
result[literalName] = i;

View File

@ -7,7 +7,7 @@
using namespace antlr4;
const std::string RuntimeMetaData::VERSION = "4.5.4";
const std::string RuntimeMetaData::VERSION = "4.6";
std::string RuntimeMetaData::getRuntimeVersion() {
return VERSION;

View File

@ -5,6 +5,8 @@
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
/// The default mechanism for creating tokens. It's used by default in Lexer and

View File

@ -78,7 +78,6 @@
#else
#define ANTLR4CPP_PUBLIC
#endif
#define EXPIMP_TEMPLATE
#else
#define GUID_LIBUUID
#if __GNUC__ >= 6
@ -86,7 +85,6 @@
#else
#define ANTLR4CPP_PUBLIC
#endif
#define EXPIMP_TEMPLATE
#endif
#include "support/guid.h"

View File

@ -11,7 +11,7 @@ namespace antlr4 {
namespace misc {
// Helpers to convert certain unsigned symbols (e.g. Token::EOF) to their original numeric value (e.g. -1)
// and vice version. This is needed mostly for intervals to keep their original order and for toString()
// and vice versa. This is needed mostly for intervals to keep their original order and for toString()
// methods to print the original numeric value (e.g. for tests).
size_t numericToSymbol(ssize_t v);
ssize_t symbolToNumeric(size_t v);

View File

@ -9,7 +9,7 @@
<parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>antlr4-runtime</artifactId>
@ -41,6 +41,7 @@
<version>1.0</version>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>dot</goal>
</goals>

View File

@ -1,6 +1,6 @@
{
"name": "antlr4",
"version": "4.6",
"version": "4.6.0",
"description": "JavaScript runtime for ANTLR4",
"main": "src/antlr4/index.js",
"repository": "antlr/antlr4.git",

View File

@ -0,0 +1,12 @@
publishing to npm
=================
The JavaScript runtime is published on npm.
There is nothing to build since JavaScript is based on source code only.
The JavaScript itself is tested using npm, so assumption is npm is already installed.
The current npm version used is 3.10.9.
The publishing itself relies on the information in src/antlr4/package.json.
To publish, from Terminal, you need to navigate to the src/ directory.
Once there, login: npm login
Then npm publish antlr4
That's it!

View File

@ -484,14 +484,14 @@ class DefaultErrorStrategy(ErrorStrategy):
expecting = self.getExpectedTokens(recognizer)
expectedTokenType = expecting[0] # get any element
if expectedTokenType==Token.EOF:
tokenText = "<missing EOF>"
tokenText = u"<missing EOF>"
else:
name = None
if expectedTokenType < len(recognizer.literalNames):
name = recognizer.literalNames[expectedTokenType]
if name is None and expectedTokenType < len(recognizer.symbolicNames):
name = recognizer.symbolicNames[expectedTokenType]
tokenText = "<missing " + str(name) + ">"
tokenText = u"<missing " + unicode(name) + u">"
current = currentSymbol
lookback = recognizer.getTokenStream().LT(-1)
if current.type==Token.EOF and lookback is not None:

View File

@ -1,59 +0,0 @@
# file GENERATED by distutils, do NOT edit
LICENSE.txt
README.txt
RELEASE-4.5.txt
setup.py
src/antlr4/BufferedTokenStream.py
src/antlr4/CommonTokenFactory.py
src/antlr4/CommonTokenStream.py
src/antlr4/FileStream.py
src/antlr4/InputStream.py
src/antlr4/IntervalSet.py
src/antlr4/LL1Analyzer.py
src/antlr4/Lexer.py
src/antlr4/ListTokenSource.py
src/antlr4/Parser.py
src/antlr4/ParserInterpreter.py
src/antlr4/ParserRuleContext.py
src/antlr4/PredictionContext.py
src/antlr4/Recognizer.py
src/antlr4/RuleContext.py
src/antlr4/Token.py
src/antlr4/Utils.py
src/antlr4/__init__.py
src/antlr4/atn/ATN.py
src/antlr4/atn/ATNConfig.py
src/antlr4/atn/ATNConfigSet.py
src/antlr4/atn/ATNDeserializationOptions.py
src/antlr4/atn/ATNDeserializer.py
src/antlr4/atn/ATNSimulator.py
src/antlr4/atn/ATNState.py
src/antlr4/atn/ATNType.py
src/antlr4/atn/LexerATNSimulator.py
src/antlr4/atn/LexerAction.py
src/antlr4/atn/LexerActionExecutor.py
src/antlr4/atn/ParserATNSimulator.py
src/antlr4/atn/PredictionMode.py
src/antlr4/atn/SemanticContext.py
src/antlr4/atn/Transition.py
src/antlr4/atn/__init__.py
src/antlr4/dfa/DFA.py
src/antlr4/dfa/DFASerializer.py
src/antlr4/dfa/DFAState.py
src/antlr4/dfa/__init__.py
src/antlr4/error/DiagnosticErrorListener.py
src/antlr4/error/ErrorListener.py
src/antlr4/error/ErrorStrategy.py
src/antlr4/error/Errors.py
src/antlr4/error/__init__.py
src/antlr4/tree/Chunk.py
src/antlr4/tree/ParseTreeMatch.py
src/antlr4/tree/ParseTreePattern.py
src/antlr4/tree/ParseTreePatternMatcher.py
src/antlr4/tree/RuleTagToken.py
src/antlr4/tree/TokenTagToken.py
src/antlr4/tree/Tree.py
src/antlr4/tree/Trees.py
src/antlr4/tree/__init__.py
src/antlr4/xpath/XPath.py
src/antlr4/xpath/__init__.py

View File

@ -473,8 +473,6 @@ public class BufferedTokenStream: TokenStream {
public func getText() throws -> String {
try lazyInit()
try fill()
return try getText(Interval.of(0, size() - 1))
}
@ -485,7 +483,7 @@ public class BufferedTokenStream: TokenStream {
if start < 0 || stop < 0 {
return ""
}
try lazyInit()
try fill()
if stop >= tokens.count {
stop = tokens.count - 1
}

View File

@ -255,9 +255,13 @@ public class CommonToken: WritableToken {
}
public var description: String {
return toString(nil)
}
public func toString(_ r: Recognizer<ATNSimulator>?) -> String {
var channelStr: String = ""
if channel > 0 {
channelStr = "channel=\(channel)"
channelStr = ",channel=\(channel)"
}
var txt: String
if let tokenText = getText() {
@ -267,15 +271,19 @@ public class CommonToken: WritableToken {
} else {
txt = "<no text>"
}
let desc: StringBuilder = StringBuilder()
desc.append("[@\(getTokenIndex()),")
desc.append("\(start):\(stop)='\(txt)',")
desc.append("<\(type)>\(channelStr),")
desc.append("\(line):\(getCharPositionInLine())]")
return desc.toString()
var typeString = "\(type)"
if let r = r {
typeString = r.getVocabulary().getDisplayName(type);
}
return "[@"+getTokenIndex()+","+start+":"+stop+"='"+txt+"',<"+typeString+">"+channelStr+","+line+":"+getCharPositionInLine()+"]"
// let desc: StringBuilder = StringBuilder()
// desc.append("[@\(getTokenIndex()),")
// desc.append("\(start):\(stop)='\(txt)',")
// desc.append("<\(typeString)>\(channelStr),")
// desc.append("\(line):\(getCharPositionInLine())]")
//
// return desc.toString()
}
public var visited: Bool {
get {
return _visited

View File

@ -79,6 +79,18 @@ open class ParserRuleContext: RuleContext {
self.start = ctx.start
self.stop = ctx.stop
// copy any error nodes to alt label node
if ctx.children != nil{
self.children = Array<ParseTree>()
// reset parent pointer for any error nodes
for child: ParseTree in ctx.children! {
if child is ErrorNode{
self.children?.append(child)
( (child as! ErrorNode)).parent = self
}
}
}
}
public init(_ parent: ParserRuleContext?, _ invokingStateNumber: Int) {

View File

@ -62,7 +62,7 @@ open class Recognizer<ATNInterpreter:ATNSimulator> {
if result == nil {
result = Dictionary<String, Int>()
let length = self.getATN().maxTokenType
for i in 0..<length {
for i in 0...length {
let literalName: String? = vocabulary.getLiteralName(i)
if literalName != nil {
result![literalName!] = i

View File

@ -232,13 +232,20 @@
* both SLL and LL parsing. Erroneous input will therefore require 2 passes over
* the input.</p>
*/
import Foundation
open class ParserATNSimulator: ATNSimulator {
public let debug: Bool = false
public let debug_list_atn_decisions: Bool = false
public let dfa_debug: Bool = false
public let retry_debug: Bool = false
/** Just in case this optimization is bad, add an ENV variable to turn it off */
public static let TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT: Bool = {
if let value = ProcessInfo.processInfo.environment["TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT"] {
return NSString(string: value).boolValue
}
return false
}()
internal final var parser: Parser
public final var decisionToDFA: [DFA]
@ -1441,6 +1448,10 @@ open class ParserATNSimulator: ATNSimulator {
}
let length = p.getNumberOfTransitions()
for i in 0..<length {
if i == 0 &&
canDropLoopEntryEdgeInLeftRecursiveRule(config) {
continue
}
let t: Transition = p.transition(i)
let continueCollecting: Bool =
!(t is ActionTransition) && collectPredicates
@ -1506,7 +1517,168 @@ open class ParserATNSimulator: ATNSimulator {
//print("That took: "+(finishTime-startTime)+ " ms");
}
/** Implements first-edge (loop entry) elimination as an optimization
* during closure operations. See antlr/antlr4#1398.
*
* The optimization is to avoid adding the loop entry config when
* the exit path can only lead back to the same
* StarLoopEntryState after popping context at the rule end state
* (traversing only epsilon edges, so we're still in closure, in
* this same rule).
*
* We need to detect any state that can reach loop entry on
* epsilon w/o exiting rule. We don't have to look at FOLLOW
* links, just ensure that all stack tops for config refer to key
* states in LR rule.
*
* To verify we are in the right situation we must first check
* closure is at a StarLoopEntryState generated during LR removal.
* Then we check that each stack top of context is a return state
* from one of these cases:
*
* 1. 'not' expr, '(' type ')' expr. The return state points at loop entry state
* 2. expr op expr. The return state is the block end of internal block of (...)*
* 3. 'between' expr 'and' expr. The return state of 2nd expr reference.
* That state points at block end of internal block of (...)*.
* 4. expr '?' expr ':' expr. The return state points at block end,
* which points at loop entry state.
*
* If any is true for each stack top, then closure does not add a
* config to the current config set for edge[0], the loop entry branch.
*
* Conditions fail if any context for the current config is:
*
* a. empty (we'd fall out of expr to do a global FOLLOW which could
* even be to some weird spot in expr) or,
* b. lies outside of expr or,
* c. lies within expr but at a state not the BlockEndState
* generated during LR removal
*
* Do we need to evaluate predicates ever in closure for this case?
*
* No. Predicates, including precedence predicates, are only
* evaluated when computing a DFA start state. I.e., only before
* the lookahead (but not parser) consumes a token.
*
* There are no epsilon edges allowed in LR rule alt blocks or in
* the "primary" part (ID here). If closure is in
* StarLoopEntryState any lookahead operation will have consumed a
* token as there are no epsilon-paths that lead to
* StarLoopEntryState. We do not have to evaluate predicates
* therefore if we are in the generated StarLoopEntryState of a LR
* rule. Note that when making a prediction starting at that
* decision point, decision d=2, compute-start-state performs
* closure starting at edges[0], edges[1] emanating from
* StarLoopEntryState. That means it is not performing closure on
* StarLoopEntryState during compute-start-state.
*
* How do we know this always gives same prediction answer?
*
* Without predicates, loop entry and exit paths are ambiguous
* upon remaining input +b (in, say, a+b). Either paths lead to
* valid parses. Closure can lead to consuming + immediately or by
* falling out of this call to expr back into expr and loop back
* again to StarLoopEntryState to match +b. In this special case,
* we choose the more efficient path, which is to take the bypass
* path.
*
* The lookahead language has not changed because closure chooses
* one path over the other. Both paths lead to consuming the same
* remaining input during a lookahead operation. If the next token
* is an operator, lookahead will enter the choice block with
* operators. If it is not, lookahead will exit expr. Same as if
* closure had chosen to enter the choice block immediately.
*
* Closure is examining one config (some loopentrystate, some alt,
* context) which means it is considering exactly one alt. Closure
* always copies the same alt to any derived configs.
*
* How do we know this optimization doesn't mess up precedence in
* our parse trees?
*
* Looking through expr from left edge of stat only has to confirm
* that an input, say, a+b+c; begins with any valid interpretation
* of an expression. The precedence actually doesn't matter when
* making a decision in stat seeing through expr. It is only when
* parsing rule expr that we must use the precedence to get the
* right interpretation and, hence, parse tree.
*
* @since 4.6
*/
internal func canDropLoopEntryEdgeInLeftRecursiveRule(_ config: ATNConfig) -> Bool {
if ParserATNSimulator.TURN_OFF_LR_LOOP_ENTRY_BRANCH_OPT {
return false
}
let p: ATNState = config.state
guard let configContext = config.context else {
return false
}
// First check to see if we are in StarLoopEntryState generated during
// left-recursion elimination. For efficiency, also check if
// the context has an empty stack case. If so, it would mean
// global FOLLOW so we can't perform optimization
if p.getStateType() != ATNState.STAR_LOOP_ENTRY ||
!( (p as! StarLoopEntryState)).precedenceRuleDecision || // Are we the special loop entry/exit state?
configContext.isEmpty() || // If SLL wildcard
configContext.hasEmptyPath(){
return false
}
// Require all return states to return back to the same rule
// that p is in.
let numCtxs: Int = configContext.size()
for i in 0 ..< numCtxs { // for each stack context
let returnState: ATNState = atn.states[configContext.getReturnState(i)]!
if returnState.ruleIndex != p.ruleIndex
{return false}
}
let decisionStartState: BlockStartState = (p.transition(0).target as! BlockStartState)
let blockEndStateNum: Int = decisionStartState.endState!.stateNumber
let blockEndState: BlockEndState = (atn.states[blockEndStateNum] as! BlockEndState)
// Verify that the top of each stack context leads to loop entry/exit
// state through epsilon edges and w/o leaving rule.
for i in 0 ..< numCtxs { // for each stack context
let returnStateNumber: Int = configContext.getReturnState(i)
let returnState: ATNState = atn.states[returnStateNumber]!
// all states must have single outgoing epsilon edge
if returnState.getNumberOfTransitions() != 1 || !returnState.transition(0).isEpsilon(){
return false
}
// Look for prefix op case like 'not expr', (' type ')' expr
let returnStateTarget: ATNState = returnState.transition(0).target
if returnState.getStateType() == ATNState.BLOCK_END &&
returnStateTarget == p {
continue
}
// Look for 'expr op expr' or case where expr's return state is block end
// of (...)* internal block; the block end points to loop back
// which points to p but we don't need to check that
if returnState == blockEndState{
continue
}
// Look for ternary expr ? expr : expr. The return state points at block end,
// which points at loop entry state
if returnStateTarget == blockEndState{
continue
}
// Look for complex prefix 'between expr and expr' case where 2nd expr's
// return state points at block end state of (...)* internal block
if returnStateTarget.getStateType() == ATNState.BLOCK_END &&
returnStateTarget.getNumberOfTransitions() == 1 &&
returnStateTarget.transition(0).isEpsilon() &&
returnStateTarget.transition(0).target == p{
continue
}
// anything else ain't conforming
return false
}
return true
}
open func getRuleName(_ index: Int) -> String {
if index >= 0 {
return parser.getRuleNames()[index]

View File

@ -10,7 +10,7 @@
<parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
</parent>
<artifactId>antlr4-tool-testsuite</artifactId>
<name>ANTLR 4 Tool Tests</name>

View File

@ -320,4 +320,21 @@ public class TestSymbolIssues extends BaseJavaToolTest {
testErrors(test, false);
}
@Test public void testCharsCollision() throws Exception {
String[] test = {
"lexer grammar L;\n" +
"TOKEN_RANGE: [aa-f];\n" +
"TOKEN_RANGE_2: [A-FD-J];\n" +
"TOKEN_RANGE_3: 'Z' | 'K'..'R' | 'O'..'V';\n" +
"TOKEN_RANGE_4: 'g'..'l' | [g-l];\n", // Handling in ATNOptimizer.
"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4:2:18: chars \"a-f\" used multiple times in set [aa-f]\n" +
"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4:3:18: chars \"D-J\" used multiple times in set [A-FD-J]\n" +
"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4:4:13: chars \"O-V\" used multiple times in set 'Z' | 'K'..'R' | 'O'..'V'\n" +
"warning(" + ErrorType.CHARACTERS_COLLISION_IN_SET.code + "): L.g4::: chars \"g-l\" used multiple times in set [g-l]\n"
};
testErrors(test, false);
}
}

View File

@ -487,11 +487,39 @@ public class TestToolSyntaxErrors extends BaseJavaToolTest {
"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";
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:2:8: string literals and sets cannot be empty: ''\n" +
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:2:16: string literals and sets cannot be empty: ''\n" +
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:3:8: string literals and sets cannot be empty: ''\n" +
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:4:15: string literals and sets cannot be empty: ''\n" +
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): T.g4:5:8: string literals and sets cannot be empty: ''\n";
String[] pair = new String[] {
grammar,
expected
};
super.testErrors(pair, true);
}
@Test public void testInvalidCharSetAndRange() {
String grammar =
"lexer grammar Test;\n" +
"INVALID_RANGE: 'GH'..'LM';\n" +
"INVALID_RANGE_2: 'F'..'A' | 'Z';\n" +
"VALID_STRING_LITERALS: '\\u1234' | '\\t' | [\\-\\]];\n" +
"INVALID_CHAR_SET: [f-az][];\n" +
"INVALID_CHAR_SET_2: [\\u24\\uA2][\\u24];\n" + //https://github.com/antlr/antlr4/issues/1077
"INVALID_CHAR_SET_3: [\\t\\{];";
String expected =
"error(" + ErrorType.INVALID_LITERAL_IN_LEXER_SET.code + "): Test.g4:2:23: multi-character literals are not allowed in lexer sets: 'GH'\n" +
"error(" + ErrorType.INVALID_LITERAL_IN_LEXER_SET.code + "): Test.g4:2:29: multi-character literals are not allowed in lexer sets: 'LM'\n" +
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): Test.g4:3:26: string literals and sets cannot be empty: 'F'..'A'\n" +
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): Test.g4:5:23: string literals and sets cannot be empty: [f-a]\n" +
"error(" + ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED.code + "): Test.g4:5:29: string literals and sets cannot be empty: []\n" +
"error(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:6:23: invalid escape sequence\n" +
"error(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:6:33: invalid escape sequence\n" +
"error(" + ErrorType.INVALID_ESCAPE_SEQUENCE.code + "): Test.g4:7:23: invalid escape sequence\n";
String[] pair = new String[] {
grammar,

View File

@ -9,40 +9,40 @@
<parent>
<groupId>org.antlr</groupId>
<artifactId>antlr4-master</artifactId>
<version>4.6-SNAPSHOT</version>
<version>4.6.1-SNAPSHOT</version>
</parent>
<artifactId>antlr4</artifactId>
<name>ANTLR 4 Tool</name>
<url>http://www.antlr.org</url>
<description>The ANTLR 4 grammar compiler.</description>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>ST4</artifactId>
<version>4.0.8</version>
</dependency>
<dependency>
<groupId>org.abego.treelayout</groupId>
<artifactId>org.abego.treelayout.core</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>ST4</artifactId>
<version>4.0.8</version>
</dependency>
<dependency>
<groupId>org.abego.treelayout</groupId>
<artifactId>org.abego.treelayout.core</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
@ -73,6 +73,7 @@
</configuration>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>javadoc</goal>
</goals>

View File

@ -720,6 +720,7 @@ if ( <if(invert)><m.varName> \<= 0 || <else>!<endif>(<expr>) ) {
<if(m.labels)><m.labels:{l | <labelref(l)> = }><endif>ErrorHandler.RecoverInline(this);
}
else {
ErrorHandler.ReportMatch(this);
Consume();
}
>>

View File

@ -43,7 +43,7 @@ cppTypeInitMap ::= [
LexerHeader(lexer, atn, actionFuncs, sempredFuncs, superClass = {antlr4::Lexer}) ::= <<
<namedActions.context>
class <lexer.name> : public <superClass> {
class <file.exportMacro> <lexer.name> : public <superClass> {
public:
<if (lexer.tokens)>
enum {
@ -266,7 +266,7 @@ bool <if (r.factory.g.lexer)><lexer.name><else><parser.name><endif>::<r.name>Sem
ParserHeader(parser, funcs, atn, sempredFuncs, superClass = {antlr4::Parser}) ::= <<
<namedActions.context>
class <parser.name> : public <superClass> {
class <file.exportMacro> <parser.name> : public <superClass> {
public:
<if (parser.tokens)>
enum {
@ -526,7 +526,7 @@ LeftRecursiveRuleFunction(currentRule, args, code, locals, ruleCtx, altLabelCtxs
>>
StructDeclHeader(struct, ctorAttrs, attrs, getters, dispatchMethods, interfaces, extensionMembers) ::= <<
class <struct.name> : public <if (contextSuperClass)><contextSuperClass><else>antlr4::ParserRuleContext<endif><if(interfaces)>, <interfaces; separator=", "><endif> {
class <file.exportMacro> <struct.name> : public <if (contextSuperClass)><contextSuperClass><else>antlr4::ParserRuleContext<endif><if(interfaces)>, <interfaces; separator=", "><endif> {
public:
<attrs: {a | <a>;}; separator="\n">
<if (ctorAttrs)><struct.name>(antlr4::ParserRuleContext *parent, size_t invokingState);<endif>
@ -578,7 +578,7 @@ void <parser.name>::<struct.name>::copyFrom(<struct.name> *ctx) {
>>
AltLabelStructDeclHeader(struct, attrs, getters, dispatchMethods) ::= <<
class <struct.name> : public <currentRule.name; format = "cap">Context {
class <file.exportMacro> <struct.name> : public <currentRule.name; format = "cap">Context {
public:
<struct.name>(<currentRule.name; format = "cap">Context *ctx);
@ -816,7 +816,9 @@ setState(<m.stateNumber>);
<capture>
if (<if (invert)><m.varName> == 0 || <m.varName> == Token::EOF || <else>!<endif>(<expr>)) {
<if (m.labels)><m.labels: {l | <labelref(l)> = }><endif>_errHandler->recoverInline(this);
} else {
}
else {
_errHandler->reportMatch(this);
consume();
}
>>

View File

@ -132,7 +132,7 @@ namespace <file.genPackage> {
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
class <file.grammarName>BaseListener : public <file.grammarName>Listener {
class <file.exportMacro> <file.grammarName>BaseListener : public <file.grammarName>Listener {
public:
<namedActions.baselistenerdeclarations>
@ -192,7 +192,7 @@ namespace <file.genPackage> {
/**
* This interface defines an abstract listener for a parse tree produced by <file.parserName>.
*/
class <file.grammarName>Listener : public antlr4::tree::ParseTreeListener {
class <file.exportMacro> <file.grammarName>Listener : public antlr4::tree::ParseTreeListener {
public:
<namedActions.listenerdeclarations>
@ -248,7 +248,7 @@ namespace <file.genPackage> {
* This class provides an empty implementation of <file.grammarName>Visitor, which can be
* extended to create a visitor which only needs to handle a subset of the available methods.
*/
class <file.grammarName>BaseVisitor : public <file.grammarName>Visitor {
class <file.exportMacro> <file.grammarName>BaseVisitor : public <file.grammarName>Visitor {
public:
<namedActions.basevisitordeclarations>
@ -304,7 +304,7 @@ VisitorFileHeader(file, header, namedActions) ::= <<
* This class defines an abstract visitor for a parse tree
* produced by <file.parserName>.
*/
class <file.grammarName>Visitor : public antlr4::tree::AbstractParseTreeVisitor {
class <file.exportMacro> <file.grammarName>Visitor : public antlr4::tree::AbstractParseTreeVisitor {
public:
<namedActions.visitordeclarations>

View File

@ -405,7 +405,7 @@ func (p *<parser.name>) <currentRule.name; format="cap">(<currentRule.args:{a |
<endif>
}
}()
<if(currentRule.hasLookaheadBlock)>
var _alt int
<endif>
@ -808,6 +808,7 @@ var _lt = p.GetTokenStream().LT(1)<! TODO: Should LT be called always like Invok
p.GetErrorHandler().RecoverInline(p)
<endif>
} else {
p.GetErrorHandler().ReportMatch(p)
p.Consume()
}
>>

View File

@ -643,7 +643,10 @@ setState(<m.stateNumber>);
<capture>
if ( <if(invert)><m.varName> \<= 0 || <else>!<endif>(<expr>) ) {
<if(m.labels)><m.labels:{l | <labelref(l)> = (Token)}><endif>_errHandler.recoverInline(this);
} else {
}
else {
if ( _input.LA(1)==Token.EOF ) matchedEOF = true;
_errHandler.reportMatch(this);
consume();
}
>>

View File

@ -236,7 +236,7 @@ case <index>:
* overriding implementation impossible to maintain.
*/
RuleSempredFunction(r, actions) ::= <<
<if(parser)><parser.name><else><lexer.name><endif>.prototype.<r.name>_sempred = function(localctx, predIndex) {
<if (r.factory.g.lexer)><lexer.name><else><parser.name><endif>.prototype.<r.name>_sempred = function(localctx, predIndex) {
switch(predIndex) {
<actions:{index| case <index>:
return <actions.(index)>;}; separator="\n">
@ -523,6 +523,7 @@ this.state = <m.stateNumber>;
<if(m.labels)><m.labels:{l | <labelref(l)> = }><endif>this._errHandler.recoverInline(this);
}
else {
this._errHandler.reportMatch(this);
this.consume();
}
>>

View File

@ -493,6 +493,7 @@ self.state = <m.stateNumber>
<if(invert)>if <m.varName> \<= 0 or <expr><else>if not(<expr>)<endif>:
<if(m.labels)><m.labels:{l | <labelref(l)> = }><else> <endif>self._errHandler.recoverInline(self)
else:
self._errHandler.reportMatch(self)
self.consume()
>>

View File

@ -501,6 +501,7 @@ self.state = <m.stateNumber>
<if(invert)>if <m.varName> \<= 0 or <expr><else>if not(<expr>)<endif>:
<if(m.labels)><m.labels:{l | <labelref(l)> = }><else> <endif>self._errHandler.recoverInline(self)
else:
self._errHandler.reportMatch(self)
self.consume()
>>

View File

@ -696,7 +696,9 @@ setState(<m.stateNumber>)
<capture>
if (<if(invert)><m.varName> \<= 0 || <else>!<endif>(<expr>)) {
<if(m.labels)><m.labels:{l | <labelref(l)> = }><endif>try _errHandler.recoverInline(self)<if(m.labels)> as Token<endif>
} else {
}
else {
_errHandler.reportMatch(self)
try consume()
}
>>

View File

@ -112,6 +112,7 @@ public class Tool {
public boolean gen_visitor = false;
public boolean gen_dependencies = false;
public String genPackage = null;
public String exportMacro = null; // C++ specific, need to allow setting a macro to set declspec for generated classes for VC++.
public Map<String, String> grammarOptions = null;
public boolean warnings_are_errors = false;
public boolean longMessages = false;
@ -128,6 +129,7 @@ public class Tool {
new Option("gen_visitor", "-visitor", "generate parse tree visitor"),
new Option("gen_visitor", "-no-visitor", "don't generate parse tree visitor (default)"),
new Option("genPackage", "-package", OptionArgType.STRING, "specify a package/namespace for the generated code"),
new Option("exportMacro", "-export-macro", OptionArgType.STRING, "C++ only, specify a macro for import/export of generated classes"),
new Option("gen_dependencies", "-depend", "generate file dependencies"),
new Option("", "-D<option>=value", "set/override a grammar-level option"),
new Option("warnings_are_errors", "-Werror", "treat warnings as errors"),

View File

@ -18,6 +18,7 @@ import org.antlr.v4.runtime.atn.SetTransition;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.IntervalSet;
import org.antlr.v4.tool.ErrorType;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.Rule;
@ -94,20 +95,34 @@ public class ATNOptimizer {
Transition matchTransition = decision.transition(j).target.transition(0);
if (matchTransition instanceof NotSetTransition) {
throw new UnsupportedOperationException("Not yet implemented.");
} else {
matchSet.addAll(matchTransition.label());
}
IntervalSet set = matchTransition.label();
int minElem = set.getMinElement();
int maxElem = set.getMaxElement();
for (int k = minElem; k <= maxElem; k++) {
if (matchSet.contains(k)) {
char setMin = (char) set.getMinElement();
char setMax = (char) set.getMaxElement();
// TODO: Token is missing (i.e. position in source will not be displayed).
g.tool.errMgr.grammarError(ErrorType.CHARACTERS_COLLISION_IN_SET, g.fileName,
null, (char) minElem + "-" + (char) maxElem, "[" + setMin + "-" + setMax + "]");
break;
}
}
matchSet.addAll(set);
}
Transition newTransition;
if (matchSet.getIntervals().size() == 1) {
if (matchSet.size() == 1) {
newTransition = new AtomTransition(blockEndState, matchSet.getMinElement());
} else {
}
else {
Interval matchInterval = matchSet.getIntervals().get(0);
newTransition = new RangeTransition(blockEndState, matchInterval.a, matchInterval.b);
}
} else {
}
else {
newTransition = new SetTransition(blockEndState, matchSet);
}

View File

@ -39,6 +39,7 @@ import org.antlr.v4.tool.LexerGrammar;
import org.antlr.v4.tool.Rule;
import org.antlr.v4.tool.ast.ActionAST;
import org.antlr.v4.tool.ast.GrammarAST;
import org.antlr.v4.tool.ast.RangeAST;
import org.antlr.v4.tool.ast.TerminalAST;
import org.stringtemplate.v4.ST;
import org.stringtemplate.v4.STGroup;
@ -253,6 +254,7 @@ public class LexerATNFactory extends ParserATNFactory {
ATNState right = newState(b);
int t1 = CharSupport.getCharValueFromGrammarCharLiteral(a.getText());
int t2 = CharSupport.getCharValueFromGrammarCharLiteral(b.getText());
checkRange(a, b, t1, t2);
left.addTransition(new RangeTransition(right, t1, t2));
a.atnState = left;
b.atnState = left;
@ -268,7 +270,10 @@ public class LexerATNFactory extends ParserATNFactory {
if ( t.getType()==ANTLRParser.RANGE ) {
int a = CharSupport.getCharValueFromGrammarCharLiteral(t.getChild(0).getText());
int b = CharSupport.getCharValueFromGrammarCharLiteral(t.getChild(1).getText());
set.add(a, b);
if (checkRange((GrammarAST) t.getChild(0), (GrammarAST) t.getChild(1), a, b)) {
checkSetCollision(associatedAST, set, a, b);
set.add(a,b);
}
}
else if ( t.getType()==ANTLRParser.LEXER_CHAR_SET ) {
set.addAll(getSetFromCharSetLiteral(t));
@ -276,12 +281,12 @@ public class LexerATNFactory extends ParserATNFactory {
else if ( t.getType()==ANTLRParser.STRING_LITERAL ) {
int c = CharSupport.getCharValueFromGrammarCharLiteral(t.getText());
if ( c != -1 ) {
checkSetCollision(associatedAST, set, c);
set.add(c);
}
else {
g.tool.errMgr.grammarError(ErrorType.INVALID_LITERAL_IN_LEXER_SET,
g.fileName, t.getToken(), t.getText());
}
}
else if ( t.getType()==ANTLRParser.TOKEN_REF ) {
@ -307,6 +312,27 @@ public class LexerATNFactory extends ParserATNFactory {
return new Handle(left, right);
}
protected boolean checkRange(GrammarAST leftNode, GrammarAST rightNode, int leftValue, int rightValue) {
boolean result = true;
if (leftValue == -1) {
result = false;
g.tool.errMgr.grammarError(ErrorType.INVALID_LITERAL_IN_LEXER_SET,
g.fileName, leftNode.getToken(), leftNode.getText());
}
if (rightValue == -1) {
result = false;
g.tool.errMgr.grammarError(ErrorType.INVALID_LITERAL_IN_LEXER_SET,
g.fileName, rightNode.getToken(), rightNode.getText());
}
if (!result) return result;
if (rightValue < leftValue) {
g.tool.errMgr.grammarError(ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED,
g.fileName, leftNode.parent.getToken(), leftNode.getText() + ".." + rightNode.getText());
}
return result;
}
/** For a lexer, a string is a sequence of char to match. That is,
* "fog" is treated as 'f' 'o' 'g' not as a single transition in
* the DFA. Machine== o-'f'-&gt;o-'o'-&gt;o-'g'-&gt;o and has n+1 states
@ -315,12 +341,19 @@ public class LexerATNFactory extends ParserATNFactory {
@Override
public Handle stringLiteral(TerminalAST stringLiteralAST) {
String chars = stringLiteralAST.getText();
chars = CharSupport.getStringFromGrammarStringLiteral(chars);
int n = chars.length();
ATNState left = newState(stringLiteralAST);
ATNState right;
chars = CharSupport.getStringFromGrammarStringLiteral(chars);
if (chars == null) {
g.tool.errMgr.grammarError(ErrorType.INVALID_ESCAPE_SEQUENCE,
g.fileName, stringLiteralAST.getToken());
return new Handle(left, left);
}
int n = chars.length();
ATNState prev = left;
ATNState right = null;
for (int i=0; i<n; i++) {
right = null;
for (int i = 0; i < n; i++) {
right = newState(stringLiteralAST);
prev.addTransition(new AtomTransition(right, chars.charAt(i)));
prev = right;
@ -342,34 +375,90 @@ public class LexerATNFactory extends ParserATNFactory {
public IntervalSet getSetFromCharSetLiteral(GrammarAST charSetAST) {
String chars = charSetAST.getText();
chars = chars.substring(1, chars.length()-1);
String cset = '"'+ chars +'"';
chars = chars.substring(1, chars.length() - 1);
String cset = '"' + chars + '"';
IntervalSet set = new IntervalSet();
if (chars.length() == 0) {
g.tool.errMgr.grammarError(ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED,
g.fileName, charSetAST.getToken(), "[]");
return set;
}
// unescape all valid escape char like \n, leaving escaped dashes as '\-'
// so we can avoid seeing them as '-' range ops.
chars = CharSupport.getStringFromGrammarStringLiteral(cset);
// now make x-y become set of char
if (chars == null) {
g.tool.errMgr.grammarError(ErrorType.INVALID_ESCAPE_SEQUENCE,
g.fileName, charSetAST.getToken());
return set;
}
int n = chars.length();
for (int i=0; i< n; i++) {
// now make x-y become set of char
for (int i = 0; i < n; i++) {
int c = chars.charAt(i);
if ( c=='\\' && (i+1)<n && chars.charAt(i+1)=='-' ) { // \-
if (c == '\\' && i+1 < n && chars.charAt(i+1) == '-') { // \-
checkSetCollision(charSetAST, set, '-');
set.add('-');
i++;
}
else if ( (i+2)<n && chars.charAt(i+1)=='-' ) { // range x-y
else if (i+2 < n && chars.charAt(i+1) == '-') { // range x-y
int x = c;
int y = chars.charAt(i+2);
if ( x<=y ) set.add(x,y);
i+=2;
if (x <= y) {
checkSetCollision(charSetAST, set, x, y);
set.add(x,y);
}
else {
g.tool.errMgr.grammarError(ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED,
g.fileName, charSetAST.getToken(), "[" + (char) x + "-" + (char) y + "]");
}
i += 2;
}
else {
checkSetCollision(charSetAST, set, c);
set.add(c);
}
}
return set;
}
protected void checkSetCollision(GrammarAST ast, IntervalSet set, int el) {
if (set.contains(el)) {
g.tool.errMgr.grammarError(ErrorType.CHARACTERS_COLLISION_IN_SET, g.fileName, ast.getToken(),
(char)el, ast.getText());
}
}
protected void checkSetCollision(GrammarAST ast, IntervalSet set, int a, int b) {
for (int i = a; i <= b; i++) {
if (set.contains(i)) {
String setText;
if (ast.getChildren() == null) {
setText = ast.getText();
}
else {
StringBuilder sb = new StringBuilder();
for (Object child : ast.getChildren()) {
if (child instanceof RangeAST) {
sb.append(((RangeAST) child).getChild(0).getText());
sb.append("..");
sb.append(((RangeAST) child).getChild(1).getText());
}
else {
sb.append(((GrammarAST)child).getText());
}
sb.append(" | ");
}
sb.replace(sb.length() - 3, sb.length(), "");
setText = sb.toString();
}
g.tool.errMgr.grammarError(ErrorType.CHARACTERS_COLLISION_IN_SET, g.fileName, ast.getToken(),
(char)a + "-" + (char)b, setText);
break;
}
}
}
@Override
public Handle tokenRef(TerminalAST node) {
// Ref to EOF in lexer yields char transition on -1

View File

@ -12,6 +12,7 @@ import java.util.Map;
public class LexerFile extends OutputFile {
public String genPackage; // from -package cmd-line
public String exportMacro; // from -DexportMacro cmd-line
public boolean genListener; // from -listener cmd-line
public boolean genVisitor; // from -visitor cmd-line
@ModelElement public Lexer lexer;
@ -21,6 +22,7 @@ public class LexerFile extends OutputFile {
super(factory, fileName);
namedActions = buildNamedActions(factory.getGrammar());
genPackage = factory.getGrammar().tool.genPackage;
exportMacro = factory.getGrammar().getOptionString("exportMacro");
genListener = factory.getGrammar().tool.gen_listener;
genVisitor = factory.getGrammar().tool.gen_visitor;
}

View File

@ -23,6 +23,7 @@ import java.util.Set;
*/
public class ListenerFile extends OutputFile {
public String genPackage; // from -package cmd-line
public String exportMacro; // from -DexportMacro cmd-line
public String grammarName;
public String parserName;
/**
@ -61,5 +62,6 @@ public class ListenerFile extends OutputFile {
ActionAST ast = g.namedActions.get("header");
if ( ast!=null ) header = new Action(factory, ast);
genPackage = factory.getGrammar().tool.genPackage;
exportMacro = factory.getGrammar().getOptionString("exportMacro");
}
}

View File

@ -16,6 +16,7 @@ import java.util.Map;
/** */
public class ParserFile extends OutputFile {
public String genPackage; // from -package cmd-line
public String exportMacro; // from -DexportMacro cmd-line
public boolean genListener; // from -listener cmd-line
public boolean genVisitor; // from -visitor cmd-line
@ModelElement public Parser parser;
@ -28,6 +29,7 @@ public class ParserFile extends OutputFile {
Grammar g = factory.getGrammar();
namedActions = buildNamedActions(factory.getGrammar());
genPackage = g.tool.genPackage;
exportMacro = factory.getGrammar().getOptionString("exportMacro");
// need the below members in the ST for Python, C++
genListener = g.tool.gen_listener;
genVisitor = g.tool.gen_visitor;

View File

@ -20,6 +20,7 @@ import java.util.Set;
public class VisitorFile extends OutputFile {
public String genPackage; // from -package cmd-line
public String exportMacro; // from -DexportMacro cmd-line
public String grammarName;
public String parserName;
/**
@ -58,5 +59,6 @@ public class VisitorFile extends OutputFile {
ActionAST ast = g.namedActions.get("header");
if ( ast!=null ) header = new Action(factory, ast);
genPackage = factory.getGrammar().tool.genPackage;
exportMacro = factory.getGrammar().getOptionString("exportMacro");
}
}

View File

@ -28,6 +28,8 @@ public class CharSupport {
ANTLRLiteralEscapedCharValue['\\'] = '\\';
ANTLRLiteralEscapedCharValue['\''] = '\'';
ANTLRLiteralEscapedCharValue['"'] = '"';
ANTLRLiteralEscapedCharValue['-'] = '-';
ANTLRLiteralEscapedCharValue[']'] = ']';
ANTLRLiteralCharValueEscape['\n'] = "\\n";
ANTLRLiteralCharValueEscape['\r'] = "\\r";
ANTLRLiteralCharValueEscape['\t'] = "\\t";
@ -76,32 +78,6 @@ public class CharSupport {
return getCharValueFromCharInGrammarLiteral(literal.substring(1,literal.length()-1));
}
/** Given char x or \t or \u1234 return the char value;
* Unnecessary escapes like '\{' yield -1.
*/
public static int getCharValueFromCharInGrammarLiteral(String cstr) {
switch ( cstr.length() ) {
case 1 :
// 'x'
return cstr.charAt(0); // no escape char
case 2 :
if ( cstr.charAt(0)!='\\' ) return -1;
// '\x' (antlr lexer will catch invalid char)
if ( Character.isDigit(cstr.charAt(1)) ) return -1;
int escChar = cstr.charAt(1);
int charVal = ANTLRLiteralEscapedCharValue[escChar];
if ( charVal==0 ) return -1;
return charVal;
case 6 :
// '\u1234'
if ( !cstr.startsWith("\\u") ) return -1;
String unicodeChars = cstr.substring(2, cstr.length());
return Integer.parseInt(unicodeChars, 16);
default :
return -1;
}
}
public static String getStringFromGrammarStringLiteral(String literal) {
StringBuilder buf = new StringBuilder();
int i = 1; // skip first quote
@ -110,19 +86,60 @@ public class CharSupport {
int end = i+1;
if ( literal.charAt(i) == '\\' ) {
end = i+2;
if ( (i+1)>=n ) break; // ignore spurious \ on end
if ( literal.charAt(i+1) == 'u' ) end = i+6;
if ( i+1 < n && literal.charAt(i+1) == 'u' ) {
for (end = i + 2; end < i + 6; end++) {
if ( end>n ) return null; // invalid escape sequence.
char charAt = literal.charAt(end);
if (!Character.isDigit(charAt) && !(charAt >= 'a' && charAt <= 'f') && !(charAt >= 'A' && charAt <= 'F')) {
return null; // invalid escape sequence.
}
}
}
}
if ( end>n ) break;
if ( end>n ) return null; // invalid escape sequence.
String esc = literal.substring(i, end);
int c = getCharValueFromCharInGrammarLiteral(esc);
if ( c==-1 ) { buf.append(esc); }
if ( c==-1 ) {
return null; // invalid escape sequence.
}
else buf.append((char)c);
i = end;
}
return buf.toString();
}
/** Given char x or \t or \u1234 return the char value;
* Unnecessary escapes like '\{' yield -1.
*/
public static int getCharValueFromCharInGrammarLiteral(String cstr) {
switch ( cstr.length() ) {
case 1:
// 'x'
return cstr.charAt(0); // no escape char
case 2:
if ( cstr.charAt(0)!='\\' ) return -1;
// '\x' (antlr lexer will catch invalid char)
if ( Character.isDigit(cstr.charAt(1)) ) return -1;
int escChar = cstr.charAt(1);
int charVal = ANTLRLiteralEscapedCharValue[escChar];
if ( charVal==0 ) return -1;
return charVal;
case 6:
// '\u1234'
if ( !cstr.startsWith("\\u") ) return -1;
String unicodeChars = cstr.substring(2, cstr.length());
int result = -1;
try {
result = Integer.parseInt(unicodeChars, 16);
}
catch (NumberFormatException e) {
}
return result;
default:
return -1;
}
}
public static String capitalize(String s) {
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}

View File

@ -471,7 +471,7 @@ public class BasicSemanticChecks extends GrammarTreeVisitor {
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);
g.tool.errMgr.grammarError(ErrorType.EMPTY_STRINGS_AND_SETS_NOT_ALLOWED, g.fileName, tree.token, "''");
}
}

View File

@ -982,11 +982,15 @@ public enum ErrorType {
*
* <p>empty strings not allowed</p>
*
* <pre>A: '''test''';</pre>
* <pre>B: '';</pre>
* <pre>C: 'test' '';</pre>
* <pre>
* A: '''test''';
* B: '';
* C: 'test' '';
* D: [];
* E: [f-a];
* </pre>
*/
EMPTY_STRINGS_NOT_ALLOWED(174, "string literals cannot be empty", ErrorSeverity.ERROR),
EMPTY_STRINGS_AND_SETS_NOT_ALLOWED(174, "string literals and sets cannot be empty: <arg>", ErrorSeverity.ERROR),
/**
* Compiler Error 175.
*
@ -1027,6 +1031,19 @@ public enum ErrorType {
* <p>T00: 'a00' -> skip, more;</p>
*/
INCOMPATIBLE_COMMANDS(179, "incompatible commands <arg> and <arg2>", ErrorSeverity.WARNING),
/**
* Compiler Warning 180.
*
* <p>chars "a-f" used multiple times in set [a-fc-m]</p>
*
* <pre>
* A: [aa-z]; // warning
* B: [a-fc-m]; // warning
* </pre>
*
* TODO: Does not work with fragment rules.
*/
CHARACTERS_COLLISION_IN_SET(180, "chars \"<arg>\" used multiple times in set <arg2>", ErrorSeverity.WARNING),
/*
* Backward incompatibility errors

View File

@ -81,6 +81,7 @@ public class Grammar implements AttributeResolver {
parserOptions.add("TokenLabelType");
parserOptions.add("tokenVocab");
parserOptions.add("language");
parserOptions.add("exportMacro");
}
public static final Set<String> lexerOptions = parserOptions;

View File

@ -8,6 +8,7 @@ package org.antlr.v4.tool.ast;
import org.antlr.runtime.Token;
import org.antlr.v4.misc.CharSupport;
import org.antlr.v4.tool.ErrorType;
import java.util.Collections;
import java.util.HashMap;
@ -41,6 +42,10 @@ public abstract class GrammarASTWithOptions extends GrammarAST {
String v = value.getText();
if ( v.startsWith("'") || v.startsWith("\"") ) {
v = CharSupport.getStringFromGrammarStringLiteral(v);
if (v == null) {
g.tool.errMgr.grammarError(ErrorType.INVALID_ESCAPE_SEQUENCE, g.fileName, value.getToken());
v = "";
}
}
return v;
}