Merge branch 'master' into patch-1

This commit is contained in:
Terence Parr 2020-11-24 10:21:47 -08:00 committed by GitHub
commit bb2a1ecbad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
198 changed files with 21655 additions and 1075 deletions

5
.gitignore vendored
View File

@ -3,7 +3,7 @@ target/
# ... but not code generation targets
!tool/src/org/antlr/v4/codegen/target/
# Node.js (npm and typings) cached dependencies
# Node.js (npm and typings) cached dependencies
node_modules/
typings/
@ -98,3 +98,6 @@ xcuserdata
javac-services.0.log
javac-services.0.log.lck
test/
# Don't ignore python tests
!runtime/Python3/test/

View File

@ -152,6 +152,10 @@ matrix:
jdk: openjdk8
env: TARGET=csharp
stage: main-test
- os: linux
jdk: openjdk8
env: TARGET=dart
stage: main-test
- os: linux
language: php
php:
@ -199,6 +203,9 @@ matrix:
jdk: openjdk8
env: TARGET=javascript
stage: main-test
before_install:
- nvm install 14 # otherwise it runs by default on node 8
- f="./.travis/before-install-linux-javascript.sh"; ! [ -x "$f" ] || "$f"
- os: linux
dist: trusty
jdk: openjdk8
@ -211,7 +218,7 @@ before_install:
script:
- |
cd runtime-testsuite;
travis_wait 40 ../.travis/run-tests-$TARGET.sh;
rc=$?;
cat target/surefire-reports/*.dumpstream || true;
travis_wait 40 ../.travis/run-tests-$TARGET.sh
rc=$?
cat target/surefire-reports/*.dumpstream || true
exit $rc

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -euo pipefail
wget https://storage.googleapis.com/dart-archive/channels/stable/release/2.8.4/linux_packages/dart_2.8.4-1_amd64.deb
sudo dpkg -i ./dart_2.8.4-1_amd64.deb
sudo rm ./dart_2.8.4-1_amd64.deb
sudo apt-get install -f

View File

@ -2,7 +2,6 @@
set -euo pipefail
sudo apt-get update -qq
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -qq nodejs
node --version
# use v14 and check
echo node version: $(node --version)

4
.travis/run-tests-dart.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
set -euo pipefail
mvn -q -Dparallel=classes -DthreadCount=4 -Dtest=dart.* test

View File

@ -2,4 +2,8 @@
set -euo pipefail
mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=javascript.* test
cd ../runtime/JavaScript
npm install
npm link
cd ../../runtime-testsuite
mvn -q -Dparallel=methods -DthreadCount=1 -Dtest=javascript.* test

View File

@ -23,6 +23,7 @@ ANTLR project lead and supreme dictator for life
* [Ewan Mellor](https://github.com/ewanmellor), [Hanzhou Shi](https://github.com/hanjoes) (Swift target merging)
* [Ben Hamilton](https://github.com/bhamiltoncx) (Full Unicode support in serialized ATN and all languages' runtimes for code points > U+FFFF)
* [Marcos Passos](https://github.com/marcospassos) (PHP target)
* [Lingyu Li](https://github.com/lingyv-li) (Dart target)
## Useful information

View File

@ -8,6 +8,7 @@ install:
- git submodule update --init --recursive
- cinst -y php --params "/InstallDir:C:\tools\php"
- cinst -y composer
- cinst -y dart-sdk --version=2.8.4
build_script:
- mvn -DskipTests install --batch-mode
- msbuild /target:restore /target:rebuild /property:Configuration=Release /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /verbosity:detailed runtime/CSharp/runtime/CSharp/Antlr4.dotnet.sln
@ -15,7 +16,7 @@ build_script:
after_build:
- msbuild /target:pack /property:Configuration=Release /verbosity:detailed runtime/CSharp/runtime/CSharp/Antlr4.dotnet.sln
test_script:
- mvn install -Dantlr-php-php="C:\tools\php\php.exe" -Dantlr-python2-python="C:\Python27\python.exe" -Dantlr-python3-python="C:\Python35\python.exe" -Dantlr-javascript-nodejs="C:\Program Files (x86)\nodejs\node.exe" --batch-mode
- mvn install -Dantlr-php-php="C:\tools\php\php.exe" -Dantlr-dart-dart="C:\tools\dart-sdk\bin\dart.exe" -Dantlr-dart-pub="C:\tools\dart-sdk\bin\pub.bat" -Dantlr-dart-dart2native="C:\tools\dart-sdk\bin\dart2native.bat" -Dantlr-python2-python="C:\Python27\python.exe" -Dantlr-python3-python="C:\Python35\python.exe" --batch-mode
artifacts:
- path: 'runtime\**\*.nupkg'
name: NuGet

View File

@ -1,5 +1,9 @@
ANTLR Project Contributors Certification of Origin and Rights
NOTE: This tool is mature and Terence is mostly occupied elsewhere. We
can't accept any changes that could have widespread effects on thousands
of existing projects. Sorry!
All contributors to ANTLR v4 must formally agree to abide by this
certificate of origin by signing on the bottom with their github
userid, full name, email address (you can obscure your e-mail, but it
@ -204,6 +208,7 @@ YYYY/MM/DD, github id, Full name, email
2018/07/03, jgoppert, James Goppert, james.goppert@gmail.com
2018/07/27, Maksim Novikov, mnovikov.work@gmail.com
2018/08/03, ENDOH takanao, djmchl@gmail.com
2018/10/08, xsIceman, Andreas Skaar, andreas.skaar@gmail.com
2018/10/18, edirgarcia, Edir García Lazo, edirgl@hotmail.com
2018/07/31, Lucas Henrqiue, lucashenrique580@gmail.com
2018/08/03, ENDOH takanao, djmchl@gmail.com
@ -214,6 +219,7 @@ YYYY/MM/DD, github id, Full name, email
2018/11/29, hannemann-tamas, Ralf Hannemann-Tamas, ralf.ht@gmail.com
2018/12/20, WalterCouto, Walter Couto, WalterCouto@users.noreply.github.com
2018/12/23, youkaichao, Kaichao You, youkaichao@gmail.com
2019/01/02, wkhemir, Wail Khemir, khemirwail@gmail.com
2019/01/16, kuegi, Markus Zancolo, markus.zancolo@roomle.com
2019/02/06, ralucado, Cristina Raluca Vijulie, ralucris.v[at]gmail[dot]com
2019/02/23, gedimitr, Gerasimos Dimitriadis, gedimitr@gmail.com
@ -237,9 +243,31 @@ YYYY/MM/DD, github id, Full name, email
2019/11/11, foxeverl, Liu Xinfeng, liuxf1986[at]gmail[dot]com
2019/11/17, felixn, Felix Nieuwenhuizhen, felix@tdlrali.com
2019/11/18, mlilback, Mark Lilback, mark@lilback.com
2020/01/19, lingyv-li, Lingyu Li, lingyv.li@gmail.com
2020/02/02, carocad, Camilo Roca, carocad@unal.edu.co
2020/02/10, julibert, Julián Bermúdez Ortega, julibert.dev@gmail.com
2020/02/21, StochasticTinkr, Daniel Pitts, github@coloraura.com
2020/03/17, XsongyangX, Song Yang, songyang1218@gmail.com
2020/04/07, deniskyashif, Denis Kyashif, denis.kyashif@gmail.com
2020/04/10, agrabski, Adam Grabski, adam.gr@outlook.com
2020/04/10, agrabski, Adam Grabski, adam.gr@outlook.com
2020/04/23, martinvw, Martin van Wingerden, martin@martinvw.nl
2020/04/30, TristonianJones, Tristan Swadell, tswadell@google.com
2020/05/06, iammosespaulr, Moses Paul R, iammosespaulr@gmail.com
2020/05/10, gomerser, Erik Gomersbach, gomerser@gomersba.ch
2020/06/04, sigmasoldi3r, Pablo Blanco, pablobc.1995@gmail.com
2020/05/25, graknol, Sindre van der Linden, graknol@gmail.com
2020/05/31, d-markey, David Markey, dmarkey@free.fr
2020/06/02, cohomology, Kilian Kilger, kkilger AT gmail.com
2020/06/04, IohannRabeson, Iohann Rabeson, iotaka6@gmail.com
2020/07/01, sha-N, Shan M Mathews, admin@bluestarqatar.com
2020/08/22, stevenjohnstone, Steven Johnstone, steven.james.johnstone@gmail.com
2020/09/06, ArthurSonzogni, Sonzogni Arthur, arthursonzogni@gmail.com
2020/09/10, Khailian, Arunav Sanyal, arunav.sanyal91@gmail.com
2020/09/12, Clcanny, Charles Ruan, a837940593@gmail.com
2020/09/15, rmcgregor1990, Robert McGregor, rmcgregor1990@gmail.com
2020/09/16, trenki2, Markus Trenkwalder, trenki2[at]gmx[dot]net
2020/10/08, Marti2203, Martin Mirchev, mirchevmartin2203@gmail.com
2020/10/16, adarshbhat, Adarsh Bhat, adarshbhat@users.noreply.github.com
2020/10/20, adamwojs, Adam Wójs, adam[at]wojs.pl
2020/10/24, cliid, Jiwu Jang, jiwujang@naver.com
2020/11/05, MichelHartmann, Michel Hartmann, MichelHartmann@users.noreply.github.com

View File

@ -1,6 +1,6 @@
# C++
The C++ target supports all platforms that can either run MS Visual Studio 2013 (or newer), XCode 7 (or newer) or CMake (C++11 required). All build tools can either create static or dynamic libraries, both as 64bit or 32bit arch. Additionally, XCode can create an iOS library. Also see [Antlr4 for C++ with CMake: A practical example](http://blorente.me//Antlr-,-C++-and-CMake-Wait-what.html).
The C++ target supports all platforms that can either run MS Visual Studio 2013 (or newer), XCode 7 (or newer) or CMake (C++11 required). All build tools can either create static or dynamic libraries, both as 64bit or 32bit arch. Additionally, XCode can create an iOS library. Also see [Antlr4 for C++ with CMake: A practical example](https://beyondtheloop.dev/Antlr-cpp-cmake/).
## How to create a C++ 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:
@ -65,7 +65,7 @@ int main(int argc, const char* argv[]) {
tree::ParseTree *tree = parser.key();
TreeShapeListener listener;
tree::ParseTreeWalker::DEFAULT->walk(&listener, tree);
tree::ParseTreeWalker::DEFAULT.walk(&listener, tree);
return 0;
}

View File

@ -10,6 +10,8 @@ Creating a new target involves the following key elements:
1. Create *X*.stg in directory tool/resources/org/antlr/v4/tool/templates/codegen/*X*/*X*.stg. This is a [StringTemplate](http://www.stringtemplate.org/) group file (`.stg`) that tells ANTLR how to express all of the parsing elements needed to generate code. You will see templates called `ParserFile`, `Parser`, `Lexer`, `CodeBlockForAlt`, `AltBlock`, etc... Each of these must be described how to build the indicated chunk of code. Your best bet is to find the closest existing target, copy that template file, and tweak to suit.
1. Create a runtime library to support the parsers generated by ANTLR. Under directory runtime/*X*, you are in complete control of the directory structure as dictated by common usage of that target language. For example, Java has: `runtime/Java/lib` and `runtime/Java/src` directories. Under `src`, you will find a directory structure for package `org.antlr.v4.runtime` and below.
1. Create a template file for runtime tests. All you have to do is provide a few templates that indicate how to print values and declare variables. Our runtime test mechanism in dir `runtime-testsuite` will automatically generate code using these templates for each target and check the test results. It needs to know how to define various class fields, compare members and so on. You must create a *X*.test.stg file underneath [runtime-testsuite/resources/org/antlr/v4/test/runtime](https://github.com/antlr/antlr4/tree/master/runtime-testsuite/resources/org/antlr/v4/test/runtime). Again, your best bet is to copy the templates from the closest language to your target and tweak it to suit.
1. Create test files under [/runtime-testsuite/test/org/antlr/v4/test/runtime](https://github.com/antlr/antlr4/tree/master/runtime-testsuite/test/org/antlr/v4/test/runtime). They will load defined test cases in each test descriptor. Also add the `/runtime-testsuite/test/org/antlr/v4/test/runtime/X/BaseXTest.java` which defines how test cases will execute and output.
1. Create/edit shell scripts in [/.travis](https://github.com/antlr/antlr4/blob/master/.travis) and [/appveyor.yml](https://github.com/antlr/antlr4/blob/master/appveyor.yml) to run tests in CI pipelines.
## Getting started

View File

@ -86,7 +86,7 @@ In order to execute this listener, you would simply add the following lines to t
...
IParseTree tree = parser.StartRule() - only repeated here for reference
KeyPrinter printer = new KeyPrinter();
ParseTreeWalker.DEFAULT.walk(printer, tree);
ParseTreeWalker.Default.Walk(printer, tree);
```
Further information can be found from The Definitive ANTLR Reference book.

117
doc/dart-target.md Normal file
View File

@ -0,0 +1,117 @@
# ANTLR4 Runtime for Dart
Notice: Dart target may generate code incompatible with Dart 2.9 sound null safety. Please set the minimum SDK constraint to 2.8.4 or lower if such violation is found. Contributions are welcomed.
### First steps
#### 1. Install ANTLR4
[The getting started guide](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md)
should get you started.
#### 2. Install the Dart ANTLR runtime
Each target language for ANTLR has a runtime package for running parser
generated by ANTLR4. The runtime provides a common set of tools for using your parser.
Install the runtime with the same version as the main ANTLR tool:
Add this to your package's pubspec.yaml file:
```yaml
...
dependencies:
antlr4: <ANTLR version>
...
```
#### 3. Generate your parser
You use the ANTLR4 "tool" to generate a parser. These will reference the ANTLR
runtime, installed above.
Suppose you're using a UNIX system and have set up an alias for the ANTLR4 tool
as described in [the getting started guide](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md).
To generate your Dart parser, run the following command:
```shell script
antlr4 -Dlanguage=Dart MyGrammar.g4
```
For a full list of antlr4 tool options, please visit the
[tool documentation page](https://github.com/antlr/antlr4/blob/master/doc/tool-options.md).
### Complete example
Suppose you're using the JSON grammar from https://github.com/antlr/grammars-v4/tree/master/json.
Then, invoke `antlr4 -Dlanguage=Dart JSON.g4`. The result of this is a
collection of `.dart` including:
* JsonLexer.dart
* JsonParser.dart
* JsonBaseListener.dart
* JsonListener.dart (if you have not activated the -no-listener option)
* JsonVisitor.dart (if you have activated the -visitor option)
We'll write a small main func to call the generated parser/lexer
(assuming they are separate). This one writes out the encountered
`ParseTreeContext`'s:
```dart
import 'package:antlr4/antlr4.dart';
import 'package:my_project/JSONParser.dart';
import 'package:my_project/JSONLexer.dart';
class TreeShapeListener implements ParseTreeListener {
@override
void enterEveryRule(ParserRuleContext ctx) {
print(ctx.text);
}
@override
void exitEveryRule(ParserRuleContext node) {
}
@override
void visitErrorNode(ErrorNode node) {
}
@override
void visitTerminal(TerminalNode node) {
}
}
void main(List<String> args) async {
JSONLexer.checkVersion();
JSONParser.checkVersion();
final input = await InputStream.fromPath(args[0]);
final lexer = JSONLexer(input);
final tokens = CommonTokenStream(lexer);
final parser = JSONParser(tokens);
parser.addErrorListener(DiagnosticErrorListener());
parser.buildParseTree = true;
final tree = parser.json();
ParseTreeWalker.DEFAULT.walk(TreeShapeListener(), tree);
}
```
Create a `example.json` file:
```json
{"a":1}
```
Parse the input file:
```shell script
dart bin/main.dart example.json
```
The expected output is:
```
{"a":1}
{"a":1}
{"a":1}
"a":1
1
```

View File

@ -38,8 +38,8 @@ This is the main landing page for the ANTLR 4 FAQ. The links below will take you
## Translation
* [ASTs vs parse trees](parse-trees.md)
* [Decoupling input walking from output generation](parse-trees.md)
* [ASTs vs parse trees](translation.md)
* [Decoupling input walking from output generation](translation.md)
## Actions and semantic predicates

View File

@ -50,7 +50,7 @@ For writing a compiler, either generate [LLVM-type static-single-assignment](htt
### XPath
XPath works great when you need to find specific nodes, possibly in certain contexts. The context is limited to the parents on the way to the root of the tree. For example, if you want to find all ID nodes, use path `//ID`. If you want all variable declarations, you might use path `//vardecl`. If you only want fields declarations, then you can use some context information via path `/classdef/vardecl`, which would only find vardecls that our children of class definitions. You can merge the results of multiple XPath `findAll()`s simulating a set union for XPath. The only caveat is that the order from the original tree is not preserved when you union multiple `findAll()` sets.
XPath works great when you need to find specific nodes, possibly in certain contexts. The context is limited to the parents on the way to the root of the tree. For example, if you want to find all ID nodes, use path `//ID`. If you want all variable declarations, you might use path `//vardecl`. If you only want fields declarations, then you can use some context information via path `/classdef/vardecl`, which would only find vardecls that are children of class definitions. You can merge the results of multiple XPath `findAll()`s simulating a set union for XPath. The only caveat is that the order from the original tree is not preserved when you union multiple `findAll()` sets.
### Tree pattern matching
@ -70,4 +70,4 @@ scopeStack.peek().define(new VariableSymbol("foo"))
That way each listener function does not have to compute its appropriate scope.
Examples: [DefScopesAndSymbols.java](https://github.com/mantra/compiler/blob/master/src/java/mantra/semantics/DefScopesAndSymbols.java) and [SetScopeListener.java](https://github.com/mantra/compiler/blob/master/src/java/mantra/semantics/SetScopeListener.java) and [VerifyListener.java](https://github.com/mantra/compiler/blob/master/src/java/mantra/semantics/VerifyListener.java)
Examples: [DefScopesAndSymbols.java](https://github.com/mantra/compiler/blob/master/src/java/mantra/semantics/DefScopesAndSymbols.java) and [SetScopeListener.java](https://github.com/mantra/compiler/blob/master/src/java/mantra/semantics/SetScopeListener.java) and [VerifyListener.java](https://github.com/mantra/compiler/blob/master/src/java/mantra/semantics/VerifyListener.java)

View File

@ -6,9 +6,9 @@ Hi and welcome to the version 4 release of ANTLR! It's named after the fearless
ANTLR is really two things: a tool that translates your grammar to a parser/lexer in Java (or other target language) and the runtime needed by the generated parsers/lexers. Even if you are using the ANTLR Intellij plug-in or ANTLRWorks to run the ANTLR tool, the generated code will still need the runtime library.
The first thing you should do is probably download and install a development tool plug-in. Even if you only use such tools for editing, they are great. Then, follow the instructions below to get the runtime environment available to your system to run generated parsers/lexers. In what follows, I talk about antlr-4.7.1-complete.jar, which has the tool and the runtime and any other support libraries (e.g., ANTLR v4 is written in v3).
The first thing you should do is probably download and install a development tool plug-in. Even if you only use such tools for editing, they are great. Then, follow the instructions below to get the runtime environment available to your system to run generated parsers/lexers. In what follows, I talk about antlr-4.9-complete.jar, which has the tool and the runtime and any other support libraries (e.g., ANTLR v4 is written in v3).
If you are going to integrate ANTLR into your existing build system using mvn, ant, or want to get ANTLR into your IDE such as eclipse or intellij, see Integrating ANTLR into Development Systems.
If you are going to integrate ANTLR into your existing build system using mvn, ant, or want to get ANTLR into your IDE such as eclipse or intellij, see [Integrating ANTLR into Development Systems](https://github.com/antlr/antlr4/blob/master/doc/IDEs.md).
### UNIX
@ -16,22 +16,22 @@ If you are going to integrate ANTLR into your existing build system using mvn, a
1. Download
```
$ cd /usr/local/lib
$ curl -O https://www.antlr.org/download/antlr-4.7.1-complete.jar
$ curl -O https://www.antlr.org/download/antlr-4.9-complete.jar
```
Or just download in browser from website:
[https://www.antlr.org/download.html](https://www.antlr.org/download.html)
and put it somewhere rational like `/usr/local/lib`.
2. Add `antlr-4.7.1-complete.jar` to your `CLASSPATH`:
2. Add `antlr-4.9-complete.jar` to your `CLASSPATH`:
```
$ export CLASSPATH=".:/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH"
$ export CLASSPATH=".:/usr/local/lib/antlr-4.9-complete.jar.jar:$CLASSPATH"
```
It's also a good idea to put this in your `.bash_profile` or whatever your startup script is.
3. Create aliases for the ANTLR Tool, and `TestRig`.
```
$ alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.Tool'
$ alias grun='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSPATH" org.antlr.v4.gui.TestRig'
$ alias antlr4='java -Xmx500M -cp "/usr/local/lib/antlr-4.9-complete.jar.jar:$CLASSPATH" org.antlr.v4.Tool'
$ alias grun='java -Xmx500M -cp "/usr/local/lib/antlr-4.9-complete.jar.jar:$CLASSPATH" org.antlr.v4.gui.TestRig'
```
### WINDOWS
@ -39,13 +39,13 @@ $ alias grun='java -Xmx500M -cp "/usr/local/lib/antlr-4.7.1-complete.jar:$CLASSP
(*Thanks to Graham Wideman*)
0. Install Java (version 1.6 or higher)
1. Download antlr-4.7.1-complete.jar (or whatever version) from [https://www.antlr.org/download/](https://www.antlr.org/download/)
1. Download antlr-4.9-complete.jar (or whatever version) from [https://www.antlr.org/download/](https://www.antlr.org/download/)
Save to your directory for 3rd party Java libraries, say `C:\Javalib`
2. Add `antlr-4.7.1-complete.jar` to CLASSPATH, either:
2. Add `antlr-4.9-complete.jar.jar` to CLASSPATH, either:
* Permanently: Using System Properties dialog > Environment variables > Create or append to `CLASSPATH` variable
* Temporarily, at command line:
```
SET CLASSPATH=.;C:\Javalib\antlr-4.7.1-complete.jar;%CLASSPATH%
SET CLASSPATH=.;C:\Javalib\antlr-4.9-complete.jar;%CLASSPATH%
```
3. Create short convenient commands for the ANTLR Tool, and TestRig, using batch files or doskey commands:
* Batch files (in directory in system PATH) antlr4.bat and grun.bat
@ -71,7 +71,7 @@ Either launch org.antlr.v4.Tool directly:
```
$ java org.antlr.v4.Tool
ANTLR Parser Generator Version 4.7.1
ANTLR Parser Generator Version 4.9
-o ___ specify output directory where all output is generated
-lib ___ specify location of .tokens files
...
@ -80,8 +80,8 @@ ANTLR Parser Generator Version 4.7.1
or use -jar option on java:
```
$ java -jar /usr/local/lib/antlr-4.7.1-complete.jar
ANTLR Parser Generator Version 4.7.1
$ java -jar /usr/local/lib/antlr-4.9-complete.jar
ANTLR Parser Generator Version 4.9
-o ___ specify output directory where all output is generated
-lib ___ specify location of .tokens files
...

View File

@ -11,11 +11,18 @@ In practice, this target has been extensively tested against:
* Chrome 39.0.2171
* Explorer 11.0.3
The tests were conducted using Selenium. No issue was found, so you should find that the runtime works pretty much against any recent JavaScript engine.
The above tests were conducted using Selenium. No issue was found, so you should find that the runtime works pretty much against any recent JavaScript engine.
## Is NodeJS supported?
The runtime has also been extensively tested against Node.js 10 LTS. No issue was found.
The runtime has also been extensively tested against Node.js 14 LTS. No issue was found.
NodeJS together with a packaging tool is now the preferred development path, developers are encouraged to follow it.
## What about modules?
Starting with version 8.1, Antlr4 JavaScript runtime follows esm semantics (see https://tc39.es/ecma262/#sec-modules for details)
Generated lexers, parsers, listeners and visitors also follow this new standard.
If you have used previous versions of the runtime, you will need to migrate and make your parser a module.
## How to create a JavaScript lexer or parser?
@ -61,7 +68,10 @@ The steps to create your parsing code are the following:
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" }`
- For Webpack version 5,
- in the `webpack.config` file, exclude node.js only modules using: `resolve: { fallback: { fs: false } }`
- For older versions of Webpack,
- in the `webpack.config` file, exclude node.js only modules using: `node: { module: "empty", net: "empty", fs: "empty" }`
- from the cmd line, navigate 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!
@ -80,18 +90,18 @@ Let's suppose that your grammar is named, as above, "MyGrammar". Let's suppose t
Now a fully functioning script might look like the following:
```javascript
var antlr4 = require('antlr4');
var MyGrammarLexer = require('./MyGrammarLexer').MyGrammarLexer;
var MyGrammarParser = require('./MyGrammarParser').MyGrammarParser;
var MyGrammarListener = require('./MyGrammarListener').MyGrammarListener;
import antlr4 from 'antlr4';
import MyGrammarLexer from './MyGrammarLexer.js');
import MyGrammarParser from './MyGrammarParser.js';
import MyGrammarListener from './MyGrammarListener.js';
var input = "your text to parse here"
var chars = new antlr4.InputStream(input);
var lexer = new MyGrammarLexer(chars);
var tokens = new antlr4.CommonTokenStream(lexer);
var parser = new MyGrammarParser(tokens);
const input = "your text to parse here"
const chars = new antlr4.InputStream(input);
const lexer = new MyGrammarLexer(chars);
const tokens = new antlr4.CommonTokenStream(lexer);
const parser = new MyGrammarParser(tokens);
parser.buildParseTrees = true;
var tree = parser.MyStartRule();
const tree = parser.MyStartRule();
```
This program will work. But it won't be useful unless you do one of the following:
@ -105,19 +115,19 @@ This program will work. But it won't be useful unless you do one of the followin
## How do I create and run a visitor?
```javascript
// test.js
var antlr4 = require('antlr4');
var MyGrammarLexer = require('./QueryLexer').QueryLexer;
var MyGrammarParser = require('./QueryParser').QueryParser;
var MyGrammarListener = require('./QueryListener').QueryListener;
import antlr4 from 'antlr4';
import MyGrammarLexer from './QueryLexer.js';
import MyGrammarParser from './QueryParser.js';
import MyGrammarListener from './QueryListener.js';
var input = "field = 123 AND items in (1,2,3)"
var chars = new antlr4.InputStream(input);
var lexer = new MyGrammarLexer(chars);
var tokens = new antlr4.CommonTokenStream(lexer);
var parser = new MyGrammarParser(tokens);
const input = "field = 123 AND items in (1,2,3)"
const chars = new antlr4.InputStream(input);
const lexer = new MyGrammarLexer(chars);
const tokens = new antlr4.CommonTokenStream(lexer);
const parser = new MyGrammarParser(tokens);
parser.buildParseTrees = true;
var tree = parser.query();
const tree = parser.query();
class Visitor {
visitChildren(ctx) {
@ -145,40 +155,37 @@ tree.accept(new Visitor());
Let's suppose your MyGrammar grammar comprises 2 rules: "key" and "value". The antlr4 tool will have generated the following listener:
```javascript
MyGrammarListener = function(ParseTreeListener) {
// some code here
}
// some code here
MyGrammarListener.prototype.enterKey = function(ctx) {};
MyGrammarListener.prototype.exitKey = function(ctx) {};
MyGrammarListener.prototype.enterValue = function(ctx) {};
MyGrammarListener.prototype.exitValue = function(ctx) {};
class MyGrammarListener extends ParseTreeListener {
constructor() {
super();
}
enterKey(ctx) {}
exitKey(ctx) {}
enterValue(ctx) {}
exitValue(ctx) {}
}
```
In order to provide custom behavior, you might want to create the following class:
```javascript
var KeyPrinter = function() {
MyGrammarListener.call(this); // inherit default listener
return this;
};
class KeyPrinter extends MyGrammarListener {
// continue inheriting default listener
KeyPrinter.prototype = Object.create(MyGrammarListener.prototype);
KeyPrinter.prototype.constructor = KeyPrinter;
// override default listener behavior
KeyPrinter.prototype.exitKey = function(ctx) {
console.log("Oh, a key!");
};
// override default listener behavior
exitKey(ctx) {
console.log("Oh, a key!");
}
}
```
In order to execute this listener, you would simply add the following lines to the above code:
```javascript
...
tree = parser.StartRule() // only repeated here for reference
var printer = new KeyPrinter();
...
tree = parser.StartRule() // only repeated here for reference
const printer = new KeyPrinter();
antlr4.tree.ParseTreeWalker.DEFAULT.walk(printer, tree);
```

View File

@ -58,7 +58,7 @@ Match that character or sequence of characters. E.g., while or =.</t
<tr>
<td>[char set]</td><td>
<p>Match one of the characters specified in the character set. Interpret <tt>x-y</tt> as the set of characters between range <tt>x</tt> and <tt>y</tt>, inclusively. The following escaped characters are interpreted as single special characters: <tt>\n</tt>, <tt>\r</tt>, <tt>\b</tt>, <tt>\t</tt>, <tt>\f</tt>, <tt>\uXXXX</tt>, and <tt>\u{XXXXXX}</tt>. To get <tt>]</tt>, <tt>\</tt>, or <tt>-</tt> you must escape them with <tt>\</tt>.</p>
<p>Match one of the characters specified in the character set. Interpret <tt>x-y</tt> as the set of characters between range <tt>x</tt> and <tt>y</tt>, inclusively. The following escaped characters are interpreted as single special characters: <tt>\n</tt>, <tt>\r</tt>, <tt>\b</tt>, <tt>\t</tt>, <tt>\f</tt>, <tt>\uXXXX</tt>, and <tt>\u{XXXXXX}</tt>. To get <tt>]</tt> or <tt>\</tt> you must escape them with <tt>\</tt>. To get <tt>-</tt> you must escape it with <tt>\</tt> too, except for the case when <tt>-</tt> is the first or last character in the set.</p>
<p>You can also include all characters matching Unicode properties (general category, boolean, or enumerated including scripts and blocks) with <tt>\p{PropertyName}</tt> or <tt>\p{EnumProperty=Value}</tt>. (You can invert the test with <tt>\P{PropertyName}</tt> or <tt>\P{EnumProperty=Value}</tt>).</p>
@ -90,6 +90,8 @@ UNICODE_ID : [\p{Alpha}\p{General_Category=Other_Letter}] [\p{Alnum}\p{General_C
EMOJI : [\u{1F4A9}\u{1F926}] ; // note Unicode code points > U+FFFF
DASHBRACK : [\-\]]+ ; // match - or ] one or more times
DASH : [---] ; // match a single -, i.e., "any character" between - and - (note first and last - not escaped)
</pre>
</td>
</tr>

View File

@ -96,7 +96,7 @@ The recognizers that ANTLR generates assume a character vocabulary containing al
## Actions
Actions are code blocks written in the target language. You can use actions in a number of places within a grammar, but the syntax is always the same: arbitrary text surrounded by curly braces. You dont need to escape a closing curly character if its in a string or comment: `"}"` or `/*}*/`. If the curlies are balanced, you also dont need to escape }: `{...}`. Otherwise, escape extra curlies with a backslash: `\{` or `\}`. The action text should conform to the target language as specified with thelanguage option.
Actions are code blocks written in the target language. You can use actions in a number of places within a grammar, but the syntax is always the same: arbitrary text surrounded by curly braces. You dont need to escape a closing curly character if its in a string or comment: `"}"` or `/*}*/`. If the curlies are balanced, you also dont need to escape }: `{...}`. Otherwise, escape extra curlies with a backslash: `\{` or `\}`. The action text should conform to the target language as specified with the language option.
Embedded code can appear in: `@header` and `@members` named actions, parser and lexer rules, exception catching specifications, attribute sections for parser rules (return values, arguments, and locals), and some rule element options (currently predicates).

View File

@ -65,6 +65,8 @@ Edit the repository looking for 4.5 or whatever and update it. Bump version in t
* runtime/Cpp/demo/generate.cmd
* runtime/Go/antlr/recognizer.go
* runtime/Swift/Antlr4/org/antlr/v4/runtime/RuntimeMetaData.swift
* runtime/Dart/lib/src/runtime_meta_data.dart
* runtime/Dart/pubspec.yaml
* tool/src/org/antlr/v4/codegen/target/GoTarget.java
* tool/src/org/antlr/v4/codegen/target/CppTarget.java
* tool/src/org/antlr/v4/codegen/target/CSharpTarget.java
@ -442,6 +444,19 @@ git push origin gh-pages
popd
```
### Dart
Push to pub.dev
```bash
cd runtime/Dart
pub publish
```
It will warn that no change log found for the new version.
If there are changes relevant to dart in this release, edit [CHANGELOG.md](https://github.com/antlr/antlr4/blob/master/runtime/Dart/CHANGELOG.md) to describe the changes.
Otherwise enter `N` to ignore the warning.
## Update javadoc for runtime and tool
First, gen javadoc:

View File

@ -10,12 +10,13 @@ This page lists the available and upcoming ANTLR runtimes. Please note that you
* [C++](cpp-target.md)
* [Swift](swift-target.md)
* [PHP](php-target.md)
* [Dart](dart-target.md)
## Target feature parity
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;|Python2|Python3|JavaScript|Go|C++|Swift|PHP
|---|---|---|---|---|---|---|---|---|---|
|Ambiguous tree construction|4.5.1|-|-|-|-|-|-|-|-|
|Feature|Java|C&sharp;|Python2|Python3|JavaScript|Go|C++|Swift|PHP|Dart
|---|---|---|---|---|---|---|---|---|---|---|
|Ambiguous tree construction|4.5.1|-|-|-|-|-|-|-|-|-|

View File

@ -103,6 +103,7 @@
<include>**/python2/Test*.java</include>
<include>**/python3/Test*.java</include>
<include>**/php/Test*.java</include>
<include>**/dart/Test*.java</include>
<include>${antlr.tests.swift}</include>
</includes>
</configuration>

View File

@ -74,7 +74,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
ImportListener(X) ::= <<var <X>Listener = require('./<X>Listener').<X>Listener;>>
ImportListener(X) ::= ""
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"

View File

@ -0,0 +1,318 @@
writeln(s) ::= <<print(<s>);>>
write(s) ::= <<stdout.write(<s>);>>
writeList(s) ::= <<print(<s; separator="+">);>>
False() ::= "false"
True() ::= "true"
Not(v) ::= "!<v>"
Assert(s) ::= <<assert(<s>);>>
Cast(t,v) ::= "(<v> as <t>)"
Append(a,b) ::= "<a>.toString() + <b>.toString()"
AppendStr(a,b) ::= <%<Append(a,b)>%>
Concat(a,b) ::= "<a><b>"
AssertIsList(v) ::= "assert (<v> is List);" // just use static type system
AssignLocal(s,v) ::= "<s> = <v>;"
InitIntMember(n,v) ::= <%int <n> = <v>;%>
InitBooleanMember(n,v) ::= <%bool <n> = <v>;%>
InitIntVar(n,v) ::= <%<InitIntMember(n,v)>%>
IntArg(n) ::= "int <n>"
VarRef(n) ::= "<n>"
GetMember(n) ::= <%this.<n>%>
SetMember(n,v) ::= <%this.<n> = <v>;%>
AddMember(n,v) ::= <%this.<n> += <v>;%>
MemberEquals(n,v) ::= <%this.<n> == <v>%>
ModMemberEquals(n,m,v) ::= <%this.<n> % <m> == <v>%>
ModMemberNotEquals(n,m,v) ::= <%this.<n> % <m> != <v>%>
DumpDFA() ::= "this.dumpDFA();"
Pass() ::= ""
StringList() ::= "List\<String>"
BuildParseTrees() ::= "buildParseTree = true;"
BailErrorStrategy() ::= <%errorHandler = new BailErrorStrategy();%>
ToStringTree(s) ::= <%<s>.toStringTree(parser: this)%>
Column() ::= "this.charPositionInLine"
Text() ::= "this.text"
ValEquals(a,b) ::= <%<a>==<b>%>
TextEquals(a) ::= <%this.text == "<a>"%>
PlusText(a) ::= <%"<a>" + this.text%>
InputText() ::= "tokenStream.text"
LTEquals(i, v) ::= <%tokenStream.LT(<i>).text == <v>%>
LANotEquals(i, v) ::= <%tokenStream.LA(<i>)!=<v>%>
TokenStartColumnEquals(i) ::= <%this.tokenStartCharPositionInLine==<i>%>
ImportListener(X) ::= ""
GetExpectedTokenNames() ::= "this.expectedTokens.toString(vocabulary: this.vocabulary)"
RuleInvocationStack() ::= "ruleInvocationStack"
LL_EXACT_AMBIG_DETECTION() ::= <<interpreter.predictionMode = PredictionMode.LL_EXACT_AMBIG_DETECTION;>>
ParserToken(parser, token) ::= <%<parser>.TOKEN_<token>%>
Production(p) ::= <%<p>%>
Result(r) ::= <%<r>%>
ParserPropertyMember() ::= <<
@members {
bool Property() {
return true;
}
}
>>
ParserPropertyCall(p, call) ::= "<p>.<call>"
PositionAdjustingLexerDef() ::= <<
class PositionAdjustingLexerATNSimulator extends LexerATNSimulator {
PositionAdjustingLexerATNSimulator(Lexer recog, ATN atn,
List\<DFA> decisionToDFA, PredictionContextCache sharedContextCache)
: super(atn, decisionToDFA, sharedContextCache, recog: recog);
void resetAcceptPosition(CharStream input, int index, int line,
int charPositionInLine) {
input.seek(index);
this.line = line;
this.charPositionInLine = charPositionInLine;
consume(input);
}
}
>>
PositionAdjustingLexer() ::= <<
@override
Token nextToken() {
if (!(super.interpreter is PositionAdjustingLexerATNSimulator)) {
interpreter = new PositionAdjustingLexerATNSimulator(
this, _ATN, _decisionToDFA, _sharedContextCache);
}
return super.nextToken();
}
@override
Token emit() {
switch (type) {
case TOKEN_TOKENS:
handleAcceptPositionForKeyword("tokens");
break;
case TOKEN_LABEL:
handleAcceptPositionForIdentifier();
break;
default:
break;
}
return super.emit();
}
bool handleAcceptPositionForIdentifier() {
String tokenText = text;
int identifierLength = 0;
while (identifierLength \< tokenText.length &&
isIdentifierChar(tokenText[identifierLength])) {
identifierLength++;
}
if (inputStream.index > tokenStartCharIndex + identifierLength) {
int offset = identifierLength - 1;
interpreter.resetAcceptPosition(inputStream, tokenStartCharIndex + offset,
tokenStartLine, tokenStartCharPositionInLine + offset);
return true;
}
return false;
}
bool handleAcceptPositionForKeyword(String keyword) {
if (inputStream.index > tokenStartCharIndex + keyword.length) {
int offset = keyword.length - 1;
interpreter.resetAcceptPosition(inputStream, tokenStartCharIndex + offset,
tokenStartLine, tokenStartCharPositionInLine + offset);
return true;
}
return false;
}
@override
PositionAdjustingLexerATNSimulator get interpreter {
return super.interpreter as PositionAdjustingLexerATNSimulator;
}
static bool isIdentifierChar(String c) {
return isLetterOrDigit(c) || c == '_';
}
static const ZERO = 48;
static const LOWER_A = 97;
static const LOWER_Z = 122;
static const UPPER_A = 65;
static const UPPER_Z = 90;
static bool isLetterOrDigit(String char) => isLetter(char) || isDigit(char);
// Note: this is intentially ASCII only
static bool isLetter(String char) {
if (char == null) return false;
var cc = char.codeUnitAt(0);
return cc >= LOWER_A && cc \<= LOWER_Z || cc >= UPPER_A && cc \<= UPPER_Z;
}
static bool isDigit(String char) {
if (char == null) return false;
var cc = char.codeUnitAt(0);
return cc >= ZERO && cc \< ZERO + 10;
}
>>
BasicListener(X) ::= <<
@parser::definitions {
class LeafListener extends TBaseListener {
void visitTerminal(TerminalNode node) {
print(node.symbol.text);
}
}
}
>>
WalkListener(s) ::= <<
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(new LeafListener(), <s>);
>>
TreeNodeWithAltNumField(X) ::= <<
@parser::definitions {
class MyRuleNode extends ParserRuleContext {
int altNum;
MyRuleNode(ParserRuleContext parent, int invokingStateNumber)
: super(parent, invokingStateNumber);
@override int get altNumber {
return altNum;
}
@override void set altNumber(int altNum) {
this.altNum = altNum;
}
}
}
>>
TokenGetterListener(X) ::= <<
@parser::definitions {
class LeafListener extends TBaseListener {
void exitA(AContext ctx) {
if (ctx.childCount==2)
stdout.write("${ctx.INT(0).symbol.text} ${ctx.INT(1).symbol.text} ${ctx.INTs()}");
else
print(ctx.ID().symbol);
}
}
}
>>
RuleGetterListener(X) ::= <<
@parser::definitions {
class LeafListener extends TBaseListener {
void exitA(AContext ctx) {
if (ctx.childCount==2) {
stdout.write("${ctx.b(0).start.text} ${ctx.b(1).start.text} ${ctx.bs()[0].start.text}");
} else
print(ctx.b(0).start.text);
}
}
}
>>
LRListener(X) ::= <<
@parser::definitions {
class LeafListener extends TBaseListener {
void exitE(EContext ctx) {
if (ctx.childCount==3) {
stdout.write("${ctx.e(0).start.text} ${ctx.e(1).start.text} ${ctx.es()[0].start.text}\n");
} else
print(ctx.INT().symbol.text);
}
}
}
>>
LRWithLabelsListener(X) ::= <<
@parser::definitions {
class LeafListener extends TBaseListener {
void exitCall(CallContext ctx) {
stdout.write("${ctx.e().start.text} ${ctx.eList()}");
}
void exitInt(IntContext ctx) {
print(ctx.INT().symbol.text);
}
}
}
>>
DeclareContextListGettersFunction() ::= <<
void foo() {
SContext s = null;
List\<AContext> a = s.as();
List\<BContext> b = s.bs();
}
>>
Declare_foo() ::= <<
void foo() {print("foo");}
>>
Invoke_foo() ::= "foo();"
Declare_pred() ::= <<bool pred(bool v) {
print("eval=\$v");
return v;
}
>>
Invoke_pred(v) ::= <<this.pred(<v>)>>
ParserTokenType(t) ::= "Parser.<t>"
ContextRuleFunction(ctx, rule) ::= "<ctx>.<rule>"
StringType() ::= "String"
ContextMember(ctx, subctx, member) ::= "<ctx>.<subctx>.<member>"

View File

@ -76,11 +76,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
ImportListener(X) ::= <<
@parser::header {
var <X>Listener = require('./<X>Listener').<X>Listener;
}
>>
ImportListener(X) ::= ""
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"

View File

@ -103,6 +103,8 @@ PositionAdjustingLexerDef() ::= ""
PositionAdjustingLexer() ::= <<
func (p *PositionAdjustingLexer) NextToken() antlr.Token {
if _, ok := p.Interpreter.(*PositionAdjustingLexerATNSimulator); !ok {
lexerDeserializer := antlr.NewATNDeserializer(nil)
lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
p.Interpreter = NewPositionAdjustingLexerATNSimulator(p, lexerAtn, p.Interpreter.DecisionToDFA(), p.Interpreter.SharedContextCache())
p.Virt = p
}

View File

@ -74,11 +74,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
ImportListener(X) ::= <<
@parser::header {
var <X>Listener = require('./<X>Listener').<X>Listener;
}
>>
ImportListener(X) ::= ""
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"

View File

@ -74,11 +74,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
ImportListener(X) ::= <<
@parser::header {
var <X>Listener = require('./<X>Listener').<X>Listener;
}
>>
ImportListener(X) ::= ""
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"

View File

@ -46,12 +46,14 @@ import static org.junit.Assume.assumeFalse;
public abstract class BaseRuntimeTest {
public final static String[] Targets = {
"Cpp",
"Java",
"Go",
"CSharp",
"Python2", "Python3",
"Dart",
"Go",
"Java",
"Node",
"PHP",
"Node"
"Python2", "Python3",
"Swift"
};
static {
@ -94,10 +96,17 @@ public abstract class BaseRuntimeTest {
public void setUp() throws Exception {
// From http://junit.sourceforge.net/javadoc/org/junit/Assume.html
// "The default JUnit runner treats tests with failing assumptions as ignored"
assumeFalse(descriptor.ignore(descriptor.getTarget()));
assumeFalse(checkIgnored());
delegate.testSetUp();
}
public boolean checkIgnored() {
boolean ignored = !TestContext.isSupportedTarget(descriptor.getTarget()) || descriptor.ignore(descriptor.getTarget());
if(ignored)
System.out.println("Ignore " + descriptor);
return ignored;
}
@Rule
public final TestRule testWatcher = new TestWatcher() {
@Override
@ -111,7 +120,7 @@ public abstract class BaseRuntimeTest {
public void testOne() throws Exception {
// System.out.println(delegate.getTmpDir());
if ( descriptor.ignore(descriptor.getTarget()) ) {
System.out.printf("Ignore "+descriptor);
System.out.println("Ignore " + descriptor);
return;
}
@ -272,6 +281,8 @@ public abstract class BaseRuntimeTest {
// ---- support ----
public static RuntimeTestDescriptor[] getRuntimeTestDescriptors(Class<?> clazz, String targetName) {
if(!TestContext.isSupportedTarget(targetName))
return new RuntimeTestDescriptor[0];
Class<?>[] nestedClasses = clazz.getClasses();
List<RuntimeTestDescriptor> descriptors = new ArrayList<RuntimeTestDescriptor>();
for (Class<?> nestedClass : nestedClasses) {
@ -279,8 +290,10 @@ public abstract class BaseRuntimeTest {
if ( RuntimeTestDescriptor.class.isAssignableFrom(nestedClass) && !Modifier.isAbstract(modifiers) ) {
try {
RuntimeTestDescriptor d = (RuntimeTestDescriptor) nestedClass.newInstance();
d.setTarget(targetName);
descriptors.add(d);
if(!d.ignore(targetName)) {
d.setTarget(targetName);
descriptors.add(d);
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
@ -299,6 +312,16 @@ public abstract class BaseRuntimeTest {
}
}
public static String readFile(String dir, String fileName) {
try {
return String.copyValueOf(Utils.readFile(dir+"/"+fileName, "UTF-8"));
}
catch (IOException ioe) {
System.err.println("can't read file");
ioe.printStackTrace(System.err);
}
return null;
}
protected static void assertCorrectOutput(RuntimeTestDescriptor descriptor, RuntimeTestSupport delegate, String actualOutput) {
String actualParseErrors = delegate.getParseErrors();

View File

@ -0,0 +1,19 @@
package org.antlr.v4.test.runtime;
public abstract class TestContext {
public static boolean isTravisCI() {
return "true".equals(String.valueOf(System.getenv("TRAVIS")).toLowerCase());
}
public static boolean isAppVeyorCI() {
return "true".equals(String.valueOf(System.getenv("APPVEYOR")).toLowerCase());
}
public static boolean isSupportedTarget(String target) {
if(isAppVeyorCI())
return !target.matches("Swift|Node");
else
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.CompositeLexersDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestCompositeLexers extends BaseRuntimeTest {
public TestCompositeLexers(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(CompositeLexersDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.CompositeParsersDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestCompositeParsers extends BaseRuntimeTest {
public TestCompositeParsers(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(CompositeParsersDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.FullContextParsingDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestFullContextParsing extends BaseRuntimeTest {
public TestFullContextParsing(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(FullContextParsingDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.LeftRecursionDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestLeftRecursion extends BaseRuntimeTest {
public TestLeftRecursion(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(LeftRecursionDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.LexerErrorsDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestLexerErrors extends BaseRuntimeTest {
public TestLexerErrors(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(LexerErrorsDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.LexerExecDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestLexerExec extends BaseRuntimeTest {
public TestLexerExec(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(LexerExecDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.ListenersDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestListeners extends BaseRuntimeTest {
public TestListeners(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(ListenersDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.ParseTreesDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestParseTrees extends BaseRuntimeTest {
public TestParseTrees(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(ParseTreesDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.ParserErrorsDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestParserErrors extends BaseRuntimeTest {
public TestParserErrors(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(ParserErrorsDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.ParserExecDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestParserExec extends BaseRuntimeTest {
public TestParserExec(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(ParserExecDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.PerformanceDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestPerformance extends BaseRuntimeTest {
public TestPerformance(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(PerformanceDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.SemPredEvalLexerDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestSemPredEvalLexer extends BaseRuntimeTest {
public TestSemPredEvalLexer(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(SemPredEvalLexerDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.SemPredEvalParserDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestSemPredEvalParser extends BaseRuntimeTest {
public TestSemPredEvalParser(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(SemPredEvalParserDescriptors.class, "Dart");
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
package org.antlr.v4.test.runtime.dart;
import org.antlr.v4.test.runtime.BaseRuntimeTest;
import org.antlr.v4.test.runtime.RuntimeTestDescriptor;
import org.antlr.v4.test.runtime.descriptors.SetsDescriptors;
import org.antlr.v4.test.runtime.dart.BaseDartTest;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestSets extends BaseRuntimeTest {
public TestSets(RuntimeTestDescriptor descriptor) {
super(descriptor,new BaseDartTest());
}
@Parameterized.Parameters(name="{0}")
public static RuntimeTestDescriptor[] getAllTestDescriptors() {
return BaseRuntimeTest.getRuntimeTestDescriptors(SetsDescriptors.class, "Dart");
}
}

View File

@ -1051,10 +1051,39 @@ public class LexerExecDescriptors {
grammar = new String(Files.readAllBytes(Paths.get(stuff.toURI())));
}
catch (Exception e) {
System.err.println("Cannot find grammar org/antlr/v4/test/runtime/LarseLexer.g4");
System.err.println("Cannot find grammar org/antlr/v4/test/runtime/LargeLexer.g4");
}
return new Pair<>(grammarName, grammar);
}
}
/**
* This is a regression test for antlr/antlr4#2709 "PHP target generates
* invalid output when $ is used as part of the literal in lexer rule"
* https://github.com/antlr/antlr4/issues/2709
*/
public static class EscapeTargetStringLiteral extends BaseLexerTestDescriptor {
/**
[@0,0:-1='<EOF>',<-1>,1:0]
*/
@CommentHasStringValue
public String output;
public String errors = null;
public String startRule = "";
public String grammarName = "L";
/**
lexer grammar L;
ACTION_WITH_DOLLAR: '$ACTION';
*/
@CommentHasStringValue
public String grammar;
@Override
public boolean ignore(String targetName) {
return !targetName.equals("PHP");
}
}
}

View File

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

View File

@ -639,7 +639,7 @@ public class ParserErrorsDescriptors {
@Override
public boolean ignore(String targetName) {
return !"Java".equals(targetName) && !"Swift".equals(targetName);
return !"Java".equals(targetName) && !"Swift".equals(targetName) && !"Dart".equals(targetName);
}
}
}

View File

@ -889,4 +889,32 @@ public class ParserExecDescriptors {
@CommentHasStringValue
public String grammar;
}
/**
* This is a regression test for antlr/antlr4#2728
* It should generate correct code for grammars with more than 65 tokens.
* https://github.com/antlr/antlr4/pull/2728#issuecomment-622940562
*/
public static class TokenOffset extends BaseParserTestDescriptor {
public String input = "12 34 56 66";
public String output = "12345666\n";
public String errors = null;
public String startRule = "a";
public String grammarName = "L";
/**
grammar L;
a : ('1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'|'10'|'11'|'12'|'13'|'14'|'15'|'16'
|'17'|'18'|'19'|'20'|'21'|'22'|'23'|'24'|'25'|'26'|'27'|'28'|'29'|'30'|'31'|'32'
|'33'|'34'|'35'|'36'|'37'|'38'|'39'|'40'|'41'|'42'|'43'|'44'|'45'|'46'|'47'|'48'
|'49'|'50'|'51'|'52'|'53'|'54'|'55'|'56'|'57'|'58'|'59'|'60'|'61'|'62'|'63'|'64'
|'65'|'66')+ {
<writeln("$text")>
};
WS : (' '|'\n') -> skip;
*/
@CommentHasStringValue
public String grammar;
}
}

View File

@ -113,7 +113,7 @@ public class PerformanceDescriptors {
@Override
public boolean ignore(String targetName) {
return !Arrays.asList("Java", "CSharp", "Python2", "Python3", "Node", "Cpp", "Swift").contains(targetName);
return !Arrays.asList("Java", "CSharp", "Python2", "Python3", "Node", "Cpp", "Swift", "Dart").contains(targetName);
}
}
@ -199,7 +199,7 @@ public class PerformanceDescriptors {
@Override
public boolean ignore(String targetName) {
// passes, but still too slow in Python and JavaScript
return !Arrays.asList("Java", "CSharp", "Cpp", "Swift").contains(targetName);
return !Arrays.asList("Java", "CSharp", "Cpp", "Swift", "Dart").contains(targetName);
}
}

View File

@ -34,6 +34,7 @@ import org.antlr.v4.semantics.SemanticPipeline;
import org.antlr.v4.test.runtime.ErrorQueue;
import org.antlr.v4.test.runtime.RuntimeTestSupport;
import org.antlr.v4.test.runtime.StreamVacuum;
import org.antlr.v4.test.runtime.TestContext;
import org.antlr.v4.tool.ANTLRMessage;
import org.antlr.v4.tool.DOTGenerator;
import org.antlr.v4.tool.Grammar;
@ -45,6 +46,7 @@ import org.stringtemplate.v4.STGroup;
import org.stringtemplate.v4.STGroupString;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@ -55,6 +57,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import static org.antlr.v4.test.runtime.BaseRuntimeTest.antlrOnString;
import static org.antlr.v4.test.runtime.BaseRuntimeTest.writeFile;
@ -128,16 +131,6 @@ public class BaseNodeTest implements RuntimeTestSupport {
return antlrToolErrors.toString();
}
protected org.antlr.v4.Tool newTool(String[] args) {
Tool tool = new Tool(args);
return tool;
}
protected Tool newTool() {
org.antlr.v4.Tool tool = new Tool(new String[] { "-o", tmpdir });
return tool;
}
protected ATN createATN(Grammar g, boolean useSerializer) {
if (g.atn == null) {
semanticProcess(g);
@ -179,57 +172,6 @@ public class BaseNodeTest implements RuntimeTestSupport {
}
}
IntegerList getTypesFromString(Grammar g, String expecting) {
IntegerList expectingTokenTypes = new IntegerList();
if (expecting != null && !expecting.trim().isEmpty()) {
for (String tname : expecting.replace(" ", "").split(",")) {
int ttype = g.getTokenType(tname);
expectingTokenTypes.add(ttype);
}
}
return expectingTokenTypes;
}
public IntegerList getTokenTypesViaATN(String input,
LexerATNSimulator lexerATN) {
ANTLRInputStream in = new ANTLRInputStream(input);
IntegerList tokenTypes = new IntegerList();
int ttype;
do {
ttype = lexerATN.match(in, Lexer.DEFAULT_MODE);
tokenTypes.add(ttype);
} while (ttype != Token.EOF);
return tokenTypes;
}
public List<String> getTokenTypes(LexerGrammar lg, ATN atn, CharStream input) {
LexerATNSimulator interp = new LexerATNSimulator(atn,
new DFA[] { new DFA(
atn.modeToStartState.get(Lexer.DEFAULT_MODE)) }, null);
List<String> tokenTypes = new ArrayList<String>();
int ttype;
boolean hitEOF = false;
do {
if (hitEOF) {
tokenTypes.add("EOF");
break;
}
int t = input.LA(1);
ttype = interp.match(input, Lexer.DEFAULT_MODE);
if (ttype == Token.EOF) {
tokenTypes.add("EOF");
}
else {
tokenTypes.add(lg.typeToTokenList.get(ttype));
}
if (t == IntStream.EOF) {
hitEOF = true;
}
} while (ttype != Token.EOF);
return tokenTypes;
}
protected String execLexer(String grammarFileName, String grammarStr,
String lexerName, String input) {
return execLexer(grammarFileName, grammarStr, lexerName, input, false);
@ -243,8 +185,9 @@ public class BaseNodeTest implements RuntimeTestSupport {
assertTrue(success);
writeFile(tmpdir, "input", input);
writeLexerTestFile(lexerName, showDFA);
writeFile(tmpdir, "package.json", "{\"type\": \"module\"}");
String output = execModule("Test.js");
if ( output.length()==0 ) {
if ( output!=null && output.length()==0 ) {
output = null;
}
return output;
@ -262,6 +205,7 @@ public class BaseNodeTest implements RuntimeTestSupport {
writeFile(tmpdir, "input", input);
rawBuildRecognizerTestFile(parserName, lexerName, listenerName,
visitorName, startRuleName, showDiagnosticErrors);
writeFile(tmpdir, "package.json", "{\"type\": \"module\"}");
return execRecognizer();
}
@ -323,17 +267,21 @@ public class BaseNodeTest implements RuntimeTestSupport {
}
public String execModule(String fileName) {
String nodejsPath = locateNodeJS();
String runtimePath = locateRuntime();
String modulePath = new File(new File(tmpdir), fileName)
.getAbsolutePath();
String inputPath = new File(new File(tmpdir), "input")
.getAbsolutePath();
try {
String npmPath = locateNpm();
if(!TestContext.isTravisCI()) {
installRuntime(npmPath);
registerRuntime(npmPath);
}
String modulePath = new File(new File(tmpdir), fileName)
.getAbsolutePath();
linkRuntime(npmPath);
String nodejsPath = locateNodeJS();
String inputPath = new File(new File(tmpdir), "input")
.getAbsolutePath();
ProcessBuilder builder = new ProcessBuilder(nodejsPath, modulePath,
inputPath);
builder.environment().put("NODE_PATH",
runtimePath + File.pathSeparator + tmpdir);
builder.environment().put("NODE_PATH", tmpdir);
builder.directory(new File(tmpdir));
Process process = builder.start();
StreamVacuum stdoutVacuum = new StreamVacuum(
@ -342,7 +290,10 @@ public class BaseNodeTest implements RuntimeTestSupport {
process.getErrorStream());
stdoutVacuum.start();
stderrVacuum.start();
// TODO switch to jdk 8
process.waitFor();
// if(!process.waitFor(1L, TimeUnit.MINUTES))
// process.destroyForcibly();
stdoutVacuum.join();
stderrVacuum.join();
String output = stdoutVacuum.toString();
@ -353,22 +304,59 @@ public class BaseNodeTest implements RuntimeTestSupport {
this.stderrDuringParse = stderrVacuum.toString();
}
return output;
}
catch (Exception e) {
} catch (Exception e) {
System.err.println("can't exec recognizer");
e.printStackTrace(System.err);
System.err.println();
return null;
}
return null;
}
private String locateTool(String tool) {
String[] roots = { "/usr/bin/", "/usr/local/bin/" };
for (String root : roots) {
if (new File(root + tool).exists()) {
return root + tool;
}
}
return null;
private void installRuntime(String npmPath) throws IOException, InterruptedException {
String runtimePath = locateRuntime();
ProcessBuilder builder = new ProcessBuilder(npmPath, "install");
builder.directory(new File(runtimePath));
builder.redirectError(new File(tmpdir, "error.txt"));
builder.redirectOutput(new File(tmpdir, "output.txt"));
Process process = builder.start();
// TODO switch to jdk 8
process.waitFor();
// if(!process.waitFor(30L, TimeUnit.SECONDS))
// process.destroyForcibly();
int error = process.exitValue();
if(error!=0)
throw new IOException("'npm install' failed");
}
private void registerRuntime(String npmPath) throws IOException, InterruptedException {
String runtimePath = locateRuntime();
ProcessBuilder builder = new ProcessBuilder(npmPath, "link");
builder.directory(new File(runtimePath));
builder.redirectError(new File(tmpdir, "error.txt"));
builder.redirectOutput(new File(tmpdir, "output.txt"));
Process process = builder.start();
// TODO switch to jdk 8
process.waitFor();
// if(!process.waitFor(30L, TimeUnit.SECONDS))
// process.destroyForcibly();
int error = process.exitValue();
if(error!=0)
throw new IOException("'npm link' failed");
}
private void linkRuntime(String npmPath) throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder(npmPath, "link", "antlr4");
builder.directory(new File(tmpdir));
builder.redirectError(new File(tmpdir, "error.txt"));
builder.redirectOutput(new File(tmpdir, "output.txt"));
Process process = builder.start();
// TODO switch to jdk 8
process.waitFor();
// if(!process.waitFor(30L, TimeUnit.SECONDS))
// process.destroyForcibly();
int error = process.exitValue();
if(error!=0)
throw new IOException("'npm link antlr4' failed");
}
private boolean canExecute(String tool) {
@ -378,21 +366,29 @@ public class BaseNodeTest implements RuntimeTestSupport {
Process process = builder.start();
StreamVacuum vacuum = new StreamVacuum(process.getInputStream());
vacuum.start();
// TODO switch to jdk 8
process.waitFor();
// if(!process.waitFor(30L, TimeUnit.SECONDS))
// process.destroyForcibly();
vacuum.join();
return process.exitValue() == 0;
} catch (Exception e) {
return false;
}
catch (Exception e) {
;
}
private String locateNpm() {
// typically /usr/local/bin/npm
String prop = System.getProperty("antlr-javascript-npm");
if ( prop!=null && prop.length()!=0 ) {
return prop;
}
return false;
return "npm"; // everywhere
}
private String locateNodeJS() {
// typically /usr/local/bin/node
String propName = "antlr-javascript-nodejs";
String prop = System.getProperty(propName);
String prop = System.getProperty("antlr-javascript-nodejs");
if ( prop!=null && prop.length()!=0 ) {
return prop;
}
@ -404,7 +400,7 @@ public class BaseNodeTest implements RuntimeTestSupport {
private String locateRuntime() {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
final URL runtimeSrc = loader.getResource("JavaScript/src");
final URL runtimeSrc = loader.getResource("JavaScript");
if ( runtimeSrc==null ) {
throw new RuntimeException("Cannot find JavaScript runtime");
}
@ -418,213 +414,16 @@ public class BaseNodeTest implements RuntimeTestSupport {
return System.getProperty("os.name").toLowerCase().contains("windows");
}
// void ambig(List<Message> msgs, int[] expectedAmbigAlts, String
// expectedAmbigInput)
// throws Exception
// {
// ambig(msgs, 0, expectedAmbigAlts, expectedAmbigInput);
// }
// void ambig(List<Message> msgs, int i, int[] expectedAmbigAlts, String
// expectedAmbigInput)
// throws Exception
// {
// List<Message> amsgs = getMessagesOfType(msgs, AmbiguityMessage.class);
// AmbiguityMessage a = (AmbiguityMessage)amsgs.get(i);
// if ( a==null ) assertNull(expectedAmbigAlts);
// else {
// assertEquals(a.conflictingAlts.toString(),
// Arrays.toString(expectedAmbigAlts));
// }
// assertEquals(expectedAmbigInput, a.input);
// }
// void unreachable(List<Message> msgs, int[] expectedUnreachableAlts)
// throws Exception
// {
// unreachable(msgs, 0, expectedUnreachableAlts);
// }
// void unreachable(List<Message> msgs, int i, int[]
// expectedUnreachableAlts)
// throws Exception
// {
// List<Message> amsgs = getMessagesOfType(msgs,
// UnreachableAltsMessage.class);
// UnreachableAltsMessage u = (UnreachableAltsMessage)amsgs.get(i);
// if ( u==null ) assertNull(expectedUnreachableAlts);
// else {
// assertEquals(u.conflictingAlts.toString(),
// Arrays.toString(expectedUnreachableAlts));
// }
// }
List<ANTLRMessage> getMessagesOfType(List<ANTLRMessage> msgs,
Class<? extends ANTLRMessage> c) {
List<ANTLRMessage> filtered = new ArrayList<ANTLRMessage>();
for (ANTLRMessage m : msgs) {
if (m.getClass() == c)
filtered.add(m);
}
return filtered;
}
void checkRuleATN(Grammar g, String ruleName, String expecting) {
ParserATNFactory f = new ParserATNFactory(g);
ATN atn = f.createATN();
DOTGenerator dot = new DOTGenerator(g);
System.out
.println(dot.getDOT(atn.ruleToStartState[g.getRule(ruleName).index]));
Rule r = g.getRule(ruleName);
ATNState startState = atn.ruleToStartState[r.index];
ATNPrinter serializer = new ATNPrinter(g, startState);
String result = serializer.asString();
// System.out.print(result);
assertEquals(expecting, result);
}
public void testActions(String templates, String actionName, String action,
String expected) throws org.antlr.runtime.RecognitionException {
int lp = templates.indexOf('(');
String name = templates.substring(0, lp);
STGroup group = new STGroupString(templates);
ST st = group.getInstanceOf(name);
st.add(actionName, action);
String grammar = st.render();
ErrorQueue equeue = new ErrorQueue();
Grammar g = new Grammar(grammar, equeue);
if (g.ast != null && !g.ast.hasErrors) {
SemanticPipeline sem = new SemanticPipeline(g);
sem.process();
ATNFactory factory = new ParserATNFactory(g);
if (g.isLexer())
factory = new LexerATNFactory((LexerGrammar) g);
g.atn = factory.createATN();
CodeGenerator gen = new CodeGenerator(g);
ST outputFileST = gen.generateParser();
String output = outputFileST.render();
// System.out.println(output);
String b = "#" + actionName + "#";
int start = output.indexOf(b);
String e = "#end-" + actionName + "#";
int end = output.indexOf(e);
String snippet = output.substring(start + b.length(), end);
assertEquals(expected, snippet);
}
if (equeue.size() > 0) {
System.err.println(equeue.toString());
}
}
protected void checkGrammarSemanticsError(ErrorQueue equeue,
GrammarSemanticsMessage expectedMessage) throws Exception {
ANTLRMessage foundMsg = null;
for (int i = 0; i < equeue.errors.size(); i++) {
ANTLRMessage m = equeue.errors.get(i);
if (m.getErrorType() == expectedMessage.getErrorType()) {
foundMsg = m;
}
}
assertNotNull("no error; " + expectedMessage.getErrorType()
+ " expected", foundMsg);
assertTrue("error is not a GrammarSemanticsMessage",
foundMsg instanceof GrammarSemanticsMessage);
assertEquals(Arrays.toString(expectedMessage.getArgs()),
Arrays.toString(foundMsg.getArgs()));
if (equeue.size() != 1) {
System.err.println(equeue);
}
}
protected void checkGrammarSemanticsWarning(ErrorQueue equeue,
GrammarSemanticsMessage expectedMessage) throws Exception {
ANTLRMessage foundMsg = null;
for (int i = 0; i < equeue.warnings.size(); i++) {
ANTLRMessage m = equeue.warnings.get(i);
if (m.getErrorType() == expectedMessage.getErrorType()) {
foundMsg = m;
}
}
assertNotNull("no error; " + expectedMessage.getErrorType()
+ " expected", foundMsg);
assertTrue("error is not a GrammarSemanticsMessage",
foundMsg instanceof GrammarSemanticsMessage);
assertEquals(Arrays.toString(expectedMessage.getArgs()),
Arrays.toString(foundMsg.getArgs()));
if (equeue.size() != 1) {
System.err.println(equeue);
}
}
protected void checkError(ErrorQueue equeue, ANTLRMessage expectedMessage)
throws Exception {
// System.out.println("errors="+equeue);
ANTLRMessage foundMsg = null;
for (int i = 0; i < equeue.errors.size(); i++) {
ANTLRMessage m = equeue.errors.get(i);
if (m.getErrorType() == expectedMessage.getErrorType()) {
foundMsg = m;
}
}
assertTrue("no error; " + expectedMessage.getErrorType() + " expected",
!equeue.errors.isEmpty());
assertTrue("too many errors; " + equeue.errors,
equeue.errors.size() <= 1);
assertNotNull(
"couldn't find expected error: "
+ expectedMessage.getErrorType(), foundMsg);
/*
* assertTrue("error is not a GrammarSemanticsMessage", foundMsg
* instanceof GrammarSemanticsMessage);
*/
assertArrayEquals(expectedMessage.getArgs(), foundMsg.getArgs());
}
public static class FilteringTokenStream extends CommonTokenStream {
public FilteringTokenStream(TokenSource src) {
super(src);
}
Set<Integer> hide = new HashSet<Integer>();
@Override
protected boolean sync(int i) {
if (!super.sync(i)) {
return false;
}
Token t = get(i);
if (hide.contains(t.getType())) {
((WritableToken) t).setChannel(Token.HIDDEN_CHANNEL);
}
return true;
}
public void setTokenTypeChannel(int ttype, int channel) {
hide.add(ttype);
}
}
protected void mkdir(String dir) {
File f = new File(dir);
f.mkdirs();
}
protected void writeParserTestFile(String parserName, String lexerName,
String listenerName, String visitorName,
String parserStartRuleName, boolean debug) {
ST outputFileST = new ST(
"var antlr4 = require('antlr4');\n"
+ "var <lexerName> = require('./<lexerName>');\n"
+ "var <parserName> = require('./<parserName>');\n"
+ "var <listenerName> = require('./<listenerName>').<listenerName>;\n"
+ "var <visitorName> = require('./<visitorName>').<visitorName>;\n"
"import antlr4 from 'antlr4';\n"
+ "import <lexerName> from './<lexerName>.js';\n"
+ "import <parserName> from './<parserName>.js';\n"
+ "import <listenerName> from './<listenerName>.js';\n"
+ "import <visitorName> from './<visitorName>.js';\n"
+ "\n"
+ "class TreeShapeListener extends antlr4.tree.ParseTreeListener {\n" +
" enterEveryRule(ctx) {\n" +
@ -640,11 +439,11 @@ public class BaseNodeTest implements RuntimeTestSupport {
+ "\n"
+ "function main(argv) {\n"
+ " var input = new antlr4.FileStream(argv[2], true);\n"
+ " var lexer = new <lexerName>.<lexerName>(input);\n"
+ " var lexer = new <lexerName>(input);\n"
+ " var stream = new antlr4.CommonTokenStream(lexer);\n"
+ "<createParser>"
+ " parser.buildParseTrees = true;\n"
+ " printer = function() {\n"
+ " const printer = function() {\n"
+ " this.println = function(s) { console.log(s); }\n"
+ " this.print = function(s) { process.stdout.write(s); }\n"
+ " return this;\n"
@ -654,10 +453,10 @@ public class BaseNodeTest implements RuntimeTestSupport {
+ " antlr4.tree.ParseTreeWalker.DEFAULT.walk(new TreeShapeListener(), tree);\n"
+ "}\n" + "\n" + "main(process.argv);\n" + "\n");
ST createParserST = new ST(
" var parser = new <parserName>.<parserName>(stream);\n");
" var parser = new <parserName>(stream);\n");
if (debug) {
createParserST = new ST(
" var parser = new <parserName>.<parserName>(stream);\n"
" var parser = new <parserName>(stream);\n"
+ " parser.addErrorListener(new antlr4.error.DiagnosticErrorListener());\n");
}
outputFileST.add("createParser", createParserST);
@ -671,12 +470,12 @@ public class BaseNodeTest implements RuntimeTestSupport {
protected void writeLexerTestFile(String lexerName, boolean showDFA) {
ST outputFileST = new ST(
"var antlr4 = require('antlr4');\n"
+ "var <lexerName> = require('./<lexerName>');\n"
"import antlr4 from 'antlr4';\n"
+ "import <lexerName> from './<lexerName>.js';\n"
+ "\n"
+ "function main(argv) {\n"
+ " var input = new antlr4.FileStream(argv[2], true);\n"
+ " var lexer = new <lexerName>.<lexerName>(input);\n"
+ " var lexer = new <lexerName>(input);\n"
+ " var stream = new antlr4.CommonTokenStream(lexer);\n"
+ " stream.fill();\n"
+ " for(var i=0; i\\<stream.tokens.length; i++) {\n"
@ -689,28 +488,6 @@ public class BaseNodeTest implements RuntimeTestSupport {
writeFile(tmpdir, "Test.js", outputFileST.render());
}
public void writeRecognizer(String parserName, String lexerName,
String listenerName, String visitorName,
String parserStartRuleName, boolean debug) {
if (parserName == null) {
writeLexerTestFile(lexerName, debug);
}
else {
writeParserTestFile(parserName, lexerName, listenerName,
visitorName, parserStartRuleName, debug);
}
}
protected void eraseFiles(final String filesEndingWith) {
File tmpdirF = new File(tmpdir);
String[] files = tmpdirF.list();
for (int i = 0; files != null && i < files.length; i++) {
if (files[i].endsWith(filesEndingWith)) {
new File(tmpdir + "/" + files[i]).delete();
}
}
}
protected void eraseFiles(File dir) {
String[] files = dir.list();
for (int i = 0; files != null && i < files.length; i++) {
@ -734,153 +511,10 @@ public class BaseNodeTest implements RuntimeTestSupport {
}
}
public String getFirstLineOfException() {
if (this.stderrDuringParse == null) {
return null;
}
String[] lines = this.stderrDuringParse.split("\n");
String prefix = "Exception in thread \"main\" ";
return lines[0].substring(prefix.length(), lines[0].length());
}
/**
* When looking at a result set that consists of a Map/HashTable we cannot
* rely on the output order, as the hashing algorithm or other aspects of
* the implementation may be different on differnt JDKs or platforms. Hence
* we take the Map, convert the keys to a List, sort them and Stringify the
* Map, which is a bit of a hack, but guarantees that we get the same order
* on all systems. We assume that the keys are strings.
*
* @param m
* The Map that contains keys we wish to return in sorted order
* @return A string that represents all the keys in sorted order.
*/
public <K, V> String sortMapToString(Map<K, V> m) {
// Pass in crap, and get nothing back
//
if (m == null) {
return null;
}
System.out.println("Map toString looks like: " + m.toString());
// Sort the keys in the Map
//
TreeMap<K, V> nset = new TreeMap<K, V>(m);
System.out.println("Tree map looks like: " + nset.toString());
return nset.toString();
}
public List<String> realElements(List<String> elements) {
return elements.subList(Token.MIN_USER_TOKEN_TYPE, elements.size());
}
public void assertNotNullOrEmpty(String message, String text) {
assertNotNull(message, text);
assertFalse(message, text.isEmpty());
}
public void assertNotNullOrEmpty(String text) {
assertNotNull(text);
assertFalse(text.isEmpty());
}
public static class IntTokenStream implements TokenStream {
IntegerList types;
int p = 0;
public IntTokenStream(IntegerList types) {
this.types = types;
}
@Override
public void consume() {
p++;
}
@Override
public int LA(int i) {
return LT(i).getType();
}
@Override
public int mark() {
return index();
}
@Override
public int index() {
return p;
}
@Override
public void release(int marker) {
seek(marker);
}
@Override
public void seek(int index) {
p = index;
}
@Override
public int size() {
return types.size();
}
@Override
public String getSourceName() {
return null;
}
@Override
public Token LT(int i) {
CommonToken t;
int rawIndex = p + i - 1;
if (rawIndex >= types.size())
t = new CommonToken(Token.EOF);
else
t = new CommonToken(types.get(rawIndex));
t.setTokenIndex(rawIndex);
return t;
}
@Override
public Token get(int i) {
return new org.antlr.v4.runtime.CommonToken(types.get(i));
}
@Override
public TokenSource getTokenSource() {
return null;
}
@Override
public String getText() {
throw new UnsupportedOperationException("can't give strings");
}
@Override
public String getText(Interval interval) {
throw new UnsupportedOperationException("can't give strings");
}
@Override
public String getText(RuleContext ctx) {
throw new UnsupportedOperationException("can't give strings");
}
@Override
public String getText(Token start, Token stop) {
throw new UnsupportedOperationException("can't give strings");
}
}
/** Sort a list */
public <T extends Comparable<? super T>> List<T> sort(List<T> data) {
List<T> dup = new ArrayList<T>();
dup.addAll(data);
List<T> dup = new ArrayList<T>(data);
Collections.sort(dup);
return dup;
}
@ -889,8 +523,7 @@ public class BaseNodeTest implements RuntimeTestSupport {
public <K extends Comparable<? super K>, V> LinkedHashMap<K, V> sort(
Map<K, V> data) {
LinkedHashMap<K, V> dup = new LinkedHashMap<K, V>();
List<K> keys = new ArrayList<K>();
keys.addAll(data.keySet());
List<K> keys = new ArrayList<K>(data.keySet());
Collections.sort(keys);
for (K k : keys) {
dup.put(k, data.get(k));

View File

@ -79,7 +79,7 @@ namespace Antlr4.Runtime.Atn
return false;
}
Antlr4.Runtime.Atn.SingletonPredictionContext other = (Antlr4.Runtime.Atn.SingletonPredictionContext)o;
return returnState == other.returnState && parent.Equals(other.parent);
return returnState == other.returnState && (parent != null && parent.Equals(other.parent));
}
public override string ToString()

View File

@ -22,20 +22,20 @@ namespace Antlr4.Runtime
#if !PORTABLE
public class TraceListener : IParseTreeListener
{
private readonly TextWriter Output;
public TraceListener(TextWriter output) {
Output = output;
public TraceListener(TextWriter output,Parser enclosing) {
_output = output;
_enclosing = enclosing;
}
public virtual void EnterEveryRule(ParserRuleContext ctx)
{
Output.WriteLine("enter " + this._enclosing.RuleNames[ctx.RuleIndex] + ", LT(1)=" + this._enclosing._input.LT(1).Text);
_output.WriteLine("enter " + this._enclosing.RuleNames[ctx.RuleIndex] + ", LT(1)=" + this._enclosing._input.LT(1).Text);
}
public virtual void ExitEveryRule(ParserRuleContext ctx)
{
Output.WriteLine("exit " + this._enclosing.RuleNames[ctx.RuleIndex] + ", LT(1)=" + this._enclosing._input.LT(1).Text);
_output.WriteLine("exit " + this._enclosing.RuleNames[ctx.RuleIndex] + ", LT(1)=" + this._enclosing._input.LT(1).Text);
}
public virtual void VisitErrorNode(IErrorNode node)
@ -46,15 +46,17 @@ namespace Antlr4.Runtime
{
ParserRuleContext parent = (ParserRuleContext)((IRuleNode)node.Parent).RuleContext;
IToken token = node.Symbol;
Output.WriteLine("consume " + token + " rule " + this._enclosing.RuleNames[parent.RuleIndex]);
_output.WriteLine("consume " + token + " rule " + this._enclosing.RuleNames[parent.RuleIndex]);
}
internal TraceListener(Parser _enclosing)
{
this._enclosing = _enclosing;
_output = Console.Out;
}
private readonly Parser _enclosing;
private readonly TextWriter _output;
}
#endif

View File

@ -19,7 +19,7 @@ if(NOT WITH_DEMO)
FORCE)
endif(NOT WITH_DEMO)
option(WITH_LIBCXX "Building with clang++ and libc++(in Linux). To enable with: -DWITH_LIBCXX=On" On)
option(WITH_LIBCXX "Building with clang++ and libc++(in Linux). To enable with: -DWITH_LIBCXX=On" Off)
option(WITH_STATIC_CRT "(Visual C++) Enable to statically link CRT, which avoids requiring users to install the redistribution package.
To disable with: -DWITH_STATIC_CRT=Off" On)
@ -71,6 +71,9 @@ else()
set(MY_CXX_WARNING_FLAGS " -Wall -pedantic -W")
endif()
# Define USE_UTF8_INSTEAD_OF_CODECVT macro.
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_UTF8_INSTEAD_OF_CODECVT")
# Initialize CXXFLAGS.
if("${CMAKE_VERSION}" VERSION_GREATER 3.1.0)
set(CMAKE_CXX_STANDARD 11)

View File

@ -4,9 +4,27 @@
rm -f -R antlr4-runtime build lib 2> /dev/null
rm antlr4-cpp-runtime-macos.zip 2> /dev/null
# Get utf8 dependency.
mkdir -p runtime/thirdparty 2> /dev/null
pushd runtime/thirdparty
if [ ! -d utfcpp ]
then
git clone https://github.com/nemtrif/utfcpp.git utfcpp
pushd utfcpp
git checkout tags/v3.1.1
popd
fi
popd
# Binaries
xcodebuild -project runtime/antlrcpp.xcodeproj -target antlr4 -configuration Release
xcodebuild -project runtime/antlrcpp.xcodeproj -target antlr4_static -configuration Release
xcodebuild -project runtime/antlrcpp.xcodeproj \
-target antlr4 \
# GCC_PREPROCESSOR_DEFINITIONS='$GCC_PREPROCESSOR_DEFINITIONS USE_UTF8_INSTEAD_OF_CODECVT' \
-configuration Release
xcodebuild -project runtime/antlrcpp.xcodeproj \
-target antlr4_static \
# GCC_PREPROCESSOR_DEFINITIONS='$GCC_PREPROCESSOR_DEFINITIONS USE_UTF8_INSTEAD_OF_CODECVT' \
-configuration Release
rm -f -R lib
mkdir lib
mv runtime/build/Release/libantlr4-runtime.a lib/
@ -17,6 +35,9 @@ rm -f -R antlr4-runtime
pushd runtime/src
find . -name '*.h' | cpio -pdm ../../antlr4-runtime
popd
pushd runtime/thirdparty/utfcpp/source
find . -name '*.h' | cpio -pdm ../../../../antlr4-runtime
popd
# Zip up and clean up
zip -r antlr4-cpp-runtime-macos.zip antlr4-runtime lib

View File

@ -1,4 +1,19 @@
include(${CMAKE_ROOT}/Modules/ExternalProject.cmake)
set(THIRDPARTY_DIR ${CMAKE_BINARY_DIR}/runtime/thirdparty)
set(UTFCPP_DIR ${THIRDPARTY_DIR}/utfcpp)
ExternalProject_Add(
utfcpp
GIT_REPOSITORY "git://github.com/nemtrif/utfcpp"
GIT_TAG "v3.1.1"
SOURCE_DIR ${UTFCPP_DIR}
UPDATE_DISCONNECTED 1
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${UTFCPP_DIR}/install -Dgtest_force_shared_crt=ON
TEST_AFTER_INSTALL 1
STEP_TARGETS build)
include_directories(
${PROJECT_SOURCE_DIR}/runtime/src
${PROJECT_SOURCE_DIR}/runtime/src/atn
@ -8,6 +23,8 @@ include_directories(
${PROJECT_SOURCE_DIR}/runtime/src/tree
${PROJECT_SOURCE_DIR}/runtime/src/tree/pattern
${PROJECT_SOURCE_DIR}/runtime/src/tree/xpath
${UTFCPP_DIR}/install/include/utf8cpp
${UTFCPP_DIR}/install/include/utf8cpp/utf8
)
@ -33,8 +50,8 @@ add_custom_target(make_lib_output_dir ALL
COMMAND ${CMAKE_COMMAND} -E make_directory ${LIB_OUTPUT_DIR}
)
add_dependencies(antlr4_shared make_lib_output_dir)
add_dependencies(antlr4_static make_lib_output_dir)
add_dependencies(antlr4_shared make_lib_output_dir utfcpp)
add_dependencies(antlr4_static make_lib_output_dir utfcpp)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
target_link_libraries(antlr4_shared ${UUID_LIBRARIES})
@ -102,15 +119,23 @@ set_target_properties(antlr4_static
COMPILE_FLAGS "${disabled_compile_warnings} ${extra_static_compile_flags}")
install(TARGETS antlr4_shared
DESTINATION lib
DESTINATION lib
EXPORT antlr4-targets)
install(TARGETS antlr4_static
DESTINATION lib
EXPORT antlr4-targets)
install(DIRECTORY "${PROJECT_SOURCE_DIR}/runtime/src/"
install(DIRECTORY "${PROJECT_SOURCE_DIR}/runtime/src/"
DESTINATION "include/antlr4-runtime"
COMPONENT dev
COMPONENT dev
FILES_MATCHING PATTERN "*.h"
)
install(FILES "${UTFCPP_DIR}/source/utf8.h"
DESTINATION "include/antlr4-runtime")
install(DIRECTORY "${UTFCPP_DIR}/source/utf8"
DESTINATION "include/antlr4-runtime"
COMPONENT dev
FILES_MATCHING PATTERN "*.h"
)

View File

@ -182,6 +182,7 @@
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -201,6 +202,7 @@
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -220,6 +222,7 @@
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -239,6 +242,7 @@
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -259,6 +263,7 @@
</ForcedIncludeFiles>
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -281,6 +286,7 @@
</ForcedIncludeFiles>
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -303,6 +309,7 @@
</ForcedIncludeFiles>
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -325,6 +332,7 @@
</ForcedIncludeFiles>
<DisableSpecificWarnings>4251</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>

View File

@ -2889,7 +2889,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = src/;
HEADER_SEARCH_PATHS = "src/ thirdparty/utfcpp/source/ thirdparty/utfcpp/source/utf8/";
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
@ -2945,7 +2945,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = src/;
HEADER_SEARCH_PATHS = "src/ thirdparty/utfcpp/source/ thirdparty/utfcpp/source/utf8/";
MACOSX_DEPLOYMENT_TARGET = 10.9;
SDKROOT = macosx;
};

View File

@ -17,7 +17,11 @@ using namespace antlrcpp;
using misc::Interval;
#if __cplusplus >= 201703L
ANTLRInputStream::ANTLRInputStream(std::string_view input) {
#else
ANTLRInputStream::ANTLRInputStream(const std::string &input) {
#endif
InitializeInstanceFields();
load(input);
}
@ -31,6 +35,16 @@ ANTLRInputStream::ANTLRInputStream(std::istream &stream) {
load(stream);
}
#if __cplusplus >= 201703L
void ANTLRInputStream::load(std::string_view input) {
// Remove the UTF-8 BOM if present.
constexpr std::string_view bom = "\xef\xbb\xbf";
if (input.compare(0, 3, bom) == 0)
input.remove_prefix(3);
_data = antlrcpp::utf8_to_utf32(input.data(), input.data() + input.size());
p = 0;
}
#else
void ANTLRInputStream::load(const std::string &input) {
// Remove the UTF-8 BOM if present.
const char bom[4] = "\xef\xbb\xbf";
@ -40,6 +54,7 @@ void ANTLRInputStream::load(const std::string &input) {
_data = antlrcpp::utf8_to_utf32(input.data(), input.data() + input.size());
p = 0;
}
#endif
void ANTLRInputStream::load(std::istream &stream) {
if (!stream.good() || stream.eof()) // No fail, bad or EOF.

View File

@ -25,11 +25,19 @@ namespace antlr4 {
/// What is name or source of this char stream?
std::string name;
#if __cplusplus >= 201703L
ANTLRInputStream(std::string_view input = "");
#else
ANTLRInputStream(const std::string &input = "");
#endif
ANTLRInputStream(const char data_[], size_t numberOfActualCharsInArray);
ANTLRInputStream(std::istream &stream);
#if __cplusplus >= 201703L
virtual void load(std::string_view input);
#else
virtual void load(const std::string &input);
#endif
virtual void load(std::istream &stream);
/// Reset the stream so that it's in the same state it was

View File

@ -27,7 +27,13 @@ namespace antlr4 {
/// </summary>
class ANTLR4CPP_PUBLIC IntStream {
public:
static const size_t EOF = static_cast<size_t>(-1); // std::numeric_limits<size_t>::max(); doesn't work in VS 2013
#if __cplusplus >= 201703L
static constexpr size_t EOF = std::numeric_limits<size_t>::max();
#else
enum : size_t {
EOF = static_cast<size_t>(-1), // std::numeric_limits<size_t>::max(); doesn't work in VS 2013
};
#endif
/// The value returned by <seealso cref="#LA LA()"/> when the end of the stream is
/// reached.

View File

@ -18,14 +18,27 @@ namespace antlr4 {
/// of speed.
class ANTLR4CPP_PUBLIC Lexer : public Recognizer, public TokenSource {
public:
static const size_t DEFAULT_MODE = 0;
static const size_t MORE = static_cast<size_t>(-2);
static const size_t SKIP = static_cast<size_t>(-3);
#if __cplusplus >= 201703L
static constexpr size_t DEFAULT_MODE = 0;
static constexpr size_t MORE = std::numeric_limits<size_t>::max() - 1;
static constexpr size_t SKIP = std::numeric_limits<size_t>::max() - 2;
static const size_t DEFAULT_TOKEN_CHANNEL = Token::DEFAULT_CHANNEL;
static const size_t HIDDEN = Token::HIDDEN_CHANNEL;
static const size_t MIN_CHAR_VALUE = 0;
static const size_t MAX_CHAR_VALUE = 0x10FFFF;
static constexpr size_t DEFAULT_TOKEN_CHANNEL = Token::DEFAULT_CHANNEL;
static constexpr size_t HIDDEN = Token::HIDDEN_CHANNEL;
static constexpr size_t MIN_CHAR_VALUE = 0;
static constexpr size_t MAX_CHAR_VALUE = 0x10FFFF;
#else
enum : size_t {
DEFAULT_MODE = 0,
MORE = static_cast<size_t>(-2), // std::numeric_limits<size_t>::max() - 1; doesn't work in VS 2013
SKIP = static_cast<size_t>(-3), // std::numeric_limits<size_t>::max() - 2; doesn't work in VS 2013
DEFAULT_TOKEN_CHANNEL = Token::DEFAULT_CHANNEL,
HIDDEN = Token::HIDDEN_CHANNEL,
MIN_CHAR_VALUE = 0,
MAX_CHAR_VALUE = 0x10FFFF,
};
#endif
CharStream *_input; // Pure reference, usually from statically allocated instance.

View File

@ -190,7 +190,7 @@ void Parser::removeParseListeners() {
}
void Parser::triggerEnterRuleEvent() {
for (auto listener : _parseListeners) {
for (auto *listener : _parseListeners) {
listener->enterEveryRule(_ctx);
_ctx->enterRule(listener);
}
@ -307,14 +307,14 @@ Token* Parser::consume() {
tree::ErrorNode *node = createErrorNode(o);
_ctx->addChild(node);
if (_parseListeners.size() > 0) {
for (auto listener : _parseListeners) {
for (auto *listener : _parseListeners) {
listener->visitErrorNode(node);
}
}
} else {
tree::TerminalNode *node = _ctx->addChild(createTerminalNode(o));
if (_parseListeners.size() > 0) {
for (auto listener : _parseListeners) {
for (auto *listener : _parseListeners) {
listener->visitTerminal(node);
}
}

View File

@ -38,8 +38,8 @@ void ParserRuleContext::copyFrom(ParserRuleContext *ctx) {
// copy any error nodes to alt label node
if (!ctx->children.empty()) {
for (auto child : ctx->children) {
auto errorNode = dynamic_cast<ErrorNode *>(child);
for (auto *child : ctx->children) {
auto *errorNode = dynamic_cast<ErrorNode *>(child);
if (errorNode != nullptr) {
errorNode->setParent(this);
children.push_back(errorNode);
@ -82,7 +82,7 @@ tree::TerminalNode* ParserRuleContext::getToken(size_t ttype, size_t i) {
}
size_t j = 0; // what token with ttype have we found?
for (auto o : children) {
for (auto *o : children) {
if (is<tree::TerminalNode *>(o)) {
tree::TerminalNode *tnode = dynamic_cast<tree::TerminalNode *>(o);
Token *symbol = tnode->getSymbol();

View File

@ -114,7 +114,7 @@ namespace antlr4 {
template<typename T>
std::vector<T *> getRuleContexts() {
std::vector<T *> contexts;
for (auto child : children) {
for (auto *child : children) {
if (antlrcpp::is<T *>(child)) {
contexts.push_back(dynamic_cast<T *>(child));
}

View File

@ -26,28 +26,28 @@ void ProxyErrorListener::removeErrorListeners() {
void ProxyErrorListener::syntaxError(Recognizer *recognizer, Token *offendingSymbol, size_t line,
size_t charPositionInLine, const std::string &msg, std::exception_ptr e) {
for (auto listener : _delegates) {
for (auto *listener : _delegates) {
listener->syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e);
}
}
void ProxyErrorListener::reportAmbiguity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
bool exact, const antlrcpp::BitSet &ambigAlts, atn::ATNConfigSet *configs) {
for (auto listener : _delegates) {
for (auto *listener : _delegates) {
listener->reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs);
}
}
void ProxyErrorListener::reportAttemptingFullContext(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet &conflictingAlts, atn::ATNConfigSet *configs) {
for (auto listener : _delegates) {
for (auto *listener : _delegates) {
listener->reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs);
}
}
void ProxyErrorListener::reportContextSensitivity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
size_t prediction, atn::ATNConfigSet *configs) {
for (auto listener : _delegates) {
for (auto *listener : _delegates) {
listener->reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs);
}
}

View File

@ -11,7 +11,13 @@ namespace antlr4 {
class ANTLR4CPP_PUBLIC Recognizer {
public:
static const size_t EOF = static_cast<size_t>(-1); // std::numeric_limits<size_t>::max(); doesn't work in VS 2013.
#if __cplusplus >= 201703L
static constexpr size_t EOF = std::numeric_limits<size_t>::max();
#else
enum : size_t {
EOF = static_cast<size_t>(-1), // std::numeric_limits<size_t>::max(); doesn't work in VS 2013.
};
#endif
Recognizer();
Recognizer(Recognizer const&) = delete;

View File

@ -14,24 +14,50 @@ namespace antlr4 {
/// we obtained this token.
class ANTLR4CPP_PUBLIC Token {
public:
static const size_t INVALID_TYPE = 0;
#if __cplusplus >= 201703L
static constexpr size_t INVALID_TYPE = 0;
#else
enum : size_t {
INVALID_TYPE = 0,
};
#endif
/// During lookahead operations, this "token" signifies we hit rule end ATN state
/// and did not follow it despite needing to.
static const size_t EPSILON = static_cast<size_t>(-2);
static const size_t MIN_USER_TOKEN_TYPE = 1;
static const size_t EOF = IntStream::EOF;
#if __cplusplus >= 201703L
static constexpr size_t EPSILON = std::numeric_limits<size_t>::max() - 1;
static constexpr size_t MIN_USER_TOKEN_TYPE = 1;
static constexpr size_t EOF = IntStream::EOF;
#else
enum : size_t {
EPSILON = static_cast<size_t>(-2), // std::numeric_limits<size_t>::max() - 1; doesn't work in VS 2013
MIN_USER_TOKEN_TYPE = 1,
EOF = IntStream::EOF,
};
#endif
virtual ~Token();
/// All tokens go to the parser (unless skip() is called in that rule)
/// on a particular "channel". The parser tunes to a particular channel
/// so that whitespace etc... can go to the parser on a "hidden" channel.
static const size_t DEFAULT_CHANNEL = 0;
#if __cplusplus >= 201703L
static constexpr size_t DEFAULT_CHANNEL = 0;
#else
enum : size_t {
DEFAULT_CHANNEL = 0,
};
#endif
/// Anything on different channel than DEFAULT_CHANNEL is not parsed
/// by parser.
static const size_t HIDDEN_CHANNEL = 1;
#if __cplusplus >= 201703L
static constexpr size_t HIDDEN_CHANNEL = 1;
#else
enum : size_t {
HIDDEN_CHANNEL = 1,
};
#endif
/**
* This is the minimum constant value which can be assigned to a
@ -44,7 +70,13 @@ namespace antlr4 {
*
* @see Token#getChannel()
*/
static const size_t MIN_USER_CHANNEL_VALUE = 2;
#if __cplusplus >= 201703L
static constexpr size_t MIN_USER_CHANNEL_VALUE = 2;
#else
enum : size_t {
MIN_USER_CHANNEL_VALUE = 2,
};
#endif
/// Get the text of the token.
virtual std::string getText() const = 0;

View File

@ -94,7 +94,7 @@ TokenStreamRewriter::TokenStreamRewriter(TokenStream *tokens_) : tokens(tokens_)
TokenStreamRewriter::~TokenStreamRewriter() {
for (auto program : _programs) {
for (auto operation : program.second) {
for (auto *operation : program.second) {
delete operation;
}
}
@ -323,7 +323,7 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
// Wipe prior inserts within range
std::vector<InsertBeforeOp *> inserts = getKindOfOps<InsertBeforeOp>(rewrites, i);
for (auto iop : inserts) {
for (auto *iop : inserts) {
if (iop->index == rop->index) {
// E.g., insert before 2, delete 2..2; update replace
// text to include insert before, kill insert
@ -339,7 +339,7 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
}
// Drop any prior replaces contained within
std::vector<ReplaceOp*> prevReplaces = getKindOfOps<ReplaceOp>(rewrites, i);
for (auto prevRop : prevReplaces) {
for (auto *prevRop : prevReplaces) {
if (prevRop->index >= rop->index && prevRop->lastIndex <= rop->lastIndex) {
// delete replace as it's a no-op.
delete rewrites[prevRop->instructionIndex];
@ -373,7 +373,7 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
// combine current insert with prior if any at same index
std::vector<InsertBeforeOp *> prevInserts = getKindOfOps<InsertBeforeOp>(rewrites, i);
for (auto prevIop : prevInserts) {
for (auto *prevIop : prevInserts) {
if (prevIop->index == iop->index) { // combine objects
// convert to strings...we're in process of toString'ing
// whole token buffer so no lazy eval issue with any templates
@ -385,7 +385,7 @@ std::unordered_map<size_t, TokenStreamRewriter::RewriteOperation*> TokenStreamRe
}
// look for replaces where iop.index is in range; error
std::vector<ReplaceOp*> prevReplaces = getKindOfOps<ReplaceOp>(rewrites, i);
for (auto rop : prevReplaces) {
for (auto *rop : prevReplaces) {
if (iop->index == rop->index) {
rop->text = catOpText(&iop->text, &rop->text);
delete rewrites[i];

View File

@ -86,8 +86,15 @@ namespace antlr4 {
class ANTLR4CPP_PUBLIC TokenStreamRewriter {
public:
static const std::string DEFAULT_PROGRAM_NAME;
static const size_t PROGRAM_INIT_SIZE = 100;
static const size_t MIN_TOKEN_INDEX = 0;
#if __cplusplus >= 201703L
static constexpr size_t PROGRAM_INIT_SIZE = 100;
static constexpr size_t MIN_TOKEN_INDEX = 0;
#else
enum : size_t {
PROGRAM_INIT_SIZE = 100,
MIN_TOKEN_INDEX = 0,
};
#endif
TokenStreamRewriter(TokenStream *tokens);
virtual ~TokenStreamRewriter();

View File

@ -22,8 +22,7 @@ Vocabulary::Vocabulary(const std::vector<std::string> &literalNames,
// See note here on -1 part: https://github.com/antlr/antlr4/pull/1146
}
Vocabulary::~Vocabulary() {
}
Vocabulary::~Vocabulary() = default;
Vocabulary Vocabulary::fromTokenNames(const std::vector<std::string> &tokenNames) {
if (tokenNames.empty()) {
@ -34,25 +33,18 @@ Vocabulary Vocabulary::fromTokenNames(const std::vector<std::string> &tokenNames
std::vector<std::string> symbolicNames = tokenNames;
std::locale locale;
for (size_t i = 0; i < tokenNames.size(); i++) {
std::string tokenName = tokenNames[i];
if (tokenName == "") {
const std::string& tokenName = tokenNames[i];
if (tokenName.empty()) {
continue;
} else if (tokenName.front() == '\'') {
symbolicNames[i].clear();
} else if (std::isupper(tokenName.front(), locale)) {
literalNames[i].clear();
} else {
// wasn't a literal or symbolic name
literalNames[i].clear();
symbolicNames[i].clear();
}
if (!tokenName.empty()) {
char firstChar = tokenName[0];
if (firstChar == '\'') {
symbolicNames[i] = "";
continue;
} else if (std::isupper(firstChar, locale)) {
literalNames[i] = "";
continue;
}
}
// wasn't a literal or symbolic name
literalNames[i] = "";
symbolicNames[i] = "";
}
return Vocabulary(literalNames, symbolicNames, tokenNames);

View File

@ -14,9 +14,6 @@ namespace dfa {
/// interface.
class ANTLR4CPP_PUBLIC Vocabulary {
public:
Vocabulary(Vocabulary const&) = default;
virtual ~Vocabulary();
/// Gets an empty <seealso cref="Vocabulary"/> instance.
///
/// <para>
@ -25,7 +22,9 @@ namespace dfa {
/// except <seealso cref="Token#EOF"/>.</para>
static const Vocabulary EMPTY_VOCABULARY;
Vocabulary() {}
Vocabulary() = default;
Vocabulary(Vocabulary const&) = default;
virtual ~Vocabulary();
/// <summary>
/// Constructs a new instance of <seealso cref="Vocabulary"/> from the specified

View File

@ -8,7 +8,6 @@
#include <algorithm>
#include <assert.h>
#include <atomic>
#include <codecvt>
#include <chrono>
#include <fstream>
#include <iostream>
@ -37,6 +36,10 @@
#include <condition_variable>
#include <functional>
#ifndef USE_UTF8_INSTEAD_OF_CODECVT
#include <codecvt>
#endif
// Defines for the Guid class and other platform dependent stuff.
#ifdef _WIN32
#ifdef _MSC_VER

View File

@ -183,7 +183,7 @@ std::string ATN::toString() const {
ss << "states (" << states.size() << ") {" << std::endl;
size_t index = 0;
for (auto state : states) {
for (auto *state : states) {
if (state == nullptr) {
ss << " " << index++ << ": nul" << std::endl;
} else {
@ -193,7 +193,7 @@ std::string ATN::toString() const {
}
index = 0;
for (auto state : decisionToState) {
for (auto *state : decisionToState) {
if (state == nullptr) {
ss << " " << index++ << ": nul" << std::endl;
} else {

View File

@ -12,7 +12,13 @@ namespace atn {
class ANTLR4CPP_PUBLIC ATN {
public:
static const size_t INVALID_ALT_NUMBER = 0;
#if __cplusplus >= 201703L
static constexpr size_t INVALID_ALT_NUMBER = 0;
#else
enum : size_t {
INVALID_ALT_NUMBER = 0,
};
#endif
/// Used for runtime deserialization of ATNs from strings.
ATN();

View File

@ -11,8 +11,6 @@
using namespace antlr4::atn;
const size_t ATNConfig::SUPPRESS_PRECEDENCE_FILTER = 0x40000000;
ATNConfig::ATNConfig(ATNState *state_, size_t alt_, Ref<PredictionContext> const& context_)
: ATNConfig(state_, alt_, context_, SemanticContext::NONE) {
}

View File

@ -114,7 +114,13 @@ namespace atn {
* {@link #isPrecedenceFilterSuppressed} property as a bit within the
* existing {@link #reachesIntoOuterContext} field.
*/
static const size_t SUPPRESS_PRECEDENCE_FILTER;
#if __cplusplus >= 201703L
static constexpr size_t SUPPRESS_PRECEDENCE_FILTER = 0x40000000;
#else
enum : size_t {
SUPPRESS_PRECEDENCE_FILTER = 0x40000000,
};
#endif
};
} // namespace atn
@ -139,7 +145,7 @@ namespace std {
size_t operator() (const std::vector<Ref<ATNConfig>> &vector) const
{
std::size_t seed = 0;
for (auto &config : vector) {
for (const auto &config : vector) {
seed ^= config->hashCode() + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;

View File

@ -57,8 +57,6 @@ using namespace antlr4;
using namespace antlr4::atn;
using namespace antlrcpp;
const size_t ATNDeserializer::SERIALIZED_VERSION = 3;
namespace {
uint32_t deserializeInt32(const std::vector<uint16_t>& data, size_t offset) {

View File

@ -13,7 +13,13 @@ namespace atn {
class ANTLR4CPP_PUBLIC ATNDeserializer {
public:
static const size_t SERIALIZED_VERSION;
#if __cplusplus >= 201703L
static constexpr size_t SERIALIZED_VERSION = 3;
#else
enum : size_t {
SERIALIZED_VERSION = 3,
};
#endif
/// This is the current serialized UUID.
// ml: defined as function to avoid the “static initialization order fiasco”.

View File

@ -166,7 +166,7 @@ std::vector<size_t> ATNSerializer::serialize() {
}
data.push_back(containsEof ? 1 : 0);
for (auto &interval : set.getIntervals()) {
for (const auto &interval : set.getIntervals()) {
if (interval.a == -1) {
if (interval.b == -1) {
continue;

View File

@ -17,7 +17,7 @@ ATNState::ATNState() {
}
ATNState::~ATNState() {
for (auto transition : transitions) {
for (auto *transition : transitions) {
delete transition;
}
}

View File

@ -81,8 +81,15 @@ namespace atn {
ATNState& operator=(ATNState const&) = delete;
static const size_t INITIAL_NUM_TRANSITIONS = 4;
static const size_t INVALID_STATE_NUMBER = static_cast<size_t>(-1); // std::numeric_limits<size_t>::max();
#if __cplusplus >= 201703L
static constexpr size_t INITIAL_NUM_TRANSITIONS = 4;
static constexpr size_t INVALID_STATE_NUMBER = std::numeric_limits<size_t>::max();
#else
enum : size_t {
INITIAL_NUM_TRANSITIONS = 4,
INVALID_STATE_NUMBER = static_cast<size_t>(-1), // std::numeric_limits<size_t>::max(); doesn't work in VS 2013
};
#endif
enum {
ATN_INVALID_TYPE = 0,

View File

@ -17,7 +17,13 @@ namespace atn {
public:
/// Special value added to the lookahead sets to indicate that we hit
/// a predicate during analysis if {@code seeThruPreds==false}.
static const size_t HIT_PRED = Token::INVALID_TYPE;
#if __cplusplus >= 201703L
static constexpr size_t HIT_PRED = Token::INVALID_TYPE;
#else
enum : size_t {
HIT_PRED = Token::INVALID_TYPE,
};
#endif
const atn::ATN &_atn;

View File

@ -38,8 +38,15 @@ namespace atn {
public:
static const size_t MIN_DFA_EDGE = 0;
static const size_t MAX_DFA_EDGE = 127; // forces unicode to stay in ATN
#if __cplusplus >= 201703L
static constexpr size_t MIN_DFA_EDGE = 0;
static constexpr size_t MAX_DFA_EDGE = 127; // forces unicode to stay in ATN
#else
enum : size_t {
MIN_DFA_EDGE = 0,
MAX_DFA_EDGE = 127, // forces unicode to stay in ATN
};
#endif
protected:
/// <summary>

View File

@ -774,7 +774,7 @@ std::pair<ATNConfigSet *, ATNConfigSet *> ParserATNSimulator::splitAccordingToSe
BitSet ParserATNSimulator::evalSemanticContext(std::vector<dfa::DFAState::PredPrediction*> predPredictions,
ParserRuleContext *outerContext, bool complete) {
BitSet predictions;
for (auto prediction : predPredictions) {
for (auto *prediction : predPredictions) {
if (prediction->pred == SemanticContext::NONE) {
predictions.set(prediction->alt);
if (!complete) {

View File

@ -30,10 +30,22 @@ namespace atn {
// ml: originally Integer.MAX_VALUE, which would be -1 for us, but this is already used in places where
// -1 is converted to unsigned, so we use a different value here. Any value does the job provided it doesn't
// conflict with real return states.
static const size_t EMPTY_RETURN_STATE = static_cast<size_t>(-10); // std::numeric_limits<size_t>::max() - 9;
#if __cplusplus >= 201703L
static constexpr size_t EMPTY_RETURN_STATE = std::numeric_limits<size_t>::max() - 9;
#else
enum : size_t {
EMPTY_RETURN_STATE = static_cast<size_t>(-10), // std::numeric_limits<size_t>::max() - 9; doesn't work in VS 2013
};
#endif
private:
static const size_t INITIAL_HASH = 1;
#if __cplusplus >= 201703L
static constexpr size_t INITIAL_HASH = 1;
#else
enum : size_t {
INITIAL_HASH = 1,
};
#endif
public:
static size_t globalNodeCount;

View File

@ -46,7 +46,7 @@ DFA::DFA(DFA &&other) : atnStartState(other.atnStartState), decision(other.decis
DFA::~DFA() {
bool s0InList = (s0 == nullptr);
for (auto state : states) {
for (auto *state : states) {
if (state == s0)
s0InList = true;
delete state;
@ -88,7 +88,7 @@ void DFA::setPrecedenceStartState(int precedence, DFAState *startState, SingleWr
std::vector<DFAState *> DFA::getStates() const {
std::vector<DFAState *> result;
for (auto state : states)
for (auto *state : states)
result.push_back(state);
std::sort(result.begin(), result.end(), [](DFAState *o1, DFAState *o2) -> bool {

View File

@ -27,7 +27,7 @@ std::string DFASerializer::toString() const {
std::stringstream ss;
std::vector<DFAState *> states = _dfa->getStates();
for (auto s : states) {
for (auto *s : states) {
for (size_t i = 0; i < s->edges.size(); i++) {
DFAState *t = s->edges[i];
if (t != nullptr && t->stateNumber != INT32_MAX) {

View File

@ -42,7 +42,7 @@ DFAState::DFAState(std::unique_ptr<ATNConfigSet> configs_) : DFAState() {
}
DFAState::~DFAState() {
for (auto predicate : predicates) {
for (auto *predicate : predicates) {
delete predicate;
}
}

View File

@ -112,7 +112,7 @@ void IntervalSet::add(const Interval &addition) {
IntervalSet IntervalSet::Or(const std::vector<IntervalSet> &sets) {
IntervalSet result;
for (auto &s : sets) {
for (const auto &s : sets) {
result.addAll(s);
}
return result;
@ -271,7 +271,7 @@ bool IntervalSet::contains(ssize_t el) const {
if (el < _intervals[0].a) // list is sorted and el is before first interval; not here
return false;
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
if (el >= interval.a && el <= interval.b) {
return true; // found in this interval
}
@ -315,7 +315,7 @@ std::vector<Interval> const& IntervalSet::getIntervals() const {
size_t IntervalSet::hashCode() const {
size_t hash = MurmurHash::initialize();
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
hash = MurmurHash::update(hash, interval.a);
hash = MurmurHash::update(hash, interval.b);
}
@ -349,7 +349,7 @@ std::string IntervalSet::toString(bool elemAreChar) const {
}
bool firstEntry = true;
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
if (!firstEntry)
ss << ", ";
firstEntry = false;
@ -395,7 +395,7 @@ std::string IntervalSet::toString(const dfa::Vocabulary &vocabulary) const {
}
bool firstEntry = true;
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
if (!firstEntry)
ss << ", ";
firstEntry = false;
@ -436,7 +436,7 @@ std::string IntervalSet::elementName(const dfa::Vocabulary &vocabulary, ssize_t
size_t IntervalSet::size() const {
size_t result = 0;
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
result += size_t(interval.b - interval.a + 1);
}
return result;
@ -444,7 +444,7 @@ size_t IntervalSet::size() const {
std::vector<ssize_t> IntervalSet::toList() const {
std::vector<ssize_t> result;
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
ssize_t a = interval.a;
ssize_t b = interval.b;
for (ssize_t v = a; v <= b; v++) {
@ -456,7 +456,7 @@ std::vector<ssize_t> IntervalSet::toList() const {
std::set<ssize_t> IntervalSet::toSet() const {
std::set<ssize_t> result;
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
ssize_t a = interval.a;
ssize_t b = interval.b;
for (ssize_t v = a; v <= b; v++) {
@ -468,7 +468,7 @@ std::set<ssize_t> IntervalSet::toSet() const {
ssize_t IntervalSet::get(size_t i) const {
size_t index = 0;
for (auto &interval : _intervals) {
for (const auto &interval : _intervals) {
ssize_t a = interval.a;
ssize_t b = interval.b;
for (ssize_t v = a; v <= b; v++) {

View File

@ -13,7 +13,13 @@ namespace misc {
class ANTLR4CPP_PUBLIC MurmurHash {
private:
static const size_t DEFAULT_SEED = 0;
#if __cplusplus >= 201703L
static constexpr size_t DEFAULT_SEED = 0;
#else
enum : size_t {
DEFAULT_SEED = 0,
};
#endif
/// Initialize the hash using the default seed value.
/// Returns the intermediate hash value.

View File

@ -79,7 +79,7 @@ struct ANTLR4CPP_PUBLIC Any
if (_ptr == a._ptr)
return *this;
auto old_ptr = _ptr;
auto * old_ptr = _ptr;
_ptr = a.clone();
if (old_ptr)

View File

@ -16,7 +16,7 @@ std::string Arrays::listToString(const std::vector<std::string> &list, const std
bool firstEntry = true;
ss << '[';
for (auto &entry : list) {
for (const auto &entry : list) {
ss << entry;
if (firstEntry) {
ss << separator;
@ -32,7 +32,7 @@ template <>
std::string Arrays::toString(const std::vector<antlr4::tree::ParseTree*> &source) {
std::string result = "[";
bool firstEntry = true;
for (auto value : source) {
for (auto *value : source) {
result += value->toStringTree();
if (firstEntry) {
result += ", ";

View File

@ -46,7 +46,7 @@ namespace antlrcpp {
case ' ':
if (escapeSpaces) {
result += "·";
result += "\u00B7";
break;
}
// else fall through

View File

@ -20,16 +20,26 @@ void replaceAll(std::string& str, std::string const& from, std::string const& to
}
std::string ws2s(std::wstring const& wstr) {
#ifndef USE_UTF8_INSTEAD_OF_CODECVT
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string narrow = converter.to_bytes(wstr);
#else
std::string narrow;
utf8::utf32to8(wstr.begin(), wstr.end(), std::back_inserter(narrow));
#endif
return narrow;
}
std::wstring s2ws(const std::string &str) {
#ifndef USE_UTF8_INSTEAD_OF_CODECVT
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wide = converter.from_bytes(str);
#else
std::wstring wide;
utf8::utf8to32(str.begin(), str.end(), std::back_inserter(wide));
#endif
return wide;
}

View File

@ -7,43 +7,65 @@
#include "antlr4-common.h"
#ifdef USE_UTF8_INSTEAD_OF_CODECVT
#include "utf8.h"
#endif
namespace antlrcpp {
// For all conversions utf8 <-> utf32.
// I wouldn't prefer wstring_convert because: according to
// https://en.cppreference.com/w/cpp/locale/wstring_convert,
// wstring_convert is deprecated in C++17.
// utfcpp (https://github.com/nemtrif/utfcpp) is a substitution.
#ifndef USE_UTF8_INSTEAD_OF_CODECVT
// VS 2015 and VS 2017 have different bugs in std::codecvt_utf8<char32_t> (VS 2013 works fine).
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
typedef std::wstring_convert<std::codecvt_utf8<__int32>, __int32> UTF32Converter;
#else
typedef std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> UTF32Converter;
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
typedef std::wstring_convert<std::codecvt_utf8<__int32>, __int32> UTF32Converter;
#else
typedef std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> UTF32Converter;
#endif
#endif
// The conversion functions fails in VS2017, so we explicitly use a workaround.
template<typename T>
inline std::string utf32_to_utf8(T const& data)
{
// Don't make the converter static or we have to serialize access to it.
thread_local UTF32Converter converter;
#ifndef USE_UTF8_INSTEAD_OF_CODECVT
// Don't make the converter static or we have to serialize access to it.
thread_local UTF32Converter converter;
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
auto p = reinterpret_cast<const int32_t *>(data.data());
return converter.to_bytes(p, p + data.size());
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
const auto p = reinterpret_cast<const int32_t *>(data.data());
return converter.to_bytes(p, p + data.size());
#else
return converter.to_bytes(data);
#endif
#else
return converter.to_bytes(data);
std::string narrow;
utf8::utf32to8(data.begin(), data.end(), std::back_inserter(narrow));
return narrow;
#endif
}
inline UTF32String utf8_to_utf32(const char* first, const char* last)
{
thread_local UTF32Converter converter;
#ifndef USE_UTF8_INSTEAD_OF_CODECVT
thread_local UTF32Converter converter;
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
auto r = converter.from_bytes(first, last);
i32string s = reinterpret_cast<const int32_t *>(r.data());
#if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000
auto r = converter.from_bytes(first, last);
i32string s = reinterpret_cast<const int32_t *>(r.data());
return s;
#else
std::u32string s = converter.from_bytes(first, last);
return s;
#endif
#else
std::u32string s = converter.from_bytes(first, last);
UTF32String wide;
utf8::utf8to32(first, last, std::back_inserter(wide));
return wide;
#endif
return s;
}
void replaceAll(std::string &str, std::string const& from, std::string const& to);

View File

@ -88,7 +88,7 @@ namespace tree {
}
void reset() {
for (auto entry : _allocated)
for (auto * entry : _allocated)
delete entry;
_allocated.clear();
}

View File

@ -192,7 +192,7 @@ std::vector<ParseTree *> Trees::getDescendants(ParseTree *t) {
std::size_t n = t->children.size();
for (size_t i = 0 ; i < n ; i++) {
auto descentants = getDescendants(t->children[i]);
for (auto entry: descentants) {
for (auto *entry: descentants) {
nodes.push_back(entry);
}
}

View File

@ -37,7 +37,7 @@ std::vector<ParseTreeMatch> ParseTreePattern::findAll(ParseTree *tree, const std
xpath::XPath finder(_matcher->getParser(), xpath);
std::vector<ParseTree *> subtrees = finder.evaluate(tree);
std::vector<ParseTreeMatch> matches;
for (auto t : subtrees) {
for (auto *t : subtrees) {
ParseTreeMatch aMatch = match(t);
if (aMatch.succeeded()) {
matches.push_back(aMatch);

View File

@ -137,7 +137,7 @@ std::vector<ParseTree *> XPath::evaluate(ParseTree *t) {
while (i < elements.size()) {
std::vector<ParseTree *> next;
for (auto node : work) {
for (auto *node : work) {
if (!node->children.empty()) {
// only try to match next element if it has children
// e.g., //func/*/stat might have a token node for which

Some files were not shown because too many files have changed in this diff Show More