diff --git a/.gitignore b/.gitignore index af9050eef..c6e172a5b 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,4 @@ xcuserdata # VSCode Java plugin temporary files javac-services.0.log javac-services.0.log.lck +test/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..7944e8e32 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "runtime/PHP"] + path = runtime/PHP + url = https://github.com/antlr/antlr-php-runtime.git diff --git a/.travis.yml b/.travis.yml index 760f36be4..0220f4ca2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,8 +19,9 @@ stages: matrix: include: - os: linux + dist: trusty compiler: clang - jdk: openjdk7 + jdk: openjdk8 env: - TARGET=cpp - CXX=g++-5 @@ -36,8 +37,9 @@ matrix: - uuid-dev - clang-3.7 - os: linux + dist: trusty compiler: clang - jdk: openjdk7 + jdk: openjdk8 env: - TARGET=cpp - CXX=g++-5 @@ -53,8 +55,9 @@ matrix: - uuid-dev - clang-3.7 - os: linux + dist: trusty compiler: clang - jdk: openjdk7 + jdk: openjdk8 env: - TARGET=cpp - CXX=g++-5 @@ -137,23 +140,27 @@ matrix: - GROUP=RECURSION stage: extended-test - os: linux + dist: trusty jdk: openjdk7 env: TARGET=java stage: extended-test - os: linux jdk: openjdk8 env: TARGET=java - stage: extended-test - - os: linux - jdk: oraclejdk8 - env: TARGET=java stage: smoke-test - os: linux - jdk: openjdk7 + jdk: openjdk8 env: TARGET=csharp stage: main-test - os: linux - jdk: oraclejdk8 + language: php + php: + - 7.2 + jdk: openjdk8 + env: TARGET=php + stage: main-test + - os: linux + jdk: openjdk8 dist: trusty env: - TARGET=dotnet @@ -167,18 +174,18 @@ matrix: - GROUP=PARSER stage: extended-test - os: linux - jdk: oraclejdk8 + jdk: openjdk8 dist: trusty env: - TARGET=dotnet - GROUP=RECURSION stage: extended-test - os: linux - jdk: openjdk7 + jdk: openjdk8 env: TARGET=python2 stage: main-test - os: linux - jdk: openjdk7 + jdk: openjdk8 env: TARGET=python3 addons: apt: diff --git a/.travis/before-install-linux-csharp.sh b/.travis/before-install-linux-csharp.sh index fc8cbcec2..0872a4635 100755 --- a/.travis/before-install-linux-csharp.sh +++ b/.travis/before-install-linux-csharp.sh @@ -3,6 +3,6 @@ set -euo pipefail sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +echo "deb http://download.mono-project.com/repo/debian xenial main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list sudo apt-get update -qq -echo "deb http://download.mono-project.com/repo/debian wheezy/snapshots/3.12.1 main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list sudo apt-get install -qq mono-complete diff --git a/.travis/before-install-linux-dotnet.sh b/.travis/before-install-linux-dotnet.sh index bfe4eff76..816044f40 100755 --- a/.travis/before-install-linux-dotnet.sh +++ b/.travis/before-install-linux-dotnet.sh @@ -6,5 +6,5 @@ set -euo pipefail sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list' sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893 sudo apt-get update -sudo apt-get install dotnet-dev-1.0.4 +sudo apt-get --allow-unauthenticated install dotnet-dev-1.0.4 diff --git a/.travis/before-install-linux-php.sh b/.travis/before-install-linux-php.sh new file mode 100755 index 000000000..b95e3b31d --- /dev/null +++ b/.travis/before-install-linux-php.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -euo pipefail + +sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF +sudo apt-get update -qq + +php -v + +mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V \ No newline at end of file diff --git a/.travis/run-tests-php.sh b/.travis/run-tests-php.sh new file mode 100755 index 000000000..853efbd86 --- /dev/null +++ b/.travis/run-tests-php.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -euo pipefail + +php_path=$(which php) + +composer install -d ../runtime/PHP + +mvn -q -DPHP_PATH="${php_path}" -Dparallel=methods -DthreadCount=4 -Dtest=php.* test diff --git a/.travis/run-tests-python2.sh b/.travis/run-tests-python2.sh index 4d23f32a2..d2a22dc77 100755 --- a/.travis/run-tests-python2.sh +++ b/.travis/run-tests-python2.sh @@ -3,3 +3,7 @@ set -euo pipefail mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=python2.* test + +cd ../runtime/Python2/tests + +python run.py \ No newline at end of file diff --git a/.travis/run-tests-python3.sh b/.travis/run-tests-python3.sh index 2a6ff050d..9b528f35b 100755 --- a/.travis/run-tests-python3.sh +++ b/.travis/run-tests-python3.sh @@ -3,3 +3,7 @@ set -euo pipefail mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=python3.* test + +cd ../runtime/Python3/test + +python3.6 run.py \ No newline at end of file diff --git a/README.md b/README.md index d63bc4f66..ec5c21c62 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ ANTLR project lead and supreme dictator for life * [Janyou](https://github.com/janyou) (Swift target) * [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) ## Useful information diff --git a/appveyor.yml b/appveyor.yml index 266eeebad..d58657c98 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,9 @@ cache: - '%USERPROFILE%\.nuget\packages -> **\project.json' image: Visual Studio 2017 build: off +install: + - git submodule update --init --recursive + - cinst -y php composer 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 @@ -11,7 +14,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-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\php73\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 artifacts: - path: 'runtime\**\*.nupkg' name: NuGet \ No newline at end of file diff --git a/contributors.txt b/contributors.txt index 58c23e4ae..2c82eaffb 100644 --- a/contributors.txt +++ b/contributors.txt @@ -203,6 +203,8 @@ YYYY/MM/DD, github id, Full name, email 2018/06/16, EternalPhane, Zongyuan Zuo, eternalphane@gmail.com 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/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 2018/10/29, chrisaycock, Christopher Aycock, chris[at]chrisaycock[dot]com @@ -214,3 +216,20 @@ YYYY/MM/DD, github id, Full name, email 2018/12/23, youkaichao, Kaichao You, youkaichao@gmail.com 2019/02/06, ralucado, Cristina Raluca Vijulie, ralucris.v[at]gmail[dot]com 2019/02/23, gedimitr, Gerasimos Dimitriadis, gedimitr@gmail.com +2019/03/13, base698, Justin Thomas, justin.thomas1@gmail.com +2019/03/18, carlodri, Carlo Dri, carlo.dri@gmail.com +2019/05/02, askingalot, Andy Collins, askingalot@gmail.com +2019/07/11, olowo726, Olof Wolgast, olof@baah.se +2019/07/16, abhijithneilabraham, Abhijith Neil Abraham, abhijithneilabrahampk@gmail.com +2019/07/26, Braavos96, Eric Hettiaratchi, erichettiaratchi@gmail.com +2019/08/23, akaJes, Oleksandr Mamchyts, akaJes@gmail.com +2019/09/10, ImanHosseini, Iman Hosseini, hosseini.iman@yahoo.com +2019/09/03, João Henrique, johnnyonflame@hotmail.com +2019/09/10, neko1235, Ihar Mokharau, igor.mohorev@gmail.com +2019/09/10, yar3333, Yaroslav Sivakov, yar3333@gmail.com +2019/09/10, marcospassos, Marcos Passos, marcospassos.com@gmail.com +2019/09/10, amorimjuliana, Juliana Amorim, juu.amorim@gmail.com +2019/09/17, kaz, Kazuki Sawada, kazuki@6715.jp +2019/09/28, lmy269, Mingyang Liu, lmy040758@gmail.com +2019/10/31, a-square, Alexei Averchenko, lex.aver@gmail.com +2019/11/11, foxeverl, Liu Xinfeng, liuxf1986[at]gmail[dot]com diff --git a/doc/case-insensitive-lexing.md b/doc/case-insensitive-lexing.md index 8e9a4f72a..4c4248438 100644 --- a/doc/case-insensitive-lexing.md +++ b/doc/case-insensitive-lexing.md @@ -14,7 +14,7 @@ For the 4.7.1 release, we discussed both approaches in [detail](https://github.c ## Case-insensitive grammars -As a prime example of a grammar that specifically describes case insensitive keywords, see the +As a prime example of a grammar that specifically describes case insensitive keywords, see the [SQLite grammar](https://github.com/antlr/grammars-v4/blob/master/sqlite/SQLite.g4). To match a case insensitive keyword, there are rules such as ``` @@ -72,7 +72,8 @@ Lexer lexer = new SomeSQLLexer(upper); Here are implementations of `CaseChangingCharStream` in various target languages: -* [Java](https://github.com/parrt/antlr4/blob/case-insensitivity-doc/doc/resources/CaseChangingCharStream.java) -* [JavaScript](https://github.com/parrt/antlr4/blob/case-insensitivity-doc/doc/resources/CaseInsensitiveInputStream.js) -* [Go](https://github.com/parrt/antlr4/blob/case-insensitivity-doc/doc/resources/case_changing_stream.go) -* [C#](https://github.com/parrt/antlr4/blob/case-insensitivity-doc/doc/resources/CaseChangingCharStream.cs) \ No newline at end of file +* [C#](https://github.com/antlr/antlr4/blob/master/doc/resources/CaseChangingCharStream.cs) +* [Go](https://github.com/antlr/antlr4/blob/master/doc/resources/case_changing_stream.go) +* [Java](https://github.com/antlr/antlr4/blob/master/doc/resources/CaseChangingCharStream.java) +* [JavaScript](https://github.com/antlr/antlr4/blob/master/doc/resources/CaseChangingStream.js) +* [Python2/3](https://github.com/antlr/antlr4/blob/master/doc/resources/CaseChangingStream.py) diff --git a/doc/cpp-target.md b/doc/cpp-target.md index 2933d606e..eec7cf88b 100644 --- a/doc/cpp-target.md +++ b/doc/cpp-target.md @@ -45,7 +45,7 @@ The generation step above created a listener and base listener class for you. Th #include "MyGrammarParser.h" #include "MyGrammarBaseListener.h" -using namespace org::antlr::v4::runtime; +using namespace antlr4; class TreeShapeListener : public MyGrammarBaseListener { public: diff --git a/doc/csharp-target.md b/doc/csharp-target.md index 40be51840..a869a82f6 100644 --- a/doc/csharp-target.md +++ b/doc/csharp-target.md @@ -30,7 +30,7 @@ Let's suppose that your grammar is named `MyGrammar`. The tool will generate for Now a fully functioning code might look like the following for start rule `StartRule`: -``` +```csharp using Antlr4.Runtime; using Antlr4.Runtime.Tree; @@ -59,7 +59,7 @@ Let's suppose your MyGrammar grammar comprises 2 rules: "key" and "value". The antlr4 tool will have generated the following listener (only partial code shown here): -``` +```csharp interface IMyGrammarParserListener : IParseTreeListener { void EnterKey (MyGrammarParser.KeyContext context); void ExitKey (MyGrammarParser.KeyContext context); @@ -70,7 +70,7 @@ interface IMyGrammarParserListener : IParseTreeListener { In order to provide custom behavior, you might want to create the following class: -``` +```csharp class KeyPrinter : MyGrammarBaseListener { // override default listener behavior void ExitKey (MyGrammarParser.KeyContext context) { @@ -82,7 +82,7 @@ class KeyPrinter : MyGrammarBaseListener { In order to execute this listener, you would simply add the following lines to the above code: -``` +```csharp ... IParseTree tree = parser.StartRule() - only repeated here for reference KeyPrinter printer = new KeyPrinter(); diff --git a/doc/getting-started.md b/doc/getting-started.md index ca1fd33b1..4614c67f6 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -112,8 +112,11 @@ Now test it: ``` $ grun Hello r -tree +(Now enter something like the string below) hello parrt +(now,do:) ^D +(The output:) (r hello parrt) (That ^D means EOF on unix; it's ^Z in Windows.) The -tree option prints the parse tree in LISP notation. It's nicer to look at parse trees visually. diff --git a/doc/javascript-target.md b/doc/javascript-target.md index 2d9973be6..845fcba59 100644 --- a/doc/javascript-target.md +++ b/doc/javascript-target.md @@ -117,6 +117,44 @@ This program will work. But it won't be useful unless you do one of the followin (please note that production code is target specific, so you can't have multi target grammars that include production code) +## How do I create and run a visitor? +```javascript +// test.js +var antlr4 = require('antlr4'); +var MyGrammarLexer = require('./QueryLexer').QueryLexer; +var MyGrammarParser = require('./QueryParser').QueryParser; +var MyGrammarListener = require('./QueryListener').QueryListener; + + +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); +parser.buildParseTrees = true; +var tree = parser.query(); + +class Visitor { + visitChildren(ctx) { + if (!ctx) { + return; + } + + if (ctx.children) { + return ctx.children.map(child => { + if (child.children && child.children.length != 0) { + return child.accept(this); + } else { + return child.getText(); + } + }); + } + } +} + +tree.accept(new Visitor()); +```` + ## How do I create and run a custom listener? Let's suppose your MyGrammar grammar comprises 2 rules: "key" and "value". The antlr4 tool will have generated the following listener: diff --git a/doc/php-target.md b/doc/php-target.md new file mode 100644 index 000000000..75eae465c --- /dev/null +++ b/doc/php-target.md @@ -0,0 +1,111 @@ +# ANTLR4 Runtime for PHP + +### 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 PHP 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 Composer: + +```bash +composer install antlr/antlr4 +``` + +#### 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 PHP parser, run the following command: + +```bash +antlr4 -Dlanguage=PHP 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=PHP JSON.g4`. The result of this is a +collection of `.php` files in the `parser` directory including: +``` +JsonParser.php +JsonBaseListener.php +JsonLexer.php +JsonListener.php +``` + +Another common option to the ANTLR tool is `-visitor`, which generates a parse +tree visitor, but we won't be doing that here. For a full list of antlr4 tool +options, please visit the [tool documentation page](tool-options.md). + +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: + +```php +getText(); + } +} + +$input = InputStream::fromPath($argv[1]); +$lexer = new JSONLexer($input); +$tokens = new CommonTokenStream($lexer); +$parser = new JSONParser($tokens); +$parser->addErrorListener(new DiagnosticErrorListener()); +$parser->setBuildParseTree(true); +$tree = $parser->json(); + +ParseTreeWalker::default()->walk(new TreeShapeListener(), $tree); +``` + +Create a `example.json` file: +```json +{"a":1} +``` + +Parse the input file: + +``` +php json.php example.json +``` + +The expected output is: + +``` +{"a":1} +{"a":1} +"a":1 +1 +``` \ No newline at end of file diff --git a/doc/python-target.md b/doc/python-target.md index e3bd883f2..7ed73c281 100644 --- a/doc/python-target.md +++ b/doc/python-target.md @@ -50,8 +50,8 @@ from MyGrammarLexer import MyGrammarLexer from MyGrammarParser import MyGrammarParser def main(argv): - input = FileStream(argv[1]) - lexer = MyGrammarLexer(input) + input_stream = FileStream(argv[1]) + lexer = MyGrammarLexer(input_stream) stream = CommonTokenStream(lexer) parser = MyGrammarParser(stream) tree = parser.startRule() diff --git a/doc/resources/CaseChangingStream.js b/doc/resources/CaseChangingStream.js new file mode 100644 index 000000000..3af1ad612 --- /dev/null +++ b/doc/resources/CaseChangingStream.js @@ -0,0 +1,65 @@ +// +/* 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. + */ +// + +function CaseChangingStream(stream, upper) { + this._stream = stream; + this._upper = upper; +} + +CaseChangingStream.prototype.LA = function(offset) { + var c = this._stream.LA(offset); + if (c <= 0) { + return c; + } + return String.fromCodePoint(c)[this._upper ? "toUpperCase" : "toLowerCase"]().codePointAt(0); +}; + +CaseChangingStream.prototype.reset = function() { + return this._stream.reset(); +}; + +CaseChangingStream.prototype.consume = function() { + return this._stream.consume(); +}; + +CaseChangingStream.prototype.LT = function(offset) { + return this._stream.LT(offset); +}; + +CaseChangingStream.prototype.mark = function() { + return this._stream.mark(); +}; + +CaseChangingStream.prototype.release = function(marker) { + return this._stream.release(marker); +}; + +CaseChangingStream.prototype.seek = function(_index) { + return this._stream.seek(_index); +}; + +CaseChangingStream.prototype.getText = function(start, stop) { + return this._stream.getText(start, stop); +}; + +CaseChangingStream.prototype.toString = function() { + return this._stream.toString(); +}; + +Object.defineProperty(CaseChangingStream.prototype, "index", { + get: function() { + return this._stream.index; + } +}); + +Object.defineProperty(CaseChangingStream.prototype, "size", { + get: function() { + return this._stream.size; + } +}); + +exports.CaseChangingStream = CaseChangingStream; diff --git a/doc/resources/CaseChangingStream.py b/doc/resources/CaseChangingStream.py new file mode 100644 index 000000000..6d2815de4 --- /dev/null +++ b/doc/resources/CaseChangingStream.py @@ -0,0 +1,13 @@ +class CaseChangingStream(): + def __init__(self, stream, upper): + self._stream = stream + self._upper = upper + + def __getattr__(self, name): + return self._stream.__getattribute__(name) + + def LA(self, offset): + c = self._stream.LA(offset) + if c <= 0: + return c + return ord(chr(c).upper() if self._upper else chr(c).lower()) diff --git a/doc/resources/CaseInsensitiveInputStream.js b/doc/resources/CaseInsensitiveInputStream.js deleted file mode 100644 index 5ec762de9..000000000 --- a/doc/resources/CaseInsensitiveInputStream.js +++ /dev/null @@ -1,54 +0,0 @@ -// -/* 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. - */ -// - -function CaseInsensitiveInputStream(stream, upper) { - this._stream = stream; - this._case = upper ? String.toUpperCase : String.toLowerCase; - return this; -} - -CaseInsensitiveInputStream.prototype.LA = function (offset) { - c = this._stream.LA(i); - if (c <= 0) { - return c; - } - return this._case.call(String.fromCodePoint(c)) -}; - -CaseInsensitiveInputStream.prototype.reset = function() { - return this._stream.reset(); -}; - -CaseInsensitiveInputStream.prototype.consume = function() { - return this._stream.consume(); -}; - -CaseInsensitiveInputStream.prototype.LT = function(offset) { - return this._stream.LT(offset); -}; - -CaseInsensitiveInputStream.prototype.mark = function() { - return this._stream.mark(); -}; - -CaseInsensitiveInputStream.prototype.release = function(marker) { - return this._stream.release(marker); -}; - -CaseInsensitiveInputStream.prototype.seek = function(_index) { - return this._stream.getText(start, stop); -}; - -CaseInsensitiveInputStream.prototype.getText = function(start, stop) { - return this._stream.getText(start, stop); -}; - -CaseInsensitiveInputStream.prototype.toString = function() { - return this._stream.toString(); -}; - -exports.CaseInsensitiveInputStream = CaseInsensitiveInputStream; diff --git a/doc/resources/case_changing_stream.go b/doc/resources/case_changing_stream.go index 2963acf89..5b510fa32 100644 --- a/doc/resources/case_changing_stream.go +++ b/doc/resources/case_changing_stream.go @@ -1,13 +1,15 @@ -package antlr +package antlr_resource import ( "unicode" + + "github.com/antlr/antlr4/runtime/Go/antlr" ) // CaseChangingStream wraps an existing CharStream, but upper cases, or // lower cases the input before it is tokenized. type CaseChangingStream struct { - CharStream + antlr.CharStream upper bool } @@ -15,10 +17,8 @@ type CaseChangingStream struct { // NewCaseChangingStream returns a new CaseChangingStream that forces // all tokens read from the underlying stream to be either upper case // or lower case based on the upper argument. -func NewCaseChangingStream(in CharStream, upper bool) *CaseChangingStream { - return &CaseChangingStream{ - in, upper, - } +func NewCaseChangingStream(in antlr.CharStream, upper bool) *CaseChangingStream { + return &CaseChangingStream{in, upper} } // LA gets the value of the symbol at offset from the current position diff --git a/doc/targets.md b/doc/targets.md index 418630bb1..c2341ec48 100644 --- a/doc/targets.md +++ b/doc/targets.md @@ -9,12 +9,13 @@ This page lists the available and upcoming ANTLR runtimes. Please note that you * [Go](go-target.md) * [C++](cpp-target.md) * [Swift](swift-target.md) +* [PHP](php-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♯|Python2|Python3|JavaScript|Go|C++|Swift| -|---|---|---|---|---|---|---|---|---| -|Ambiguous tree construction|4.5.1|-|-|-|-|-|-|-| +|Feature|Java|C♯|Python2|Python3|JavaScript|Go|C++|Swift|PHP +|---|---|---|---|---|---|---|---|---|---| +|Ambiguous tree construction|4.5.1|-|-|-|-|-|-|-|-| diff --git a/runtime-testsuite/pom.xml b/runtime-testsuite/pom.xml index 6cc9b2ef9..b9e6bd936 100644 --- a/runtime-testsuite/pom.xml +++ b/runtime-testsuite/pom.xml @@ -68,7 +68,8 @@ org.eclipse.jetty jetty-server - [9.3.24.v20180605,) + + 9.4.19.v20190610 test @@ -108,14 +109,15 @@ -Dfile.encoding=UTF-8 - **/csharp/Test*.java - **/java/Test*.java - **/go/Test*.java - **/javascript/node/Test*.java - **/python2/Test*.java - **/python3/Test*.java - ${antlr.tests.swift} - + **/csharp/Test*.java + **/java/Test*.java + **/go/Test*.java + **/javascript/node/Test*.java + **/python2/Test*.java + **/python3/Test*.java + **/php/Test*.java + ${antlr.tests.swift} + diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/CSharp.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/CSharp.test.stg index 597248f2b..fb95440ce 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/CSharp.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/CSharp.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "(())" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "Object = ;" @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%int = ;%> InitBooleanMember(n,v) ::= <%bool = ;%> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "int " + +VarRef(n) ::= "" + GetMember(n) ::= <%this.%> SetMember(n,v) ::= <%this. = ;%> @@ -94,6 +102,8 @@ bool Property() { ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Firefox.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Firefox.test.stg index c94be90e8..c8a6c1d57 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Firefox.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Firefox.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "var = ;" @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%this. = ;%> InitBooleanMember(n,v) ::= <%this. = ;%> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "" + +VarRef(n) ::= "" + GetMember(n) ::= <%this.%> SetMember(n,v) ::= <%this. = ;%> @@ -100,6 +108,8 @@ this.Property = function() { ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg index 37fe63441..b2909f4e1 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "()" Append(a,b) ::= " + fmt.Sprint()" +AppendStr(a,b) ::= " + " + Concat(a,b) ::= "" DeclareLocal(s, v) ::= "var = " @@ -26,6 +28,12 @@ InitIntMember(n, v) ::= <%var int = ; var _ int = ; %> InitBooleanMember(n, v) ::= <%var bool = ; var _ bool = ; %> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "int " + +VarRef(n) ::= "" + GetMember(n) ::= <%%> SetMember(n, v) ::= <% = ;%> @@ -94,6 +102,8 @@ func (p *TParser) Property() bool { ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << func (p *PositionAdjustingLexer) NextToken() antlr.Token { if _, ok := p.Interpreter.(*PositionAdjustingLexerATNSimulator); !ok { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Java.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Java.test.stg index 5012aa213..11f159743 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Java.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Java.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "(())" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "Object = ;" @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%int = ;%> InitBooleanMember(n,v) ::= <%boolean = ;%> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "int " + +VarRef(n) ::= "" + GetMember(n) ::= <%this.%> SetMember(n,v) ::= <%this. = ;%> @@ -94,6 +102,8 @@ boolean Property() { ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << @Override diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Node.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Node.test.stg index 92cb1dbbb..81573d6c0 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Node.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Node.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "var = ;" @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%this. = ;%> InitBooleanMember(n,v) ::= <%this. = ;%> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "" + +VarRef(n) ::= "" + GetMember(n) ::= <%this.%> SetMember(n,v) ::= <%this. = ;%> @@ -98,6 +106,8 @@ this.Property = function() { ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/PHP.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/PHP.test.stg new file mode 100644 index 000000000..a2ea87466 --- /dev/null +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/PHP.test.stg @@ -0,0 +1,272 @@ +writeln(s) ::= < . \PHP_EOL;>> +write(s) ::= <;>> +writeList(s) ::= <;>> + +False() ::= "false" +True() ::= "true" +Not(v) ::= "!" +Assert(s) ::= <);>> +Cast(t,v) ::= "" +Append(a,b) ::= " . " +AppendStr(a,b) ::= <%%> +Concat(a,b) ::= "" + +DeclareLocal(s,v) ::= " = ;" + +AssertIsList(v) ::= "assert(\is_array());" // just use static type system +AssignLocal(s,v) ::= " = ;" + +InitIntMember(n,v) ::= <%public \$ = ;%> +InitBooleanMember(n,v) ::= <%public \$ = ;%> +InitIntVar(n,v) ::= <%\$ = ;%> +IntArg(n) ::= "int " +VarRef(n) ::= "$" + +GetMember(n) ::= <%\$this->%> +SetMember(n,v) ::= <%\$this-> = ;%> +AddMember(n,v) ::= <%\$this-> += ;%> +PlusMember(v,n) ::= <% + \$this->%> +MemberEquals(n,v) ::= <%\$this-> == %> +ModMemberEquals(n,m,v) ::= <%\$this-> % == %> +ModMemberNotEquals(n,m,v) ::= <%\$this-> % !== %> + +DumpDFA() ::= "\$this->dumpDFA();" +Pass() ::= "" + +StringList() ::= "" +BuildParseTrees() ::= "\$this->setBuildParseTree(true);" +BailErrorStrategy() ::= <%\$this->setErrorHandler(new Antlr\\Antlr4\\Runtime\\Error\\BailErrorStrategy());%> + +ToStringTree(s) ::= <%->toStringTree(\$this->getRuleNames())%> +Column() ::= "\$this->getCharPositionInLine()" +Text() ::= "\$this->getText()" +ValEquals(a,b) ::= <%===%> +TextEquals(a) ::= <%\$this->getText() === ""%> +PlusText(a) ::= <%"" . \$this->getText()%> +InputText() ::= "\$this->input->getText()" +LTEquals(i, v) ::= <%\$this->input->LT()->getText() === %> +LANotEquals(i, v) ::= <%\$this->input->LA() !== %> +TokenStartColumnEquals(i) ::= <%\$this->tokenStartCharPositionInLine === %> + +ImportListener(X) ::= "" + +GetExpectedTokenNames() ::= "\$this->getExpectedTokens()->toStringVocabulary(\$this->getVocabulary())" + +RuleInvocationStack() ::= "'[' . \implode(', ', \$this->getRuleInvocationStack()) . ']'" + +LL_EXACT_AMBIG_DETECTION() ::= <<\$this->interp->setPredictionMode(Antlr\\Antlr4\\Runtime\\Atn\\PredictionMode::LL_EXACT_AMBIG_DETECTION);>> + + +ParserToken(parser, token) ::= <%::%> + +Production(p) ::= <%

%> + +Result(r) ::= <%%> + +ParserPropertyMember() ::= << +@members { +public function Property() : bool +{ + return true; +} +} +>> + +ParserPropertyCall(p, call) ::= "

->" + +PositionAdjustingLexerDef() ::= << +class PositionAdjustingLexerATNSimulator extends LexerATNSimulator { + public function resetAcceptPosition(CharStream \$input, int \$index, int \$line, int \$charPositionInLine) : void { + \$input->seek(\$index); + \$this->line = \$line; + \$this->charPositionInLine = \$charPositionInLine; + \$this->consume(\$input); + } +} +>> + +PositionAdjustingLexer() ::= << +public function nextToken() : Antlr\\Antlr4\\Runtime\\Token +{ + if (!\$this->interp instanceof PositionAdjustingLexerATNSimulator) { + \$this->interp = new PositionAdjustingLexerATNSimulator(\$this, self::\$atn, self::\$decisionToDFA, self::\$sharedContextCache); + } + + return parent::nextToken(); +} + +public function emit() : Antlr\\Antlr4\\Runtime\\Token +{ + switch (\$this->type) { + case self::TOKENS: + \$this->handleAcceptPositionForKeyword('tokens'); + break; + + case self::LABEL: + \$this->handleAcceptPositionForIdentifier(); + break; + } + + return parent::emit(); +} + +private function handleAcceptPositionForIdentifier() : bool +{ + \$tokenText = \$this->getText(); + \$identifierLength = 0; + while (\$identifierLength \< \strlen(\$tokenText) && self::isIdentifierChar(\$tokenText[\$identifierLength])) { + \$identifierLength++; + } + + if (\$this->getInputStream()->getIndex() > \$this->tokenStartCharIndex + \$identifierLength) { + \$offset = \$identifierLength - 1; + \$this->getInterpreter()->resetAcceptPosition(\$this->getInputStream(), \$this->tokenStartCharIndex + \$offset, \$this->tokenStartLine, \$this->tokenStartCharPositionInLine + \$offset); + + return true; + } + + return false; +} + +private function handleAcceptPositionForKeyword(string \$keyword) : bool +{ + if (\$this->getInputStream()->getIndex() > \$this->tokenStartCharIndex + \strlen(\$keyword)) { + \$offset = \strlen(\$keyword) - 1; + \$this->getInterpreter()->resetAcceptPosition(\$this->getInputStream(), \$this->tokenStartCharIndex + \$offset, \$this->tokenStartLine, \$this->tokenStartCharPositionInLine + \$offset); + + return true; + } + + return false; +} + +private static function isIdentifierChar(string \$c) : bool +{ + return \ctype_alnum(\$c) || \$c === '_'; +} +>> + +BasicListener(X) ::= << +@parser::definitions { +class LeafListener extends TBaseListener +{ + public function visitTerminal(Antlr\\Antlr4\\Runtime\\Tree\\TerminalNode \$node) : void + { + echo \$node->getSymbol()->getText() . \PHP_EOL; + } +} +} +>> + +WalkListener(s) ::= << +\$walker = new Antlr\\Antlr4\\Runtime\\Tree\\ParseTreeWalker(); +\$walker->walk(new LeafListener(), ); +>> + +TreeNodeWithAltNumField(X) ::= << +@parser::contexts { +class MyRuleNode extends ParserRuleContext +{ + public \$altNum; + + public function getAltNumber() : int + { + return \$this->altNum; + } + + public function setAltNumber(int \$altNum) : void + { + \$this->altNum = \$altNum; + } +} +} +>> + +TokenGetterListener(X) ::= << +@parser::definitions { +class LeafListener extends TBaseListener { + public function exitA(Context\\AContext \$ctx) : void { + if (\$ctx->getChildCount() === 2) { + echo \sprintf('%s %s [%s]',\$ctx->INT(0)->getSymbol()->getText(), \$ctx->INT(1)->getSymbol()->getText(), \implode(', ', \$ctx->INT())) . \PHP_EOL; + } else { + echo \$ctx->ID()->getSymbol() . \PHP_EOL; + } + } +} +} +>> + +RuleGetterListener(X) ::= << +@parser::definitions { +class LeafListener extends TBaseListener { + public function exitA(Context\\AContext \$ctx) : void + { + if (\$ctx->getChildCount() === 2) { + echo \sprintf('%s %s %s', \$ctx->b(0)->start->getText(), \$ctx->b(1)->start->getText(),\$ctx->b()[0]->start->getText()) . \PHP_EOL; + } else { + echo \$ctx->b(0)->start->getText() . \PHP_EOL; + } + } +} +} +>> + + +LRListener(X) ::= << +@parser::definitions { +class LeafListener extends TBaseListener { + public function exitE(Context\\EContext \$ctx) : void + { + if (\$ctx->getChildCount() === 3) { + echo \sprintf('%s %s %s', \$ctx->e(0)->start->getText(), \$ctx->e(1)->start->getText(), \$ctx->e()[0]->start->getText()) . \PHP_EOL; + } else { + echo \$ctx->INT()->getSymbol()->getText() . \PHP_EOL; + } + } +} +} +>> + +LRWithLabelsListener(X) ::= << +@parser::definitions { +class LeafListener extends TBaseListener +{ + public function exitCall(Context\\CallContext \$ctx) : void { + echo \sprintf('%s %s',\$ctx->e()->start->getText(),\$ctx->eList()) . \PHP_EOL; + } + + public function exitInt(Context\\IntContext \$ctx) : void { + echo \$ctx->INT()->getSymbol()->getText() . \PHP_EOL; + } +} +} +>> + +DeclareContextListGettersFunction() ::= << +public function foo() : void { + \$s = null; + \$a = \$s->a(); + \$b = \$s->b(); +} +>> + +Declare_foo() ::= << +public function foo() : void { + echo 'foo' . \PHP_EOL; +} +>> + +Invoke_foo() ::= "\$this->foo();" + +Declare_pred() ::= <pred()" + +ParserTokenType(t) ::= "Parser::" +ContextRuleFunction(ctx, rule) ::= "->" +StringType() ::= "" +ContextMember(ctx, subctx, member) ::= "->->" diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python2.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python2.test.stg index cc0d9d9c2..3102f4120 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python2.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python2.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "" Append(a,b) ::= " + str()" +AppendStr(a,b) ::= " + " + Concat(a,b) ::= "" DeclareLocal(s,v) ::= " = " @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <% = %> InitBooleanMember(n,v) ::= <% = %> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "" + +VarRef(n) ::= "" + GetMember(n) ::= <%self.%> SetMember(n,v) ::= <%self. = %> @@ -94,6 +102,8 @@ def Property(self): ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << def resetAcceptPosition(self, index, line, column): diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python3.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python3.test.stg index c91563017..858b76113 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python3.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Python3.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "" Append(a,b) ::= " + str()" +AppendStr(a,b) ::= " + " + Concat(a,b) ::= "" DeclareLocal(s,v) ::= " = " @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <% = %> InitBooleanMember(n,v) ::= <% = %> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "" + +VarRef(n) ::= "" + GetMember(n) ::= <%self.%> SetMember(n,v) ::= <%self. = %> @@ -99,6 +107,8 @@ def Property(self): ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << def resetAcceptPosition(self, index, line, column): diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Safari.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Safari.test.stg index 71254e0f2..2a09970c2 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Safari.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Safari.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "var = ;" @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%this. = ;%> InitBooleanMember(n,v) ::= <%this. = ;%> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "" + +VarRef(n) ::= "" + GetMember(n) ::= <%this.%> SetMember(n,v) ::= <%this. = ;%> @@ -98,6 +106,8 @@ this.Property = function() { ParserPropertyCall(p, call) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg index 100d6f3e7..d45168517 100755 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Swift.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "(( as! ))" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "var = " @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%var = %> InitBooleanMember(n,v) ::= <%var = %> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "int " + +VarRef(n) ::= "" + GetMember(n) ::= <%self.%> SetMember(n,v) ::= <%self. = %> @@ -96,6 +104,8 @@ ParserPropertyCall(parser, property) ::= << . >> +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << override diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/BaseRuntimeTest.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/BaseRuntimeTest.java index 71cd1e34d..f7874d671 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/BaseRuntimeTest.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/BaseRuntimeTest.java @@ -50,6 +50,7 @@ public abstract class BaseRuntimeTest { "Go", "CSharp", "Python2", "Python3", + "PHP", "Node", "Safari", "Firefox", "Explorer", "Chrome" }; public final static String[] JavaScriptTargets = { @@ -116,6 +117,7 @@ public abstract class BaseRuntimeTest { System.out.printf("Ignore "+descriptor); return; } + if ( descriptor.getTestType().contains("Parser") ) { testParser(descriptor); } diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/CompositeParsersDescriptors.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/CompositeParsersDescriptors.java index 435dcc977..6134b265b 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/CompositeParsersDescriptors.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/CompositeParsersDescriptors.java @@ -418,7 +418,7 @@ public class CompositeParsersDescriptors { parser grammar S; type_ : 'int' ; decl : type_ ID ';' - | type_ ID init_ ';' {}; + | type_ ID init_ ';' {}; init_ : '=' INT; */ @CommentHasStringValue @@ -532,7 +532,7 @@ public class CompositeParsersDescriptors { /** parser grammar S; - a @after {} : B; + a @after {} : B; */ @CommentHasStringValue public String slaveGrammarS; diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/FullContextParsingDescriptors.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/FullContextParsingDescriptors.java index 942d07be5..fb71b3863 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/FullContextParsingDescriptors.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/FullContextParsingDescriptors.java @@ -372,7 +372,7 @@ public class FullContextParsingDescriptors { : expr_or_assign*; expr_or_assign : expr '++' {} - | expr {} + | expr {} ; expr: expr_primary ('\<-' ID)?; expr_primary diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LeftRecursionDescriptors.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LeftRecursionDescriptors.java index 66dd5760d..01e868d6e 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LeftRecursionDescriptors.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LeftRecursionDescriptors.java @@ -529,8 +529,8 @@ public class LeftRecursionDescriptors { | e '+' e {$v = (0)}, {})> + (1)}, {})>;} # binary | INT {$v = $INT.int;} # anInt | '(' e ')' {$v = $e.v;} # parens - | left=e INC {$v = $left.v + 1;} # unary - | left=e DEC {$v = $left.v - 1;} # unary + | left=e INC {$v = $left.v + 1;} # unary + | left=e DEC {$v = $left.v - 1;} # unary | ID {} # anID ; ID : 'a'..'z'+ ; @@ -636,9 +636,9 @@ public class LeftRecursionDescriptors { grammar T; s : e {} ; e returns [ result] - : ID '=' e1=e {$result = "(" + $ID.text + "=" + $e1.result + ")";} + : ID '=' e1=e {$result = ;} | ID {$result = $ID.text;} - | e1=e '+' e2=e {$result = "(" + $e1.result + "+" + $e2.result + ")";} + | e1=e '+' e2=e {$result = ;} ; ID : 'a'..'z'+ ; INT : '0'..'9'+ ; diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LexerExecDescriptors.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LexerExecDescriptors.java index 60cb86cb4..7c74e74cb 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LexerExecDescriptors.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/LexerExecDescriptors.java @@ -766,6 +766,10 @@ public class LexerExecDescriptors { /** lexer grammar PositionAdjustingLexer; + @definitions { + + } + @members { } diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/SemPredEvalParserDescriptors.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/SemPredEvalParserDescriptors.java index ed4f9a384..b09f07488 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/SemPredEvalParserDescriptors.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/descriptors/SemPredEvalParserDescriptors.java @@ -144,8 +144,8 @@ public class SemPredEvalParserDescriptors { /** grammar T; s : b[2] ';' | b[2] '.' ; // decision in s drills down to ctx-dependent pred in a; - b[int i] : a[i] ; - a[int i] + b[] : a[] ; + a[] : {}? ID {} | {}? ID {} ; @@ -310,7 +310,7 @@ public class SemPredEvalParserDescriptors { grammar T; @parser::members {} primary - : ID {} + : ID {} | {}? 'enum' {} ; ID : [a-z]+ ; diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/BasePHPTest.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/BasePHPTest.java new file mode 100644 index 000000000..8f2cc5bcc --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/BasePHPTest.java @@ -0,0 +1,599 @@ +/* + * 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.php; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.antlr.v4.Tool; +import org.antlr.v4.automata.LexerATNFactory; +import org.antlr.v4.automata.ParserATNFactory; +import org.antlr.v4.runtime.atn.ATN; +import org.antlr.v4.runtime.atn.ATNDeserializer; +import org.antlr.v4.runtime.atn.ATNSerializer; +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.tool.Grammar; +import org.antlr.v4.tool.LexerGrammar; +import org.stringtemplate.v4.ST; + +import static org.antlr.v4.test.runtime.BaseRuntimeTest.antlrOnString; +import static org.antlr.v4.test.runtime.BaseRuntimeTest.writeFile; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class BasePHPTest implements RuntimeTestSupport { + public static final String newline = System.getProperty("line.separator"); + + public String tmpdir = null; + + /** + * If error during parser execution, store stderr here; can't return + * stdout and stderr. This doesn't trap errors from running antlr. + */ + protected String stderrDuringParse; + + /** + * Errors found while running antlr + */ + protected StringBuilder antlrToolErrors; + + private String getPropertyPrefix() { + return "antlr-php"; + } + + @Override + public void testSetUp() throws Exception { + // new output dir for each test + String propName = getPropertyPrefix() + "-test-dir"; + String prop = System.getProperty(propName); + + if (prop != null && prop.length() > 0) { + tmpdir = prop; + } else { + String classSimpleName = getClass().getSimpleName(); + String threadName = Thread.currentThread().getName(); + String childPath = String.format("%s-%s-%s", classSimpleName, threadName, System.currentTimeMillis()); + tmpdir = new File(System.getProperty("java.io.tmpdir"), childPath).getAbsolutePath(); + } + + antlrToolErrors = new StringBuilder(); + } + + @Override + public void testTearDown() throws Exception { + } + + @Override + public String getTmpDir() { + return tmpdir; + } + + @Override + public String getStdout() { + return null; + } + + @Override + public String getParseErrors() { + return stderrDuringParse; + } + + @Override + public String getANTLRToolErrors() { + if (antlrToolErrors.length() == 0) { + return null; + } + + return antlrToolErrors.toString(); + } + + protected ATN createATN(Grammar g, boolean useSerializer) { + if (g.atn == null) { + semanticProcess(g); + + assertEquals(0, g.tool.getNumErrors()); + + ParserATNFactory f; + + if (g.isLexer()) { + f = new LexerATNFactory((LexerGrammar) g); + } else { + f = new ParserATNFactory(g); + } + + g.atn = f.createATN(); + assertEquals(0, g.tool.getNumErrors()); + } + + ATN atn = g.atn; + + if (useSerializer) { + char[] serialized = ATNSerializer.getSerializedAsChars(atn); + + return new ATNDeserializer().deserialize(serialized); + } + + return atn; + } + + protected void semanticProcess(Grammar g) { + if (g.ast != null && !g.ast.hasErrors) { + Tool antlr = new Tool(); + SemanticPipeline sem = new SemanticPipeline(g); + sem.process(); + + if (g.getImportedGrammars() != null) { + for (Grammar imp: g.getImportedGrammars()) { + antlr.processNonCombinedGrammar(imp, false); + } + } + } + } + + protected String execLexer( + String grammarFileName, + String grammarStr, + String lexerName, + String input + ) { + return execLexer(grammarFileName, grammarStr, lexerName, input, false); + } + + @Override + public String execLexer( + String grammarFileName, + String grammarStr, + String lexerName, + String input, + boolean showDFA + ) { + boolean success = rawGenerateAndBuildRecognizer( + grammarFileName, + grammarStr, + null, + lexerName, + "-no-listener" + ); + assertTrue(success); + writeFile(tmpdir, "input", input); + writeLexerTestFile(lexerName, showDFA); + String output = execModule("Test.php"); + + return output; + } + + public String execParser( + String grammarFileName, + String grammarStr, + String parserName, + String lexerName, + String listenerName, + String visitorName, + String startRuleName, + String input, + boolean showDiagnosticErrors + ) { + return execParser_( + grammarFileName, + grammarStr, + parserName, + lexerName, + listenerName, + visitorName, + startRuleName, + input, + showDiagnosticErrors, + false + ); + } + + public String execParser_( + String grammarFileName, + String grammarStr, + String parserName, + String lexerName, + String listenerName, + String visitorName, + String startRuleName, + String input, + boolean debug, + boolean trace + ) { + boolean success = rawGenerateAndBuildRecognizer( + grammarFileName, + grammarStr, + parserName, + lexerName, + "-visitor" + ); + + assertTrue(success); + + writeFile(tmpdir, "input", input); + + rawBuildRecognizerTestFile( + parserName, + lexerName, + listenerName, + visitorName, + startRuleName, + debug, + trace + ); + + return execRecognizer(); + } + + /** + * Return true if all is well + */ + protected boolean rawGenerateAndBuildRecognizer( + String grammarFileName, + String grammarStr, + String parserName, + String lexerName, + String... extraOptions + ) { + return rawGenerateAndBuildRecognizer( + grammarFileName, + grammarStr, + parserName, + lexerName, + false, + extraOptions + ); + } + + /** + * Return true if all is well + */ + protected boolean rawGenerateAndBuildRecognizer( + String grammarFileName, + String grammarStr, + String parserName, + String lexerName, + boolean defaultListener, + String... extraOptions + ) { + ErrorQueue equeue = antlrOnString(getTmpDir(), "PHP", grammarFileName, grammarStr, defaultListener, extraOptions); + + if (!equeue.errors.isEmpty()) { + return false; + } + + List files = new ArrayList(); + + if (lexerName != null) { + files.add(lexerName + ".php"); + } + + if (parserName != null) { + files.add(parserName + ".php"); + Set optionsSet = new HashSet(Arrays.asList(extraOptions)); + + if (!optionsSet.contains("-no-listener")) { + files.add(grammarFileName.substring(0, grammarFileName.lastIndexOf('.')) + "Listener.php"); + } + + if (optionsSet.contains("-visitor")) { + files.add(grammarFileName.substring(0, grammarFileName.lastIndexOf('.')) + "Visitor.php"); + } + } + + return true; + } + + protected void rawBuildRecognizerTestFile( + String parserName, + String lexerName, + String listenerName, + String visitorName, + String parserStartRuleName, + boolean debug, + boolean trace + ) { + this.stderrDuringParse = null; + if (parserName == null) { + writeLexerTestFile(lexerName, false); + } else { + writeParserTestFile( + parserName, + lexerName, + listenerName, + visitorName, + parserStartRuleName, + debug, + trace + ); + } + } + + public String execRecognizer() { + return execModule("Test.php"); + } + + public String execModule(String fileName) { + String phpPath = locatePhp(); + String runtimePath = locateRuntime(); + + File tmpdirFile = new File(tmpdir); + String modulePath = new File(tmpdirFile, fileName).getAbsolutePath(); + String inputPath = new File(tmpdirFile, "input").getAbsolutePath(); + Path outputPath = tmpdirFile.toPath().resolve("output").toAbsolutePath(); + + try { + ProcessBuilder builder = new ProcessBuilder(phpPath, modulePath, inputPath, outputPath.toString()); + builder.environment().put("RUNTIME", runtimePath); + builder.directory(tmpdirFile); + Process process = builder.start(); + StreamVacuum stdoutVacuum = new StreamVacuum(process.getInputStream()); + StreamVacuum stderrVacuum = new StreamVacuum(process.getErrorStream()); + stdoutVacuum.start(); + stderrVacuum.start(); + process.waitFor(); + stdoutVacuum.join(); + stderrVacuum.join(); + String output = stdoutVacuum.toString(); + + if (output.length() == 0) { + output = null; + } + + if (stderrVacuum.toString().length() > 0) { + this.stderrDuringParse = stderrVacuum.toString(); + } + + return output; + } catch (Exception e) { + System.err.println("can't exec recognizer"); + e.printStackTrace(System.err); + } + return null; + } + + private String locateTool(String tool) { + final String phpPath = System.getProperty("PHP_PATH"); + + if (phpPath != null && new File(phpPath).exists()) { + return phpPath; + } + + String[] roots = {"/usr/local/bin/", "/opt/local/bin", "/usr/bin/"}; + + for (String root: roots) { + if (new File(root + tool).exists()) { + return root + tool; + } + } + + throw new RuntimeException("Could not locate " + tool); + } + + protected String locatePhp() { + String propName = getPropertyPrefix() + "-php"; + String prop = System.getProperty(propName); + + if (prop == null || prop.length() == 0) { + prop = locateTool("php"); + } + + File file = new File(prop); + + if (!file.exists()) { + throw new RuntimeException("Missing system property:" + propName); + } + + return file.getAbsolutePath(); + } + + protected String locateRuntime() { + String propName = "antlr-php-runtime"; + String prop = System.getProperty(propName); + + if (prop == null || prop.length() == 0) { + prop = "../runtime/PHP"; + } + + File file = new File(prop); + + if (!file.exists()) { + throw new RuntimeException("Missing system property:" + propName); + } + + try { + return file.getCanonicalPath(); + } catch (IOException e) { + return file.getAbsolutePath(); + } + } + + protected void mkdir(String dir) { + File f = new File(dir); + f.mkdirs(); + } + + protected void writeLexerTestFile(String lexerName, boolean showDFA) { + ST outputFileST = new ST( + "\\($input);\n" + + "$lexer->addErrorListener(new ConsoleErrorListener());" + + "$tokens = new CommonTokenStream($lexer);\n" + + "$tokens->fill();\n" + + "\n" + + "foreach ($tokens->getAllTokens() as $token) {\n" + + " echo $token . \\PHP_EOL;\n" + + "}" + + (showDFA + ? "echo $lexer->getInterpreter()->getDFA(Lexer::DEFAULT_MODE)->toLexerString();\n" + : "") + ); + + outputFileST.add("lexerName", lexerName); + + writeFile(tmpdir, "Test.php", outputFileST.render()); + } + + protected void writeParserTestFile( + String parserName, String lexerName, + String listenerName, String visitorName, + String parserStartRuleName, boolean debug, boolean trace + ) { + if (!parserStartRuleName.endsWith(")")) { + parserStartRuleName += "()"; + } + ST outputFileST = new ST( + "\\getChildCount(); $i \\< $count; $i++) {\n" + + " $parent = $ctx->getChild($i)->getParent();\n" + + "\n" + + " if (!($parent instanceof RuleNode) || $parent->getRuleContext() !== $ctx) {\n" + + " throw new RuntimeException('Invalid parse tree shape detected.');\n" + + " }\n" + + " }\n" + + " }\n" + + "}" + + "\n" + + "$input = InputStream::fromPath($argv[1]);\n" + + "$lexer = new ($input);\n" + + "$lexer->addErrorListener(new ConsoleErrorListener());" + + "$tokens = new CommonTokenStream($lexer);\n" + + "" + + "$parser->addErrorListener(new ConsoleErrorListener());" + + "$parser->setBuildParseTree(true);\n" + + "$tree = $parser->;\n\n" + + "ParseTreeWalker::default()->walk(new TreeShapeListener(), $tree);\n" + ); + + String stSource = "$parser = new ($tokens);\n"; + + if (debug) { + stSource += "$parser->addErrorListener(new DiagnosticErrorListener());\n"; + } + + if (trace) { + stSource += "$parser->setTrace(true);\n"; + } + + ST createParserST = new ST(stSource); + outputFileST.add("createParser", createParserST); + outputFileST.add("parserName", parserName); + outputFileST.add("lexerName", lexerName); + outputFileST.add("listenerName", listenerName); + outputFileST.add("visitorName", visitorName); + outputFileST.add("parserStartRuleName", parserStartRuleName); + + writeFile(tmpdir, "Test.php", outputFileST.render()); + } + + protected void eraseFiles(File dir) { + String[] files = dir.list(); + for (int i = 0; files != null && i < files.length; i++) { + new File(dir, files[i]).delete(); + } + } + + @Override + public void eraseTempDir() { + boolean doErase = true; + String propName = getPropertyPrefix() + "-erase-test-dir"; + String prop = System.getProperty(propName); + if (prop != null && prop.length() > 0) { + doErase = Boolean.getBoolean(prop); + } + if (doErase) { + File tmpdirF = new File(tmpdir); + if (tmpdirF.exists()) { + eraseFiles(tmpdirF); + tmpdirF.delete(); + } + } + } + + /** + * Sort a list + */ + public > List sort(List data) { + List dup = new ArrayList(); + dup.addAll(data); + Collections.sort(dup); + return dup; + } + + /** + * Return map sorted by key + */ + public , V> LinkedHashMap sort(Map data) { + LinkedHashMap dup = new LinkedHashMap(); + List keys = new ArrayList(); + keys.addAll(data.keySet()); + Collections.sort(keys); + for (K k: keys) { + dup.put(k, data.get(k)); + } + return dup; + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestCompositeLexers.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestCompositeLexers.java new file mode 100644 index 000000000..d1d353875 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestCompositeLexers.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.CompositeLexersDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(CompositeLexersDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestCompositeParsers.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestCompositeParsers.java new file mode 100644 index 000000000..dd5b0015a --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestCompositeParsers.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.CompositeParsersDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(CompositeParsersDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestFullContextParsing.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestFullContextParsing.java new file mode 100644 index 000000000..60efc0718 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestFullContextParsing.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.FullContextParsingDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(FullContextParsingDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLeftRecursion.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLeftRecursion.java new file mode 100644 index 000000000..cb200ef38 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLeftRecursion.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.LeftRecursionDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(LeftRecursionDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLexerErrors.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLexerErrors.java new file mode 100644 index 000000000..cd7a5c596 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLexerErrors.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.LexerErrorsDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(LexerErrorsDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLexerExec.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLexerExec.java new file mode 100644 index 000000000..03595f564 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestLexerExec.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.LexerExecDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(LexerExecDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestListeners.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestListeners.java new file mode 100644 index 000000000..52260158d --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestListeners.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.ListenersDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(ListenersDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParseTrees.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParseTrees.java new file mode 100644 index 000000000..656e14d71 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParseTrees.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.ParseTreesDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(ParseTreesDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParserErrors.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParserErrors.java new file mode 100644 index 000000000..ac3ab88ef --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParserErrors.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.ParserErrorsDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(ParserErrorsDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParserExec.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParserExec.java new file mode 100644 index 000000000..01e3f321c --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestParserExec.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.ParserExecDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(ParserExecDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestPerformance.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestPerformance.java new file mode 100644 index 000000000..7459d77d8 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestPerformance.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.PerformanceDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(PerformanceDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSemPredEvalLexer.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSemPredEvalLexer.java new file mode 100644 index 000000000..ec7f14efc --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSemPredEvalLexer.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.SemPredEvalLexerDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(SemPredEvalLexerDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSemPredEvalParser.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSemPredEvalParser.java new file mode 100644 index 000000000..1441444c5 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSemPredEvalParser.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.SemPredEvalParserDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(SemPredEvalParserDescriptors.class, "PHP"); + } +} diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSets.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSets.java new file mode 100644 index 000000000..996045361 --- /dev/null +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/php/TestSets.java @@ -0,0 +1,25 @@ +/* + * 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.php; + +import org.antlr.v4.test.runtime.BaseRuntimeTest; +import org.antlr.v4.test.runtime.RuntimeTestDescriptor; +import org.antlr.v4.test.runtime.descriptors.SetsDescriptors; +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 BasePHPTest()); + } + + @Parameterized.Parameters(name="{0}") + public static RuntimeTestDescriptor[] getAllTestDescriptors() { + return BaseRuntimeTest.getRuntimeTestDescriptors(SetsDescriptors.class, "PHP"); + } +} diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/ParserInterpreter.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/ParserInterpreter.cs index ff50eafd7..e7b0c701b 100644 --- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/ParserInterpreter.cs +++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/ParserInterpreter.cs @@ -31,6 +31,8 @@ namespace Antlr4.Runtime private readonly string _grammarFileName; private readonly ATN _atn; + + private readonly Dfa.DFA[] _decisionToDFA; protected internal readonly BitSet pushRecursionContextStates; @@ -61,8 +63,17 @@ namespace Antlr4.Runtime this.pushRecursionContextStates.Set(state.stateNumber); } } - // get atn simulator that knows how to do predictions - Interpreter = new ParserATNSimulator(this, atn, null, null); + + //init decision DFA + int numberofDecisions = atn.NumberOfDecisions; + this._decisionToDFA = new Dfa.DFA[numberofDecisions]; + for (int i = 0; i < numberofDecisions; i++) + { + DecisionState decisionState = atn.GetDecisionState(i); + _decisionToDFA[i] = new Dfa.DFA(decisionState, i); + } + // get atn simulator that knows how to do predictions + Interpreter = new ParserATNSimulator(this, atn, _decisionToDFA, null); } public override ATN Atn diff --git a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/TokenStreamRewriter.cs b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/TokenStreamRewriter.cs index 52e91c828..8ba429c60 100644 --- a/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/TokenStreamRewriter.cs +++ b/runtime/CSharp/runtime/CSharp/Antlr4.Runtime/TokenStreamRewriter.cs @@ -612,7 +612,6 @@ namespace Antlr4.Runtime } // throw exception unless disjoint or identical bool disjoint = prevRop.lastIndex < rop.index || prevRop.index > rop.lastIndex; - bool same = prevRop.index == rop.index && prevRop.lastIndex == rop.lastIndex; // Delete special case of replace (text==null): // D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) if (prevRop.text == null && rop.text == null && !disjoint) @@ -628,7 +627,7 @@ namespace Antlr4.Runtime } else { - if (!disjoint && !same) + if (!disjoint) { throw new ArgumentException("replace op boundaries of " + rop + " overlap with previous " + prevRop); } diff --git a/runtime/Cpp/cmake/Antlr4Package.md b/runtime/Cpp/cmake/Antlr4Package.md index ac9480db2..984564203 100644 --- a/runtime/Cpp/cmake/Antlr4Package.md +++ b/runtime/Cpp/cmake/Antlr4Package.md @@ -14,7 +14,7 @@ given input file during build. The following table lists the parameters that can be used with the function: Argument# | Required | Default | Use -----------|-----------|---------|-- +----------|-----------|---------|--- 0 | Yes | n/a | Unique target name. It is used to generate CMake Variables to reference the various outputs of the generation 1 | Yes | n/a | Input file containing the lexer/parser definition 2 | Yes | n/a | Type of Rules contained in the input: LEXER, PARSER or BOTH @@ -24,10 +24,10 @@ Argument# | Required | Default | Use 7 | No | none | Additional files on which the input depends 8 | No | none | Library path to use during generation -The `ANTLR4_JAR_LOCATION` CMake variable must be set to the location where the `antlr-4*-complete.jar` generator is located. -You can download the file from [here](http://www.antlr.org/download.html). +The `ANTLR4_JAR_LOCATION` CMake variable must be set to the location where the `antlr-4*-complete.jar` generator is located. You can download the file from [here](http://www.antlr.org/download.html). -Additional option to the ANTLR4 generator can be passed in the `ANTLR4_GENERATED_OPTIONS` variable +Additional options to the ANTLR4 generator can be passed in the `ANTLR4_GENERATED_OPTIONS` variable. Add the installation prefix of `antlr4-runtime` to `CMAKE_PREFIX_PATH` or set + `antlr4-runtime_DIR` to a directory containing the files. The following CMake variables are available following a call to `antlr4_generate` diff --git a/runtime/Cpp/demo/Mac/antlrcpp-demo.xcodeproj/project.pbxproj b/runtime/Cpp/demo/Mac/antlrcpp-demo.xcodeproj/project.pbxproj index 77ad3f4f7..5f136b03e 100644 --- a/runtime/Cpp/demo/Mac/antlrcpp-demo.xcodeproj/project.pbxproj +++ b/runtime/Cpp/demo/Mac/antlrcpp-demo.xcodeproj/project.pbxproj @@ -332,7 +332,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "pushd ..\nif [ TParser.g4 -nt generated/TParser.cpp -o TLexer.g4 -nt generated/TLexer.cpp ]; then\n./generate.sh;\nfi\npopd"; + shellScript = "pushd ..\nif [ TParser.g4 -nt generated/TParser.cpp -o TLexer.g4 -nt generated/TLexer.cpp ]; then\n./generate.sh;\nfi\npopd\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/runtime/Cpp/runtime/antlr4cpp-vs2019.vcxproj b/runtime/Cpp/runtime/antlr4cpp-vs2019.vcxproj new file mode 100644 index 000000000..b93d8f641 --- /dev/null +++ b/runtime/Cpp/runtime/antlr4cpp-vs2019.vcxproj @@ -0,0 +1,651 @@ + + + + + Debug Static + Win32 + + + Debug Static + x64 + + + Debug DLL + Win32 + + + Debug DLL + x64 + + + Release Static + Win32 + + + Release Static + x64 + + + Release DLL + Win32 + + + Release DLL + x64 + + + + {83BE66CD-9C4F-4F84-B72A-DD1855C8FC8A} + Win32Proj + antlr4cpp + 10.0 + + + + DynamicLibrary + true + Unicode + v142 + + + StaticLibrary + true + Unicode + v142 + + + DynamicLibrary + true + Unicode + v142 + + + StaticLibrary + true + Unicode + v142 + + + DynamicLibrary + false + true + Unicode + v142 + + + StaticLibrary + false + true + Unicode + v142 + + + DynamicLibrary + false + true + Unicode + v142 + + + StaticLibrary + false + true + Unicode + v142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + true + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + true + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + true + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + false + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + false + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + false + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + false + $(SolutionDir)bin\vs-2019\$(PlatformTarget)\$(Configuration)\ + $(SolutionDir)obj\$(PlatformTarget)\$(Configuration)\$(ProjectName)\ + antlr4-runtime + + + + Level4 + Disabled + ANTLR4CPP_EXPORTS;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + false + + + Windows + true + + + + + Level4 + Disabled + ANTLR4CPP_EXPORTS;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + false + + + Windows + true + + + + + Level4 + Disabled + ANTLR4CPP_EXPORTS;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + false + + + Windows + true + + + + + Level4 + Disabled + ANTLR4CPP_STATIC;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + false + + + Windows + true + + + + + Level4 + MaxSpeed + true + true + ANTLR4CPP_DLL;ANTLR4CPP_EXPORTS;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + + + Windows + true + true + true + + + + + Level4 + MaxSpeed + true + true + ANTLR4CPP_EXPORTS;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + + + Windows + true + true + true + + + + + Level4 + MaxSpeed + true + true + ANTLR4CPP_DLL;ANTLR4CPP_EXPORTS;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + + + Windows + true + true + true + + + + + Level4 + MaxSpeed + true + true + ANTLR4CPP_STATIC;%(PreprocessorDefinitions) + src;%(AdditionalIncludeDirectories) + + + + + 4251 + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/runtime/Cpp/runtime/antlr4cpp-vs2019.vcxproj.filters b/runtime/Cpp/runtime/antlr4cpp-vs2019.vcxproj.filters new file mode 100644 index 000000000..eb3b687be --- /dev/null +++ b/runtime/Cpp/runtime/antlr4cpp-vs2019.vcxproj.filters @@ -0,0 +1,987 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {587a2726-4856-4d21-937a-fbaebaa90232} + + + {2662156f-1508-4dad-b991-a8298a6db9bf} + + + {5b1e59b1-7fa5-46a5-8d92-965bd709cca0} + + + {9de9fe74-5d67-441d-a972-3cebe6dfbfcc} + + + {89fd3896-0ab1-476d-8d64-a57f10a5e73b} + + + {23939d7b-8e11-421e-80eb-b2cfdfdd64e9} + + + {05f2bacb-b5b2-4ca3-abe1-ca9a7239ecaa} + + + {d3b2ae2d-836b-4c73-8180-aca4ebb7d658} + + + {6674a0f0-c65d-4a00-a9e5-1f243b89d0a2} + + + {1893fffe-7a2b-4708-8ce5-003aa9b749f7} + + + {053a0632-27bc-4043-b5e8-760951b3b5b9} + + + {048c180d-44cf-49ca-a7aa-d0053fea07f5} + + + {3181cae5-cc15-4050-8c45-22af44a823de} + + + {290632d2-c56e-4005-a417-eb83b9531e1a} + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\dfa + + + Header Files\dfa + + + Header Files\dfa + + + Header Files\dfa + + + Header Files\misc + + + Header Files\misc + + + Header Files\misc + + + Header Files\support + + + Header Files\support + + + Header Files\support + + + Header Files\support + + + Header Files\support + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree + + + Header Files\tree\pattern + + + Header Files\tree\pattern + + + Header Files\tree\pattern + + + Header Files\tree\pattern + + + Header Files\tree\pattern + + + Header Files\tree\pattern + + + Header Files\tree\pattern + + + Header Files\tree\pattern + + + Header Files\tree\xpath + + + Header Files + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\atn + + + Header Files\misc + + + Header Files + + + Header Files + + + Header Files\support + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files\tree\xpath + + + Header Files + + + Header Files + + + Header Files\tree + + + Header Files + + + Header Files\support + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\dfa + + + Source Files\dfa + + + Source Files\dfa + + + Source Files\dfa + + + Source Files\misc + + + Source Files\misc + + + Source Files\misc + + + Source Files\support + + + Source Files\support + + + Source Files\support + + + Source Files\tree + + + Source Files\tree + + + Source Files\tree + + + Source Files\tree + + + Source Files\tree\pattern + + + Source Files\tree\pattern + + + Source Files\tree\pattern + + + Source Files\tree\pattern + + + Source Files\tree\pattern + + + Source Files\tree\pattern + + + Source Files\tree\pattern + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files\atn + + + Source Files + + + Source Files + + + Source Files\support + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files\tree\xpath + + + Source Files + + + Source Files\tree + + + Source Files\tree + + + Source Files + + + Source Files + + + Source Files + + + Source Files\atn + + + Source Files\atn + + + Source Files\misc + + + Source Files + + + Source Files + + + Source Files + + + Source Files\support + + + Source Files\tree + + + Source Files\tree + + + Source Files\tree + + + Source Files\tree + + + Source Files\tree\pattern + + + \ No newline at end of file diff --git a/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj b/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj index d6822dfdd..a256e089a 100644 --- a/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj +++ b/runtime/Cpp/runtime/antlrcpp.xcodeproj/project.pbxproj @@ -2226,7 +2226,7 @@ 37D727A21867AF1E007B6D10 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1010; + LastUpgradeCheck = 1030; ORGANIZATIONNAME = ANTLR; TargetAttributes = { 270C67EF1CDB4F1E00116E17 = { @@ -2239,10 +2239,11 @@ }; buildConfigurationList = 37D727A51867AF1E007B6D10 /* Build configuration list for PBXProject "antlrcpp" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 37D727A11867AF1E007B6D10; productRefGroup = 37D727AB1867AF1E007B6D10 /* Products */; @@ -2839,6 +2840,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; @@ -2898,6 +2900,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_OBJC_ARC = YES; diff --git a/runtime/Cpp/runtime/antlrcpp.xcodeproj/xcshareddata/xcschemes/antlr4.xcscheme b/runtime/Cpp/runtime/antlrcpp.xcodeproj/xcshareddata/xcschemes/antlr4.xcscheme index 740698b37..dc8e3432a 100644 --- a/runtime/Cpp/runtime/antlrcpp.xcodeproj/xcshareddata/xcschemes/antlr4.xcscheme +++ b/runtime/Cpp/runtime/antlrcpp.xcodeproj/xcshareddata/xcschemes/antlr4.xcscheme @@ -1,6 +1,6 @@ - - - - . ///

- /// TO_DO: what to do about lexers + /// TODO: what to do about lexers /// class ANTLR4CPP_PUBLIC ANTLRErrorStrategy { public: diff --git a/runtime/Cpp/runtime/src/Lexer.cpp b/runtime/Cpp/runtime/src/Lexer.cpp index 3abd4b862..7eb64c8ef 100755 --- a/runtime/Cpp/runtime/src/Lexer.cpp +++ b/runtime/Cpp/runtime/src/Lexer.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -273,7 +273,7 @@ std::string Lexer::getErrorDisplay(const std::string &s) { } void Lexer::recover(RecognitionException * /*re*/) { - // TO_DO: Do we lose character or line position information? + // TODO: Do we lose character or line position information? _input->consume(); } diff --git a/runtime/Cpp/runtime/src/Parser.cpp b/runtime/Cpp/runtime/src/Parser.cpp index f65da1433..9ddb262d9 100755 --- a/runtime/Cpp/runtime/src/Parser.cpp +++ b/runtime/Cpp/runtime/src/Parser.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -464,7 +464,7 @@ bool Parser::precpred(RuleContext * /*localctx*/, int precedence) { } bool Parser::inContext(const std::string &/*context*/) { - // TO_DO: useful in parser? + // TODO: useful in parser? return false; } diff --git a/runtime/Cpp/runtime/src/RuleContext.cpp b/runtime/Cpp/runtime/src/RuleContext.cpp index 73cfe24e1..467e5ec42 100755 --- a/runtime/Cpp/runtime/src/RuleContext.cpp +++ b/runtime/Cpp/runtime/src/RuleContext.cpp @@ -75,16 +75,16 @@ antlrcpp::Any RuleContext::accept(tree::ParseTreeVisitor *visitor) { return visitor->visitChildren(this); } -std::string RuleContext::toStringTree(Parser *recog) { - return tree::Trees::toStringTree(this, recog); +std::string RuleContext::toStringTree(Parser *recog, bool pretty) { + return tree::Trees::toStringTree(this, recog, pretty); } -std::string RuleContext::toStringTree(std::vector &ruleNames) { - return tree::Trees::toStringTree(this, ruleNames); +std::string RuleContext::toStringTree(std::vector &ruleNames, bool pretty) { + return tree::Trees::toStringTree(this, ruleNames, pretty); } -std::string RuleContext::toStringTree() { - return toStringTree(nullptr); +std::string RuleContext::toStringTree(bool pretty) { + return toStringTree(nullptr, pretty); } diff --git a/runtime/Cpp/runtime/src/RuleContext.h b/runtime/Cpp/runtime/src/RuleContext.h index bf0ff6631..9ee0d2def 100755 --- a/runtime/Cpp/runtime/src/RuleContext.h +++ b/runtime/Cpp/runtime/src/RuleContext.h @@ -110,15 +110,15 @@ namespace antlr4 { /// (root child1 .. childN). Print just a node if this is a leaf. /// We have to know the recognizer so we can get rule names. /// - virtual std::string toStringTree(Parser *recog) override; + virtual std::string toStringTree(Parser *recog, bool pretty = false) override; ///

/// Print out a whole tree, not just a node, in LISP format /// (root child1 .. childN). Print just a node if this is a leaf. /// - virtual std::string toStringTree(std::vector &ruleNames); + virtual std::string toStringTree(std::vector &ruleNames, bool pretty = false); - virtual std::string toStringTree() override; + virtual std::string toStringTree(bool pretty = false) override; virtual std::string toString() override; std::string toString(Recognizer *recog); std::string toString(const std::vector &ruleNames); diff --git a/runtime/Cpp/runtime/src/TokenStreamRewriter.cpp b/runtime/Cpp/runtime/src/TokenStreamRewriter.cpp index e281b19cc..df20ea9b9 100755 --- a/runtime/Cpp/runtime/src/TokenStreamRewriter.cpp +++ b/runtime/Cpp/runtime/src/TokenStreamRewriter.cpp @@ -348,7 +348,6 @@ std::unordered_map TokenStreamRe } // throw exception unless disjoint or identical bool disjoint = prevRop->lastIndex < rop->index || prevRop->index > rop->lastIndex; - bool same = prevRop->index == rop->index && prevRop->lastIndex == rop->lastIndex; // Delete special case of replace (text==null): // D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) if (prevRop->text.empty() && rop->text.empty() && !disjoint) { @@ -358,7 +357,7 @@ std::unordered_map TokenStreamRe rop->lastIndex = std::max(prevRop->lastIndex, rop->lastIndex); std::cout << "new rop " << rop << std::endl; } - else if (!disjoint && !same) { + else if (!disjoint) { throw IllegalArgumentException("replace op boundaries of " + rop->toString() + " overlap with previous " + prevRop->toString()); } diff --git a/runtime/Cpp/runtime/src/Vocabulary.h b/runtime/Cpp/runtime/src/Vocabulary.h index df78b4364..7dbf85cd3 100755 --- a/runtime/Cpp/runtime/src/Vocabulary.h +++ b/runtime/Cpp/runtime/src/Vocabulary.h @@ -16,7 +16,6 @@ namespace dfa { public: Vocabulary(Vocabulary const&) = default; virtual ~Vocabulary(); - Vocabulary& operator=(Vocabulary const&) = default; /// Gets an empty instance. /// diff --git a/runtime/Cpp/runtime/src/atn/ATNConfig.h b/runtime/Cpp/runtime/src/atn/ATNConfig.h index 700a6e120..a78b5c0c5 100755 --- a/runtime/Cpp/runtime/src/atn/ATNConfig.h +++ b/runtime/Cpp/runtime/src/atn/ATNConfig.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -57,7 +57,7 @@ namespace atn { *

* closure() tracks the depth of how far we dip into the outer context: * depth > 0. Note that it may not be totally accurate depth since I - * don't ever decrement. TO_DO: make it a boolean then

+ * don't ever decrement. TODO: make it a boolean then

* *

* For memory efficiency, the {@link #isPrecedenceFilterSuppressed} method @@ -87,7 +87,6 @@ namespace atn { ATNConfig(ATNConfig const&) = default; virtual ~ATNConfig(); - ATNConfig& operator=(ATNConfig const&) = default; virtual size_t hashCode() const; diff --git a/runtime/Cpp/runtime/src/atn/ATNConfigSet.h b/runtime/Cpp/runtime/src/atn/ATNConfigSet.h index 843b055eb..850a07c12 100755 --- a/runtime/Cpp/runtime/src/atn/ATNConfigSet.h +++ b/runtime/Cpp/runtime/src/atn/ATNConfigSet.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -18,8 +18,8 @@ namespace atn { /// Track the elements as they are added to the set; supports get(i) std::vector> configs; - // TO_DO: these fields make me pretty uncomfortable but nice to pack up info together, saves recomputation - // TO_DO: can we track conflicts as they are added to save scanning configs later? + // TODO: these fields make me pretty uncomfortable but nice to pack up info together, saves recomputation + // TODO: can we track conflicts as they are added to save scanning configs later? size_t uniqueAlt; /** Currently this is only used when we detect SLL conflict; this does diff --git a/runtime/Cpp/runtime/src/atn/AtomTransition.h b/runtime/Cpp/runtime/src/atn/AtomTransition.h index b3fa18864..cc22e5ad9 100755 --- a/runtime/Cpp/runtime/src/atn/AtomTransition.h +++ b/runtime/Cpp/runtime/src/atn/AtomTransition.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -10,7 +10,7 @@ namespace antlr4 { namespace atn { - /// TO_DO: make all transitions sets? no, should remove set edges. + /// TODO: make all transitions sets? no, should remove set edges. class ANTLR4CPP_PUBLIC AtomTransition final : public Transition { public: /// The token type or character value; or, signifies special label. diff --git a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp index c21ef0b2c..827c3d59f 100755 --- a/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp +++ b/runtime/Cpp/runtime/src/atn/LexerATNSimulator.cpp @@ -422,7 +422,7 @@ Ref LexerATNSimulator::getEpsilonTarget(CharStream *input, const if (config->context == nullptr|| config->context->hasEmptyPath()) { // execute actions anywhere in the start rule for a token. // - // TO_DO: if the entry rule is invoked recursively, some + // TODO: if the entry rule is invoked recursively, some // actions may be executed during the recursive call. The // problem can appear when hasEmptyPath() is true but // isEmpty() is false. In this case, the config needs to be diff --git a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp index 7d6cd00f6..30918ff0d 100755 --- a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp +++ b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.cpp @@ -922,7 +922,7 @@ void ParserATNSimulator::closure_(Ref const& config, ATNConfigSet *co } } - configs->dipsIntoOuterContext = true; // TO_DO: can remove? only care when we add to set per middle of this method + configs->dipsIntoOuterContext = true; // TODO: can remove? only care when we add to set per middle of this method assert(newDepth > INT_MIN); newDepth--; diff --git a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.h b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.h index 7e92c906b..6520a44bd 100755 --- a/runtime/Cpp/runtime/src/atn/ParserATNSimulator.h +++ b/runtime/Cpp/runtime/src/atn/ParserATNSimulator.h @@ -760,7 +760,7 @@ namespace atn { virtual bool evalSemanticContext(Ref const& pred, ParserRuleContext *parserCallStack, size_t alt, bool fullCtx); - /* TO_DO: If we are doing predicates, there is no point in pursuing + /* TODO: If we are doing predicates, there is no point in pursuing closure operations if we reach a DFA state that uniquely predicts alternative. We will not be caching that DFA state and it is a waste to pursue the closure. Might have to advance when we do diff --git a/runtime/Cpp/runtime/src/atn/PredicateTransition.h b/runtime/Cpp/runtime/src/atn/PredicateTransition.h index fed28bdf3..4d9b4205d 100755 --- a/runtime/Cpp/runtime/src/atn/PredicateTransition.h +++ b/runtime/Cpp/runtime/src/atn/PredicateTransition.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -11,7 +11,7 @@ namespace antlr4 { namespace atn { - /// TO_DO: this is old comment: + /// TODO: this is old comment: /// A tree of semantic predicates from the grammar AST if label==SEMPRED. /// In the ATN, labels will always be exactly one predicate, but the DFA /// may have to combine a bunch of them as it collects predicates from diff --git a/runtime/Cpp/runtime/src/atn/PredictionContext.cpp b/runtime/Cpp/runtime/src/atn/PredictionContext.cpp index 597e083a6..860a18056 100755 --- a/runtime/Cpp/runtime/src/atn/PredictionContext.cpp +++ b/runtime/Cpp/runtime/src/atn/PredictionContext.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -335,7 +335,7 @@ Ref PredictionContext::mergeArrays(const Ref M = std::make_shared(mergedParents, mergedReturnStates); // if we created same array as a or b, return that instead - // TO_DO: track whether this is possible above during merge sort for speed + // TODO: track whether this is possible above during merge sort for speed if (*M == *a) { if (mergeCache != nullptr) { mergeCache->put(a, b, a); diff --git a/runtime/Cpp/runtime/src/atn/ProfilingATNSimulator.cpp b/runtime/Cpp/runtime/src/atn/ProfilingATNSimulator.cpp index 6b2762022..62fc12f0a 100755 --- a/runtime/Cpp/runtime/src/atn/ProfilingATNSimulator.cpp +++ b/runtime/Cpp/runtime/src/atn/ProfilingATNSimulator.cpp @@ -99,7 +99,7 @@ std::unique_ptr ProfilingATNSimulator::computeReachSet(ATNConfigSe _decisions[_currentDecision].LL_ATNTransitions++; // count computation even if error if (reachConfigs != nullptr) { } else { // no reach on current lookahead symbol. ERROR. - // TO_DO: does not handle delayed errors per getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule() + // TODO: does not handle delayed errors per getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule() _decisions[_currentDecision].errors.push_back(ErrorInfo(_currentDecision, closure, _input, _startIndex, _llStopIndex, true)); } } else { diff --git a/runtime/Cpp/runtime/src/support/StringUtils.h b/runtime/Cpp/runtime/src/support/StringUtils.h index d0a0472a0..49715287e 100644 --- a/runtime/Cpp/runtime/src/support/StringUtils.h +++ b/runtime/Cpp/runtime/src/support/StringUtils.h @@ -22,7 +22,7 @@ namespace antlrcpp { inline std::string utf32_to_utf8(T const& data) { // Don't make the converter static or we have to serialize access to it. - UTF32Converter converter; + thread_local UTF32Converter converter; #if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000 auto p = reinterpret_cast(data.data()); @@ -34,7 +34,7 @@ namespace antlrcpp { inline UTF32String utf8_to_utf32(const char* first, const char* last) { - UTF32Converter converter; + thread_local UTF32Converter converter; #if defined(_MSC_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000 auto r = converter.from_bytes(first, last); diff --git a/runtime/Cpp/runtime/src/tree/ParseTree.h b/runtime/Cpp/runtime/src/tree/ParseTree.h index ee50b8039..088aac3ef 100755 --- a/runtime/Cpp/runtime/src/tree/ParseTree.h +++ b/runtime/Cpp/runtime/src/tree/ParseTree.h @@ -39,12 +39,12 @@ namespace tree { /// Print out a whole tree, not just a node, in LISP format /// {@code (root child1 .. childN)}. Print just a node if this is a leaf. - virtual std::string toStringTree() = 0; + virtual std::string toStringTree(bool pretty = false) = 0; virtual std::string toString() = 0; /// Specialize toStringTree so that it can print out more information /// based upon the parser. - virtual std::string toStringTree(Parser *parser) = 0; + virtual std::string toStringTree(Parser *parser, bool pretty = false) = 0; virtual bool operator == (const ParseTree &other) const; diff --git a/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.cpp b/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.cpp index 0f806d4e7..7ab121b73 100755 --- a/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.cpp +++ b/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.cpp @@ -41,7 +41,7 @@ std::string TerminalNodeImpl::getText() { return symbol->getText(); } -std::string TerminalNodeImpl::toStringTree(Parser * /*parser*/) { +std::string TerminalNodeImpl::toStringTree(Parser * /*parser*/, bool /*pretty*/) { return toString(); } @@ -52,6 +52,6 @@ std::string TerminalNodeImpl::toString() { return symbol->getText(); } -std::string TerminalNodeImpl::toStringTree() { +std::string TerminalNodeImpl::toStringTree(bool /*pretty*/) { return toString(); } diff --git a/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.h b/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.h index d865c58e8..6f65d8204 100755 --- a/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.h +++ b/runtime/Cpp/runtime/src/tree/TerminalNodeImpl.h @@ -23,9 +23,9 @@ namespace tree { virtual antlrcpp::Any accept(ParseTreeVisitor *visitor) override; virtual std::string getText() override; - virtual std::string toStringTree(Parser *parser) override; + virtual std::string toStringTree(Parser *parser, bool pretty = false) override; virtual std::string toString() override; - virtual std::string toStringTree() override; + virtual std::string toStringTree(bool pretty = false) override; }; diff --git a/runtime/Cpp/runtime/src/tree/Trees.cpp b/runtime/Cpp/runtime/src/tree/Trees.cpp index fabad0141..72b9b8b48 100755 --- a/runtime/Cpp/runtime/src/tree/Trees.cpp +++ b/runtime/Cpp/runtime/src/tree/Trees.cpp @@ -25,17 +25,17 @@ using namespace antlrcpp; Trees::Trees() { } -std::string Trees::toStringTree(ParseTree *t) { - return toStringTree(t, nullptr); +std::string Trees::toStringTree(ParseTree *t, bool pretty) { + return toStringTree(t, nullptr, pretty); } -std::string Trees::toStringTree(ParseTree *t, Parser *recog) { +std::string Trees::toStringTree(ParseTree *t, Parser *recog, bool pretty) { if (recog == nullptr) - return toStringTree(t, std::vector()); - return toStringTree(t, recog->getRuleNames()); + return toStringTree(t, std::vector(), pretty); + return toStringTree(t, recog->getRuleNames(), pretty); } -std::string Trees::toStringTree(ParseTree *t, const std::vector &ruleNames) { +std::string Trees::toStringTree(ParseTree *t, const std::vector &ruleNames, bool pretty) { std::string temp = antlrcpp::escapeWhitespace(Trees::getNodeText(t, ruleNames), false); if (t->children.empty()) { return temp; @@ -48,6 +48,7 @@ std::string Trees::toStringTree(ParseTree *t, const std::vector &ru std::stack stack; size_t childIndex = 0; ParseTree *run = t; + size_t indentationLevel = 1; while (childIndex < run->children.size()) { if (childIndex > 0) { ss << ' '; @@ -59,6 +60,13 @@ std::string Trees::toStringTree(ParseTree *t, const std::vector &ru stack.push(childIndex); run = child; childIndex = 0; + if (pretty) { + ++indentationLevel; + ss << std::endl; + for (size_t i = 0; i < indentationLevel; ++i) { + ss << " "; + } + } ss << "(" << temp << " "; } else { ss << temp; @@ -68,6 +76,9 @@ std::string Trees::toStringTree(ParseTree *t, const std::vector &ru childIndex = stack.top(); stack.pop(); run = run->parent; + if (pretty) { + --indentationLevel; + } ss << ")"; } else { break; diff --git a/runtime/Cpp/runtime/src/tree/Trees.h b/runtime/Cpp/runtime/src/tree/Trees.h index e6a1bb88e..d9d04624f 100755 --- a/runtime/Cpp/runtime/src/tree/Trees.h +++ b/runtime/Cpp/runtime/src/tree/Trees.h @@ -18,17 +18,17 @@ namespace tree { /// Print out a whole tree in LISP form. getNodeText is used on the /// node payloads to get the text for the nodes. Detect /// parse trees and extract data appropriately. - static std::string toStringTree(ParseTree *t); + static std::string toStringTree(ParseTree *t, bool pretty = false); /// Print out a whole tree in LISP form. getNodeText is used on the /// node payloads to get the text for the nodes. Detect /// parse trees and extract data appropriately. - static std::string toStringTree(ParseTree *t, Parser *recog); + static std::string toStringTree(ParseTree *t, Parser *recog, bool pretty = false); /// Print out a whole tree in LISP form. getNodeText is used on the /// node payloads to get the text for the nodes. Detect /// parse trees and extract data appropriately. - static std::string toStringTree(ParseTree *t, const std::vector &ruleNames); + static std::string toStringTree(ParseTree *t, const std::vector &ruleNames, bool pretty = false); static std::string getNodeText(ParseTree *t, Parser *recog); static std::string getNodeText(ParseTree *t, const std::vector &ruleNames); diff --git a/runtime/Cpp/runtime/src/tree/pattern/ParseTreeMatch.h b/runtime/Cpp/runtime/src/tree/pattern/ParseTreeMatch.h index 35cb90ae4..eefde46c8 100755 --- a/runtime/Cpp/runtime/src/tree/pattern/ParseTreeMatch.h +++ b/runtime/Cpp/runtime/src/tree/pattern/ParseTreeMatch.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -45,7 +45,6 @@ namespace pattern { const std::map> &labels, ParseTree *mismatchedNode); ParseTreeMatch(ParseTreeMatch const&) = default; virtual ~ParseTreeMatch(); - ParseTreeMatch& operator=(ParseTreeMatch const&) = default; ///

/// Get the last node associated with a specific {@code label}. diff --git a/runtime/Cpp/runtime/src/tree/pattern/ParseTreePattern.h b/runtime/Cpp/runtime/src/tree/pattern/ParseTreePattern.h index 3df2f633e..d5b86ff47 100755 --- a/runtime/Cpp/runtime/src/tree/pattern/ParseTreePattern.h +++ b/runtime/Cpp/runtime/src/tree/pattern/ParseTreePattern.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +/* 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. */ @@ -30,7 +30,6 @@ namespace pattern { ParseTree *patternTree); ParseTreePattern(ParseTreePattern const&) = default; virtual ~ParseTreePattern(); - ParseTreePattern& operator=(ParseTreePattern const&) = default; /// /// Match a specific parse tree against this tree pattern. diff --git a/runtime/Cpp/runtime/src/tree/xpath/XPath.cpp b/runtime/Cpp/runtime/src/tree/xpath/XPath.cpp index 6dd13832d..c7cc3b864 100755 --- a/runtime/Cpp/runtime/src/tree/xpath/XPath.cpp +++ b/runtime/Cpp/runtime/src/tree/xpath/XPath.cpp @@ -25,11 +25,10 @@ const std::string XPath::NOT = "!"; XPath::XPath(Parser *parser, const std::string &path) { _parser = parser; _path = path; - _elements = split(path); } -std::vector XPath::split(const std::string &path) { - ANTLRFileStream in(path); +std::vector> XPath::split(const std::string &path) { + ANTLRInputStream in(path); XPathLexer lexer(&in); lexer.removeErrorListeners(); XPathLexerErrorListener listener; @@ -44,7 +43,7 @@ std::vector XPath::split(const std::string &path) { } std::vector tokens = tokenStream.getTokens(); - std::vector elements; + std::vector> elements; size_t n = tokens.size(); size_t i = 0; bool done = false; @@ -62,9 +61,9 @@ std::vector XPath::split(const std::string &path) { i++; next = tokens[i]; } - XPathElement pathElement = getXPathElement(next, anywhere); - pathElement.setInvert(invert); - elements.push_back(pathElement); + std::unique_ptr pathElement = getXPathElement(next, anywhere); + pathElement->setInvert(invert); + elements.push_back(std::move(pathElement)); i++; break; @@ -81,25 +80,26 @@ std::vector XPath::split(const std::string &path) { break; default : - throw IllegalArgumentException("Unknow path element " + el->toString()); + throw IllegalArgumentException("Unknown path element " + el->toString()); } } return elements; } -XPathElement XPath::getXPathElement(Token *wordToken, bool anywhere) { +std::unique_ptr XPath::getXPathElement(Token *wordToken, bool anywhere) { if (wordToken->getType() == Token::EOF) { throw IllegalArgumentException("Missing path element at end of path"); } + std::string word = wordToken->getText(); size_t ttype = _parser->getTokenType(word); ssize_t ruleIndex = _parser->getRuleIndex(word); switch (wordToken->getType()) { case XPathLexer::WILDCARD : if (anywhere) - return XPathWildcardAnywhereElement(); - return XPathWildcardElement(); + return std::unique_ptr(new XPathWildcardAnywhereElement()); + return std::unique_ptr(new XPathWildcardElement()); case XPathLexer::TOKEN_REF: case XPathLexer::STRING : @@ -107,35 +107,42 @@ XPathElement XPath::getXPathElement(Token *wordToken, bool anywhere) { throw IllegalArgumentException(word + " at index " + std::to_string(wordToken->getStartIndex()) + " isn't a valid token name"); } if (anywhere) - return XPathTokenAnywhereElement(word, (int)ttype); - return XPathTokenElement(word, (int)ttype); + return std::unique_ptr(new XPathTokenAnywhereElement(word, (int)ttype)); + return std::unique_ptr(new XPathTokenElement(word, (int)ttype)); default : if (ruleIndex == -1) { throw IllegalArgumentException(word + " at index " + std::to_string(wordToken->getStartIndex()) + " isn't a valid rule name"); } if (anywhere) - return XPathRuleAnywhereElement(word, (int)ruleIndex); - return XPathRuleElement(word, (int)ruleIndex); + return std::unique_ptr(new XPathRuleAnywhereElement(word, (int)ruleIndex)); + return std::unique_ptr(new XPathRuleElement(word, (int)ruleIndex)); } } static ParserRuleContext dummyRoot; +std::vector XPath::findAll(ParseTree *tree, std::string const& xpath, Parser *parser) { + XPath p(parser, xpath); + return p.evaluate(tree); +} + std::vector XPath::evaluate(ParseTree *t) { dummyRoot.children = { t }; // don't set t's parent. std::vector work = { &dummyRoot }; size_t i = 0; - while (i < _elements.size()) { + std::vector> elements = split(_path); + + while (i < elements.size()) { std::vector next; 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 // we can't go looking for stat nodes. - auto matching = _elements[i].evaluate(node); + auto matching = elements[i]->evaluate(node); next.insert(next.end(), matching.begin(), matching.end()); } } diff --git a/runtime/Cpp/runtime/src/tree/xpath/XPath.h b/runtime/Cpp/runtime/src/tree/xpath/XPath.h index 07a35921c..e38d482d5 100755 --- a/runtime/Cpp/runtime/src/tree/xpath/XPath.h +++ b/runtime/Cpp/runtime/src/tree/xpath/XPath.h @@ -61,8 +61,10 @@ namespace xpath { XPath(Parser *parser, const std::string &path); virtual ~XPath() {} - // TO_DO: check for invalid token/rule names, bad syntax - virtual std::vector split(const std::string &path); + // TODO: check for invalid token/rule names, bad syntax + virtual std::vector> split(const std::string &path); + + static std::vector findAll(ParseTree *tree, std::string const& xpath, Parser *parser); /// Return a list of all nodes starting at {@code t} as root that satisfy the /// path. The root {@code /} is relative to the node passed to @@ -71,13 +73,12 @@ namespace xpath { protected: std::string _path; - std::vector _elements; Parser *_parser; /// Convert word like {@code *} or {@code ID} or {@code expr} to a path /// element. {@code anywhere} is {@code true} if {@code //} precedes the /// word. - virtual XPathElement getXPathElement(Token *wordToken, bool anywhere); + virtual std::unique_ptr getXPathElement(Token *wordToken, bool anywhere); }; } // namespace xpath diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java b/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java index ec74ce5bd..79d903053 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/LexerATNSimulator.java @@ -78,8 +78,6 @@ public class LexerATNSimulator extends ATNSimulator { protected final SimState prevAccept = new SimState(); - public static int match_calls = 0; - public LexerATNSimulator(ATN atn, DFA[] decisionToDFA, PredictionContextCache sharedContextCache) { @@ -103,7 +101,6 @@ public class LexerATNSimulator extends ATNSimulator { } public int match(CharStream input, int mode) { - match_calls++; this.mode = mode; int mark = input.mark(); try { diff --git a/runtime/JavaScript/src/antlr4/PredictionContext.js b/runtime/JavaScript/src/antlr4/PredictionContext.js index e69cdea37..052869600 100644 --- a/runtime/JavaScript/src/antlr4/PredictionContext.js +++ b/runtime/JavaScript/src/antlr4/PredictionContext.js @@ -7,6 +7,7 @@ var RuleContext = require('./RuleContext').RuleContext; var Hash = require('./Utils').Hash; +var Map = require('./Utils').Map; function PredictionContext(cachedHashCode) { this.cachedHashCode = cachedHashCode; @@ -79,7 +80,7 @@ function calculateHashString(parent, returnState) { // can be used for both lexers and parsers. function PredictionContextCache() { - this.cache = {}; + this.cache = new Map(); return this; } @@ -91,16 +92,16 @@ PredictionContextCache.prototype.add = function(ctx) { if (ctx === PredictionContext.EMPTY) { return PredictionContext.EMPTY; } - var existing = this.cache[ctx] || null; + var existing = this.cache.get(ctx) || null; if (existing !== null) { return existing; } - this.cache[ctx] = ctx; + this.cache.put(ctx, ctx); return ctx; }; PredictionContextCache.prototype.get = function(ctx) { - return this.cache[ctx] || null; + return this.cache.get(ctx) || null; }; Object.defineProperty(PredictionContextCache.prototype, "length", { @@ -111,11 +112,13 @@ Object.defineProperty(PredictionContextCache.prototype, "length", { function SingletonPredictionContext(parent, returnState) { var hashCode = 0; + var hash = new Hash(); if(parent !== null) { - var hash = new Hash(); hash.update(parent, returnState); - hashCode = hash.finish(); + } else { + hash.update(1); } + hashCode = hash.finish(); PredictionContext.call(this, hashCode); this.parentCtx = parent; this.returnState = returnState; @@ -640,16 +643,16 @@ function mergeArrays(a, b, rootIsWildcard, mergeCache) { // ones. // / function combineCommonParents(parents) { - var uniqueParents = {}; + var uniqueParents = new Map(); for (var p = 0; p < parents.length; p++) { var parent = parents[p]; - if (!(parent in uniqueParents)) { - uniqueParents[parent] = parent; + if (!(uniqueParents.containsKey(parent))) { + uniqueParents.put(parent, parent); } } for (var q = 0; q < parents.length; q++) { - parents[q] = uniqueParents[parents[q]]; + parents[q] = uniqueParents.get(parents[q]); } } @@ -657,13 +660,13 @@ function getCachedPredictionContext(context, contextCache, visited) { if (context.isEmpty()) { return context; } - var existing = visited[context] || null; + var existing = visited.get(context) || null; if (existing !== null) { return existing; } existing = contextCache.get(context); if (existing !== null) { - visited[context] = existing; + visited.put(context, existing); return existing; } var changed = false; @@ -683,7 +686,7 @@ function getCachedPredictionContext(context, contextCache, visited) { } if (!changed) { contextCache.add(context); - visited[context] = context; + visited.put(context, context); return context; } var updated = null; @@ -696,8 +699,8 @@ function getCachedPredictionContext(context, contextCache, visited) { updated = new ArrayPredictionContext(parents, context.returnStates); } contextCache.add(updated); - visited[updated] = updated; - visited[context] = updated; + visited.put(updated, updated); + visited.put(context, updated); return updated; } @@ -708,13 +711,13 @@ function getAllContextNodes(context, nodes, visited) { nodes = []; return getAllContextNodes(context, nodes, visited); } else if (visited === null) { - visited = {}; + visited = new Map(); return getAllContextNodes(context, nodes, visited); } else { - if (context === null || visited[context] !== null) { + if (context === null || visited.containsKey(context)) { return nodes; } - visited[context] = context; + visited.put(context, context); nodes.push(context); for (var i = 0; i < context.length; i++) { getAllContextNodes(context.getParent(i), nodes, visited); diff --git a/runtime/JavaScript/src/antlr4/Utils.js b/runtime/JavaScript/src/antlr4/Utils.js index 2cb939a66..e89772244 100644 --- a/runtime/JavaScript/src/antlr4/Utils.js +++ b/runtime/JavaScript/src/antlr4/Utils.js @@ -323,7 +323,9 @@ AltDict.prototype.values = function () { }); }; -function DoubleDict() { +function DoubleDict(defaultMapCtor) { + this.defaultMapCtor = defaultMapCtor || Map; + this.cacheMap = new this.defaultMapCtor(); return this; } @@ -339,7 +341,7 @@ Hash.prototype.update = function () { if (value == null) continue; if(Array.isArray(value)) - this.update.apply(value); + this.update.apply(this, value); else { var k = 0; switch (typeof(value)) { @@ -354,7 +356,10 @@ Hash.prototype.update = function () { k = value.hashCode(); break; default: - value.updateHashCode(this); + if(value.updateHashCode) + value.updateHashCode(this); + else + console.log("No updateHashCode for " + value.toString()) continue; } k = k * 0xCC9E2D51; @@ -367,7 +372,7 @@ Hash.prototype.update = function () { this.hash = hash; } } -} +}; Hash.prototype.finish = function () { var hash = this.hash ^ (this.count * 4); @@ -377,26 +382,26 @@ Hash.prototype.finish = function () { hash = hash * 0xC2B2AE35; hash = hash ^ (hash >>> 16); return hash; -} +}; function hashStuff() { var hash = new Hash(); - hash.update.apply(arguments); + hash.update.apply(hash, arguments); return hash.finish(); } DoubleDict.prototype.get = function (a, b) { - var d = this[a] || null; - return d === null ? null : (d[b] || null); + var d = this.cacheMap.get(a) || null; + return d === null ? null : (d.get(b) || null); }; DoubleDict.prototype.set = function (a, b, o) { - var d = this[a] || null; + var d = this.cacheMap.get(a) || null; if (d === null) { - d = {}; - this[a] = d; + d = new this.defaultMapCtor(); + this.cacheMap.put(a, d); } - d[b] = o; + d.put(b, o); }; diff --git a/runtime/JavaScript/src/antlr4/atn/ATNConfigSet.js b/runtime/JavaScript/src/antlr4/atn/ATNConfigSet.js index 31b249d47..5a45f797e 100644 --- a/runtime/JavaScript/src/antlr4/atn/ATNConfigSet.js +++ b/runtime/JavaScript/src/antlr4/atn/ATNConfigSet.js @@ -175,7 +175,7 @@ ATNConfigSet.prototype.equals = function(other) { ATNConfigSet.prototype.hashCode = function() { var hash = new Hash(); - this.updateHashCode(hash); + hash.update(this.configs); return hash.finish(); }; @@ -183,13 +183,11 @@ ATNConfigSet.prototype.hashCode = function() { ATNConfigSet.prototype.updateHashCode = function(hash) { if (this.readOnly) { if (this.cachedHashCode === -1) { - var hash = new Hash(); - hash.update(this.configs); - this.cachedHashCode = hash.finish(); + this.cachedHashCode = this.hashCode(); } hash.update(this.cachedHashCode); } else { - hash.update(this.configs); + hash.update(this.hashCode()); } }; diff --git a/runtime/JavaScript/src/antlr4/atn/ATNDeserializer.js b/runtime/JavaScript/src/antlr4/atn/ATNDeserializer.js index 3d71d4242..295c07924 100644 --- a/runtime/JavaScript/src/antlr4/atn/ATNDeserializer.js +++ b/runtime/JavaScript/src/antlr4/atn/ATNDeserializer.js @@ -138,7 +138,7 @@ ATNDeserializer.prototype.deserialize = function(data) { ATNDeserializer.prototype.reset = function(data) { var adjust = function(c) { var v = c.charCodeAt(0); - return v>1 ? v-2 : v + 65533; + return v>1 ? v-2 : v + 65534; }; var temp = data.split("").map(adjust); // don't adjust the first value since that's the version number diff --git a/runtime/JavaScript/src/antlr4/atn/ATNSimulator.js b/runtime/JavaScript/src/antlr4/atn/ATNSimulator.js index ea87dabbf..6e52669cb 100644 --- a/runtime/JavaScript/src/antlr4/atn/ATNSimulator.js +++ b/runtime/JavaScript/src/antlr4/atn/ATNSimulator.js @@ -8,6 +8,7 @@ var DFAState = require('./../dfa/DFAState').DFAState; var ATNConfigSet = require('./ATNConfigSet').ATNConfigSet; var getCachedPredictionContext = require('./../PredictionContext').getCachedPredictionContext; +var Map = require('./../Utils').Map; function ATNSimulator(atn, sharedContextCache) { @@ -44,7 +45,7 @@ ATNSimulator.prototype.getCachedContext = function(context) { if (this.sharedContextCache ===null) { return context; } - var visited = {}; + var visited = new Map(); return getCachedPredictionContext(context, this.sharedContextCache, visited); }; diff --git a/runtime/JavaScript/src/antlr4/dfa/DFAState.js b/runtime/JavaScript/src/antlr4/dfa/DFAState.js index e597a54c3..b80df0365 100644 --- a/runtime/JavaScript/src/antlr4/dfa/DFAState.js +++ b/runtime/JavaScript/src/antlr4/dfa/DFAState.js @@ -139,12 +139,6 @@ DFAState.prototype.toString = function() { DFAState.prototype.hashCode = function() { var hash = new Hash(); hash.update(this.configs); - if(this.isAcceptState) { - if (this.predicates !== null) - hash.update(this.predicates); - else - hash.update(this.prediction); - } return hash.finish(); }; diff --git a/runtime/PHP b/runtime/PHP new file mode 160000 index 000000000..9e1b759d0 --- /dev/null +++ b/runtime/PHP @@ -0,0 +1 @@ +Subproject commit 9e1b759d02220eedf477771169bdfb6a186a2984 diff --git a/runtime/Python2/src/antlr4/TokenStreamRewriter.py b/runtime/Python2/src/antlr4/TokenStreamRewriter.py index 23bb0d40a..5e7ec6827 100644 --- a/runtime/Python2/src/antlr4/TokenStreamRewriter.py +++ b/runtime/Python2/src/antlr4/TokenStreamRewriter.py @@ -157,13 +157,12 @@ class TokenStreamRewriter(object): rewrites[prevRop.instructionIndex] = None continue isDisjoint = any((prevRop.last_index < rop.index, prevRop.index > rop.last_index)) - isSame = all((prevRop.index == rop.index, prevRop.last_index == rop.last_index)) if all((prevRop.text is None, rop.text is None, not isDisjoint)): rewrites[prevRop.instructionIndex] = None rop.index = min(prevRop.index, rop.index) rop.last_index = min(prevRop.last_index, rop.last_index) print('New rop {}'.format(rop)) - elif not all((isDisjoint, isSame)): + elif (not(isDisjoint)): raise ValueError("replace op boundaries of {} overlap with previous {}".format(rop, prevRop)) # Walk inserts before diff --git a/runtime/Python2/tests/run.py b/runtime/Python2/tests/run.py new file mode 100644 index 000000000..c9ae18877 --- /dev/null +++ b/runtime/Python2/tests/run.py @@ -0,0 +1,7 @@ +import sys +import os +src_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'src') +sys.path.insert(0,src_path) +from TestTokenStreamRewriter import TestTokenStreamRewriter +import unittest +unittest.main() \ No newline at end of file diff --git a/runtime/Python3/src/antlr4/TokenStreamRewriter.py b/runtime/Python3/src/antlr4/TokenStreamRewriter.py index d714d9fe6..04a3af657 100644 --- a/runtime/Python3/src/antlr4/TokenStreamRewriter.py +++ b/runtime/Python3/src/antlr4/TokenStreamRewriter.py @@ -156,13 +156,12 @@ class TokenStreamRewriter(object): rewrites[prevRop.instructionIndex] = None continue isDisjoint = any((prevRop.last_indexrop.last_index)) - isSame = all((prevRop.index == rop.index, prevRop.last_index == rop.last_index)) if all((prevRop.text is None, rop.text is None, not isDisjoint)): rewrites[prevRop.instructionIndex] = None rop.index = min(prevRop.index, rop.index) rop.last_index = min(prevRop.last_index, rop.last_index) print('New rop {}'.format(rop)) - elif not all((isDisjoint, isSame)): + elif (not(isDisjoint)): raise ValueError("replace op boundaries of {} overlap with previous {}".format(rop, prevRop)) # Walk inserts @@ -249,4 +248,4 @@ class TokenStreamRewriter(object): def __str__(self): if self.text: return ''.format(self.tokens.get(self.index), self.tokens.get(self.last_index), - self.text) \ No newline at end of file + self.text) diff --git a/runtime/Python3/src/antlr4/xpath/XPath.py b/runtime/Python3/src/antlr4/xpath/XPath.py index c49e3ba94..58b05c466 100644 --- a/runtime/Python3/src/antlr4/xpath/XPath.py +++ b/runtime/Python3/src/antlr4/xpath/XPath.py @@ -47,7 +47,7 @@ #

# Whitespace is not allowed.

# -from antlr4 import CommonTokenStream, DFA, PredictionContextCache, Lexer, LexerATNSimulator +from antlr4 import CommonTokenStream, DFA, PredictionContextCache, Lexer, LexerATNSimulator, ParserRuleContext, TerminalNode from antlr4.InputStream import InputStream from antlr4.Parser import Parser from antlr4.RuleContext import RuleContext @@ -134,7 +134,7 @@ class XPathLexer(Lexer): if _action is not None: _action(localctx, actionIndex) else: - raise Exception("No registered action for:" + str(ruleIndex)) + raise Exception("No registered action for: %d" % ruleIndex) def ID_action(self, localctx:RuleContext , actionIndex:int): if actionIndex == 0: @@ -166,40 +166,40 @@ class XPath(object): try: tokenStream.fill() except LexerNoViableAltException as e: - pos = lexer.getColumn() - msg = "Invalid tokens or characters at index " + str(pos) + " in path '" + path + "'" + pos = lexer.column + msg = "Invalid tokens or characters at index %d in path '%s'" % (pos, path) raise Exception(msg, e) - tokens = tokenStream.getTokens() + tokens = iter(tokenStream.tokens) elements = list() - n = len(tokens) - i=0 - while i < n : - el = tokens[i] - next = None + for el in tokens: + invert = False + anywhere = False + # Check for path separators, if none assume root if el.type in [XPathLexer.ROOT, XPathLexer.ANYWHERE]: - anywhere = el.type == XPathLexer.ANYWHERE - i += 1 - next = tokens[i] - invert = next.type==XPathLexer.BANG - if invert: - i += 1 - next = tokens[i] - pathElement = self.getXPathElement(next, anywhere) - pathElement.invert = invert - elements.append(pathElement) - i += 1 - - elif el.type in [XPathLexer.TOKEN_REF, XPathLexer.RULE_REF, XPathLexer.WILDCARD] : - elements.append( self.getXPathElement(el, False) ) - i += 1 - - elif el.type==Token.EOF : - break - + anywhere = el.type == XPathLexer.ANYWHERE + next_el = next(tokens, None) + if not next_el: + raise Exception('Missing element after %s' % el.getText()) + else: + el = next_el + # Check for bangs + if el.type == XPathLexer.BANG: + invert = True + next_el = next(tokens, None) + if not next_el: + raise Exception('Missing element after %s' % el.getText()) + else: + el = next_el + # Add searched element + if el.type in [XPathLexer.TOKEN_REF, XPathLexer.RULE_REF, XPathLexer.WILDCARD, XPathLexer.STRING]: + element = self.getXPathElement(el, anywhere) + element.invert = invert + elements.append(element) + elif el.type==Token.EOF: + break else: - raise Exception("Unknown path element " + str(el)) - + raise Exception("Unknown path element %s" % lexer.symbolicNames[el.type]) return elements # @@ -210,24 +210,31 @@ class XPath(object): def getXPathElement(self, wordToken:Token, anywhere:bool): if wordToken.type==Token.EOF: raise Exception("Missing path element at end of path") + word = wordToken.text - ttype = self.parser.getTokenType(word) - ruleIndex = self.parser.getRuleIndex(word) - if wordToken.type==XPathLexer.WILDCARD : - return XPathWildcardAnywhereElement() if anywhere else XPathWildcardElement() elif wordToken.type in [XPathLexer.TOKEN_REF, XPathLexer.STRING]: + tsource = self.parser.getTokenStream().tokenSource - if ttype==Token.INVALID_TYPE: - raise Exception( word + " at index " + str(wordToken.startIndex) + " isn't a valid token name") + ttype = Token.INVALID_TYPE + if wordToken.type == XPathLexer.TOKEN_REF: + if word in tsource.ruleNames: + ttype = tsource.ruleNames.index(word) + 1 + else: + if word in tsource.literalNames: + ttype = tsource.literalNames.index(word) + + if ttype == Token.INVALID_TYPE: + raise Exception("%s at index %d isn't a valid token name" % (word, wordToken.tokenIndex)) return XPathTokenAnywhereElement(word, ttype) if anywhere else XPathTokenElement(word, ttype) else: + ruleIndex = self.parser.ruleNames.index(word) if word in self.parser.ruleNames else -1 - if ruleIndex==-1: - raise Exception( word + " at index " + str(wordToken.getStartIndex()) + " isn't a valid rule name") + if ruleIndex == -1: + raise Exception("%s at index %d isn't a valid rule name" % (word, wordToken.tokenIndex)) return XPathRuleAnywhereElement(word, ruleIndex) if anywhere else XPathRuleElement(word, ruleIndex) @@ -246,18 +253,21 @@ class XPath(object): dummyRoot.children = [t] # don't set t's parent. work = [dummyRoot] - - for i in range(0, len(self.elements)): - next = set() + for element in self.elements: + work_next = list() for node in work: - if len( node.children) > 0 : + if not isinstance(node, TerminalNode) and node.children: # only try to match next element if it has children # e.g., //func/*/stat might have a token node for which # we can't go looking for stat nodes. - matching = self.elements[i].evaluate(node) - next |= matching - i += 1 - work = next + matching = element.evaluate(node) + + # See issue antlr#370 - Prevents XPath from returning the + # same node multiple times + matching = filter(lambda m: m not in work_next, matching) + + work_next.extend(matching) + work = work_next return work @@ -283,8 +293,8 @@ class XPathRuleAnywhereElement(XPathElement): self.ruleIndex = ruleIndex def evaluate(self, t:ParseTree): - return Trees.findAllRuleNodes(t, self.ruleIndex) - + # return all ParserRuleContext descendants of t that match ruleIndex (or do not match if inverted) + return filter(lambda c: isinstance(c, ParserRuleContext) and (self.invert ^ (c.getRuleIndex() == self.ruleIndex)), Trees.descendants(t)) class XPathRuleElement(XPathElement): @@ -293,9 +303,8 @@ class XPathRuleElement(XPathElement): self.ruleIndex = ruleIndex def evaluate(self, t:ParseTree): - # return all children of t that match nodeName - return [c for c in Trees.getChildren(t) if isinstance(c, ParserRuleContext) and (c.ruleIndex == self.ruleIndex) == (not self.invert)] - + # return all ParserRuleContext children of t that match ruleIndex (or do not match if inverted) + return filter(lambda c: isinstance(c, ParserRuleContext) and (self.invert ^ (c.getRuleIndex() == self.ruleIndex)), Trees.getChildren(t)) class XPathTokenAnywhereElement(XPathElement): @@ -304,8 +313,8 @@ class XPathTokenAnywhereElement(XPathElement): self.tokenType = tokenType def evaluate(self, t:ParseTree): - return Trees.findAllTokenNodes(t, self.tokenType) - + # return all TerminalNode descendants of t that match tokenType (or do not match if inverted) + return filter(lambda c: isinstance(c, TerminalNode) and (self.invert ^ (c.symbol.type == self.tokenType)), Trees.descendants(t)) class XPathTokenElement(XPathElement): @@ -314,8 +323,8 @@ class XPathTokenElement(XPathElement): self.tokenType = tokenType def evaluate(self, t:ParseTree): - # return all children of t that match nodeName - return [c for c in Trees.getChildren(t) if isinstance(c, TerminalNode) and (c.symbol.type == self.tokenType) == (not self.invert)] + # return all TerminalNode children of t that match tokenType (or do not match if inverted) + return filter(lambda c: isinstance(c, TerminalNode) and (self.invert ^ (c.symbol.type == self.tokenType)), Trees.getChildren(t)) class XPathWildcardAnywhereElement(XPathElement): diff --git a/runtime/Python3/test/expr/Expr.g4 b/runtime/Python3/test/expr/Expr.g4 new file mode 100644 index 000000000..662079641 --- /dev/null +++ b/runtime/Python3/test/expr/Expr.g4 @@ -0,0 +1,31 @@ +// Taken from "tool-testsuite/test/org/antlr/v4/test/tool/TestXPath.java" +// Builds ExprLexer.py and ExprParser.py + +grammar Expr; +prog: func+ ; +func: 'def' ID '(' arg (',' arg)* ')' body ; +body: '{' stat+ '}' ; +arg : ID ; +stat: expr ';' # printExpr + | ID '=' expr ';' # assign + | 'return' expr ';' # ret + | ';' # blank + ; +expr: expr ('*'|'/') expr # MulDiv + | expr ('+'|'-') expr # AddSub + | primary # prim + ; +primary + : INT # int + | ID # id + | '(' expr ')' # parens + ; +MUL : '*' ; // assigns token name to '*' used above in grammar +DIV : '/' ; +ADD : '+' ; +SUB : '-' ; +RETURN : 'return' ; +ID : [a-zA-Z]+ ; // match identifiers +INT : [0-9]+ ; // match integers +NEWLINE:'\r'? '\n' -> skip; // return newlines to parser (is end-statement signal) +WS : [ \t]+ -> skip ; // toss out whitespace \ No newline at end of file diff --git a/runtime/Python3/test/expr/ExprLexer.py b/runtime/Python3/test/expr/ExprLexer.py new file mode 100644 index 000000000..e338b0b9e --- /dev/null +++ b/runtime/Python3/test/expr/ExprLexer.py @@ -0,0 +1,94 @@ +# Generated from expr/Expr.g4 by ANTLR 4.7.2 +from antlr4 import * +from io import StringIO +from typing.io import TextIO +import sys + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\23") + buf.write("^\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") + buf.write("\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16") + buf.write("\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22\3\2\3\2") + buf.write("\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3") + buf.write("\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\16\3\16") + buf.write("\3\16\3\16\3\16\3\16\3\16\3\17\6\17H\n\17\r\17\16\17I") + buf.write("\3\20\6\20M\n\20\r\20\16\20N\3\21\5\21R\n\21\3\21\3\21") + buf.write("\3\21\3\21\3\22\6\22Y\n\22\r\22\16\22Z\3\22\3\22\2\2\23") + buf.write("\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31") + buf.write("\16\33\17\35\20\37\21!\22#\23\3\2\5\4\2C\\c|\3\2\62;\4") + buf.write("\2\13\13\"\"\2a\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2") + buf.write("\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21") + buf.write("\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3") + buf.write("\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2") + buf.write("\2\2#\3\2\2\2\3%\3\2\2\2\5)\3\2\2\2\7+\3\2\2\2\t-\3\2") + buf.write("\2\2\13/\3\2\2\2\r\61\3\2\2\2\17\63\3\2\2\2\21\65\3\2") + buf.write("\2\2\23\67\3\2\2\2\259\3\2\2\2\27;\3\2\2\2\31=\3\2\2\2") + buf.write("\33?\3\2\2\2\35G\3\2\2\2\37L\3\2\2\2!Q\3\2\2\2#X\3\2\2") + buf.write("\2%&\7f\2\2&\'\7g\2\2\'(\7h\2\2(\4\3\2\2\2)*\7*\2\2*\6") + buf.write("\3\2\2\2+,\7.\2\2,\b\3\2\2\2-.\7+\2\2.\n\3\2\2\2/\60\7") + buf.write("}\2\2\60\f\3\2\2\2\61\62\7\177\2\2\62\16\3\2\2\2\63\64") + buf.write("\7=\2\2\64\20\3\2\2\2\65\66\7?\2\2\66\22\3\2\2\2\678\7") + buf.write(",\2\28\24\3\2\2\29:\7\61\2\2:\26\3\2\2\2;<\7-\2\2<\30") + buf.write("\3\2\2\2=>\7/\2\2>\32\3\2\2\2?@\7t\2\2@A\7g\2\2AB\7v\2") + buf.write("\2BC\7w\2\2CD\7t\2\2DE\7p\2\2E\34\3\2\2\2FH\t\2\2\2GF") + buf.write("\3\2\2\2HI\3\2\2\2IG\3\2\2\2IJ\3\2\2\2J\36\3\2\2\2KM\t") + buf.write("\3\2\2LK\3\2\2\2MN\3\2\2\2NL\3\2\2\2NO\3\2\2\2O \3\2\2") + buf.write("\2PR\7\17\2\2QP\3\2\2\2QR\3\2\2\2RS\3\2\2\2ST\7\f\2\2") + buf.write("TU\3\2\2\2UV\b\21\2\2V\"\3\2\2\2WY\t\4\2\2XW\3\2\2\2Y") + buf.write("Z\3\2\2\2ZX\3\2\2\2Z[\3\2\2\2[\\\3\2\2\2\\]\b\22\2\2]") + buf.write("$\3\2\2\2\7\2INQZ\3\b\2\2") + return buf.getvalue() + + +class ExprLexer(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + T__0 = 1 + T__1 = 2 + T__2 = 3 + T__3 = 4 + T__4 = 5 + T__5 = 6 + T__6 = 7 + T__7 = 8 + MUL = 9 + DIV = 10 + ADD = 11 + SUB = 12 + RETURN = 13 + ID = 14 + INT = 15 + NEWLINE = 16 + WS = 17 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + "'def'", "'('", "','", "')'", "'{'", "'}'", "';'", "'='", "'*'", + "'/'", "'+'", "'-'", "'return'" ] + + symbolicNames = [ "", + "MUL", "DIV", "ADD", "SUB", "RETURN", "ID", "INT", "NEWLINE", + "WS" ] + + ruleNames = [ "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", + "T__7", "MUL", "DIV", "ADD", "SUB", "RETURN", "ID", "INT", + "NEWLINE", "WS" ] + + grammarFileName = "Expr.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.7.2") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/runtime/Python3/test/expr/ExprParser.py b/runtime/Python3/test/expr/ExprParser.py new file mode 100644 index 000000000..598c778d1 --- /dev/null +++ b/runtime/Python3/test/expr/ExprParser.py @@ -0,0 +1,658 @@ +# Generated from expr/Expr.g4 by ANTLR 4.7.2 +# encoding: utf-8 +from antlr4 import * +from io import StringIO +from typing.io import TextIO +import sys + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\23") + buf.write("S\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b") + buf.write("\t\b\3\2\6\2\22\n\2\r\2\16\2\23\3\3\3\3\3\3\3\3\3\3\3") + buf.write("\3\7\3\34\n\3\f\3\16\3\37\13\3\3\3\3\3\3\3\3\4\3\4\6\4") + buf.write("&\n\4\r\4\16\4\'\3\4\3\4\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3") + buf.write("\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6;\n\6\3\7\3\7\3\7\3") + buf.write("\7\3\7\3\7\3\7\3\7\3\7\7\7F\n\7\f\7\16\7I\13\7\3\b\3\b") + buf.write("\3\b\3\b\3\b\3\b\5\bQ\n\b\3\b\2\3\f\t\2\4\6\b\n\f\16\2") + buf.write("\4\3\2\13\f\3\2\r\16\2U\2\21\3\2\2\2\4\25\3\2\2\2\6#\3") + buf.write("\2\2\2\b+\3\2\2\2\n:\3\2\2\2\f<\3\2\2\2\16P\3\2\2\2\20") + buf.write("\22\5\4\3\2\21\20\3\2\2\2\22\23\3\2\2\2\23\21\3\2\2\2") + buf.write("\23\24\3\2\2\2\24\3\3\2\2\2\25\26\7\3\2\2\26\27\7\20\2") + buf.write("\2\27\30\7\4\2\2\30\35\5\b\5\2\31\32\7\5\2\2\32\34\5\b") + buf.write("\5\2\33\31\3\2\2\2\34\37\3\2\2\2\35\33\3\2\2\2\35\36\3") + buf.write("\2\2\2\36 \3\2\2\2\37\35\3\2\2\2 !\7\6\2\2!\"\5\6\4\2") + buf.write("\"\5\3\2\2\2#%\7\7\2\2$&\5\n\6\2%$\3\2\2\2&\'\3\2\2\2") + buf.write("\'%\3\2\2\2\'(\3\2\2\2()\3\2\2\2)*\7\b\2\2*\7\3\2\2\2") + buf.write("+,\7\20\2\2,\t\3\2\2\2-.\5\f\7\2./\7\t\2\2/;\3\2\2\2\60") + buf.write("\61\7\20\2\2\61\62\7\n\2\2\62\63\5\f\7\2\63\64\7\t\2\2") + buf.write("\64;\3\2\2\2\65\66\7\17\2\2\66\67\5\f\7\2\678\7\t\2\2") + buf.write("8;\3\2\2\29;\7\t\2\2:-\3\2\2\2:\60\3\2\2\2:\65\3\2\2\2") + buf.write(":9\3\2\2\2;\13\3\2\2\2<=\b\7\1\2=>\5\16\b\2>G\3\2\2\2") + buf.write("?@\f\5\2\2@A\t\2\2\2AF\5\f\7\6BC\f\4\2\2CD\t\3\2\2DF\5") + buf.write("\f\7\5E?\3\2\2\2EB\3\2\2\2FI\3\2\2\2GE\3\2\2\2GH\3\2\2") + buf.write("\2H\r\3\2\2\2IG\3\2\2\2JQ\7\21\2\2KQ\7\20\2\2LM\7\4\2") + buf.write("\2MN\5\f\7\2NO\7\6\2\2OQ\3\2\2\2PJ\3\2\2\2PK\3\2\2\2P") + buf.write("L\3\2\2\2Q\17\3\2\2\2\t\23\35\':EGP") + return buf.getvalue() + + +class ExprParser ( Parser ): + + grammarFileName = "Expr.g4" + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + sharedContextCache = PredictionContextCache() + + literalNames = [ "", "'def'", "'('", "','", "')'", "'{'", "'}'", + "';'", "'='", "'*'", "'/'", "'+'", "'-'", "'return'" ] + + symbolicNames = [ "", "", "", "", + "", "", "", "", + "", "MUL", "DIV", "ADD", "SUB", "RETURN", + "ID", "INT", "NEWLINE", "WS" ] + + RULE_prog = 0 + RULE_func = 1 + RULE_body = 2 + RULE_arg = 3 + RULE_stat = 4 + RULE_expr = 5 + RULE_primary = 6 + + ruleNames = [ "prog", "func", "body", "arg", "stat", "expr", "primary" ] + + EOF = Token.EOF + T__0=1 + T__1=2 + T__2=3 + T__3=4 + T__4=5 + T__5=6 + T__6=7 + T__7=8 + MUL=9 + DIV=10 + ADD=11 + SUB=12 + RETURN=13 + ID=14 + INT=15 + NEWLINE=16 + WS=17 + + def __init__(self, input:TokenStream, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.7.2") + self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache) + self._predicates = None + + + + class ProgContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def func(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(ExprParser.FuncContext) + else: + return self.getTypedRuleContext(ExprParser.FuncContext,i) + + + def getRuleIndex(self): + return ExprParser.RULE_prog + + + + + def prog(self): + + localctx = ExprParser.ProgContext(self, self._ctx, self.state) + self.enterRule(localctx, 0, self.RULE_prog) + self._la = 0 # Token type + try: + self.enterOuterAlt(localctx, 1) + self.state = 15 + self._errHandler.sync(self) + _la = self._input.LA(1) + while True: + self.state = 14 + self.func() + self.state = 17 + self._errHandler.sync(self) + _la = self._input.LA(1) + if not (_la==ExprParser.T__0): + break + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class FuncContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def ID(self): + return self.getToken(ExprParser.ID, 0) + + def arg(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(ExprParser.ArgContext) + else: + return self.getTypedRuleContext(ExprParser.ArgContext,i) + + + def body(self): + return self.getTypedRuleContext(ExprParser.BodyContext,0) + + + def getRuleIndex(self): + return ExprParser.RULE_func + + + + + def func(self): + + localctx = ExprParser.FuncContext(self, self._ctx, self.state) + self.enterRule(localctx, 2, self.RULE_func) + self._la = 0 # Token type + try: + self.enterOuterAlt(localctx, 1) + self.state = 19 + self.match(ExprParser.T__0) + self.state = 20 + self.match(ExprParser.ID) + self.state = 21 + self.match(ExprParser.T__1) + self.state = 22 + self.arg() + self.state = 27 + self._errHandler.sync(self) + _la = self._input.LA(1) + while _la==ExprParser.T__2: + self.state = 23 + self.match(ExprParser.T__2) + self.state = 24 + self.arg() + self.state = 29 + self._errHandler.sync(self) + _la = self._input.LA(1) + + self.state = 30 + self.match(ExprParser.T__3) + self.state = 31 + self.body() + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class BodyContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def stat(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(ExprParser.StatContext) + else: + return self.getTypedRuleContext(ExprParser.StatContext,i) + + + def getRuleIndex(self): + return ExprParser.RULE_body + + + + + def body(self): + + localctx = ExprParser.BodyContext(self, self._ctx, self.state) + self.enterRule(localctx, 4, self.RULE_body) + self._la = 0 # Token type + try: + self.enterOuterAlt(localctx, 1) + self.state = 33 + self.match(ExprParser.T__4) + self.state = 35 + self._errHandler.sync(self) + _la = self._input.LA(1) + while True: + self.state = 34 + self.stat() + self.state = 37 + self._errHandler.sync(self) + _la = self._input.LA(1) + if not ((((_la) & ~0x3f) == 0 and ((1 << _la) & ((1 << ExprParser.T__1) | (1 << ExprParser.T__6) | (1 << ExprParser.RETURN) | (1 << ExprParser.ID) | (1 << ExprParser.INT))) != 0)): + break + + self.state = 39 + self.match(ExprParser.T__5) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class ArgContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def ID(self): + return self.getToken(ExprParser.ID, 0) + + def getRuleIndex(self): + return ExprParser.RULE_arg + + + + + def arg(self): + + localctx = ExprParser.ArgContext(self, self._ctx, self.state) + self.enterRule(localctx, 6, self.RULE_arg) + try: + self.enterOuterAlt(localctx, 1) + self.state = 41 + self.match(ExprParser.ID) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class StatContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + + def getRuleIndex(self): + return ExprParser.RULE_stat + + + def copyFrom(self, ctx:ParserRuleContext): + super().copyFrom(ctx) + + + + class RetContext(StatContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.StatContext + super().__init__(parser) + self.copyFrom(ctx) + + def RETURN(self): + return self.getToken(ExprParser.RETURN, 0) + def expr(self): + return self.getTypedRuleContext(ExprParser.ExprContext,0) + + + + class BlankContext(StatContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.StatContext + super().__init__(parser) + self.copyFrom(ctx) + + + + class PrintExprContext(StatContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.StatContext + super().__init__(parser) + self.copyFrom(ctx) + + def expr(self): + return self.getTypedRuleContext(ExprParser.ExprContext,0) + + + + class AssignContext(StatContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.StatContext + super().__init__(parser) + self.copyFrom(ctx) + + def ID(self): + return self.getToken(ExprParser.ID, 0) + def expr(self): + return self.getTypedRuleContext(ExprParser.ExprContext,0) + + + + + def stat(self): + + localctx = ExprParser.StatContext(self, self._ctx, self.state) + self.enterRule(localctx, 8, self.RULE_stat) + try: + self.state = 56 + self._errHandler.sync(self) + la_ = self._interp.adaptivePredict(self._input,3,self._ctx) + if la_ == 1: + localctx = ExprParser.PrintExprContext(self, localctx) + self.enterOuterAlt(localctx, 1) + self.state = 43 + self.expr(0) + self.state = 44 + self.match(ExprParser.T__6) + pass + + elif la_ == 2: + localctx = ExprParser.AssignContext(self, localctx) + self.enterOuterAlt(localctx, 2) + self.state = 46 + self.match(ExprParser.ID) + self.state = 47 + self.match(ExprParser.T__7) + self.state = 48 + self.expr(0) + self.state = 49 + self.match(ExprParser.T__6) + pass + + elif la_ == 3: + localctx = ExprParser.RetContext(self, localctx) + self.enterOuterAlt(localctx, 3) + self.state = 51 + self.match(ExprParser.RETURN) + self.state = 52 + self.expr(0) + self.state = 53 + self.match(ExprParser.T__6) + pass + + elif la_ == 4: + localctx = ExprParser.BlankContext(self, localctx) + self.enterOuterAlt(localctx, 4) + self.state = 55 + self.match(ExprParser.T__6) + pass + + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + class ExprContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + + def getRuleIndex(self): + return ExprParser.RULE_expr + + + def copyFrom(self, ctx:ParserRuleContext): + super().copyFrom(ctx) + + + class PrimContext(ExprContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.ExprContext + super().__init__(parser) + self.copyFrom(ctx) + + def primary(self): + return self.getTypedRuleContext(ExprParser.PrimaryContext,0) + + + + class MulDivContext(ExprContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.ExprContext + super().__init__(parser) + self.copyFrom(ctx) + + def expr(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(ExprParser.ExprContext) + else: + return self.getTypedRuleContext(ExprParser.ExprContext,i) + + def MUL(self): + return self.getToken(ExprParser.MUL, 0) + def DIV(self): + return self.getToken(ExprParser.DIV, 0) + + + class AddSubContext(ExprContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.ExprContext + super().__init__(parser) + self.copyFrom(ctx) + + def expr(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(ExprParser.ExprContext) + else: + return self.getTypedRuleContext(ExprParser.ExprContext,i) + + def ADD(self): + return self.getToken(ExprParser.ADD, 0) + def SUB(self): + return self.getToken(ExprParser.SUB, 0) + + + + def expr(self, _p:int=0): + _parentctx = self._ctx + _parentState = self.state + localctx = ExprParser.ExprContext(self, self._ctx, _parentState) + _prevctx = localctx + _startState = 10 + self.enterRecursionRule(localctx, 10, self.RULE_expr, _p) + self._la = 0 # Token type + try: + self.enterOuterAlt(localctx, 1) + localctx = ExprParser.PrimContext(self, localctx) + self._ctx = localctx + _prevctx = localctx + + self.state = 59 + self.primary() + self._ctx.stop = self._input.LT(-1) + self.state = 69 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,5,self._ctx) + while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: + if _alt==1: + if self._parseListeners is not None: + self.triggerExitRuleEvent() + _prevctx = localctx + self.state = 67 + self._errHandler.sync(self) + la_ = self._interp.adaptivePredict(self._input,4,self._ctx) + if la_ == 1: + localctx = ExprParser.MulDivContext(self, ExprParser.ExprContext(self, _parentctx, _parentState)) + self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) + self.state = 61 + if not self.precpred(self._ctx, 3): + from antlr4.error.Errors import FailedPredicateException + raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") + self.state = 62 + _la = self._input.LA(1) + if not(_la==ExprParser.MUL or _la==ExprParser.DIV): + self._errHandler.recoverInline(self) + else: + self._errHandler.reportMatch(self) + self.consume() + self.state = 63 + self.expr(4) + pass + + elif la_ == 2: + localctx = ExprParser.AddSubContext(self, ExprParser.ExprContext(self, _parentctx, _parentState)) + self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) + self.state = 64 + if not self.precpred(self._ctx, 2): + from antlr4.error.Errors import FailedPredicateException + raise FailedPredicateException(self, "self.precpred(self._ctx, 2)") + self.state = 65 + _la = self._input.LA(1) + if not(_la==ExprParser.ADD or _la==ExprParser.SUB): + self._errHandler.recoverInline(self) + else: + self._errHandler.reportMatch(self) + self.consume() + self.state = 66 + self.expr(3) + pass + + + self.state = 71 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,5,self._ctx) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.unrollRecursionContexts(_parentctx) + return localctx + + class PrimaryContext(ParserRuleContext): + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + + def getRuleIndex(self): + return ExprParser.RULE_primary + + + def copyFrom(self, ctx:ParserRuleContext): + super().copyFrom(ctx) + + + + class ParensContext(PrimaryContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.PrimaryContext + super().__init__(parser) + self.copyFrom(ctx) + + def expr(self): + return self.getTypedRuleContext(ExprParser.ExprContext,0) + + + + class IdContext(PrimaryContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.PrimaryContext + super().__init__(parser) + self.copyFrom(ctx) + + def ID(self): + return self.getToken(ExprParser.ID, 0) + + + class IntContext(PrimaryContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a ExprParser.PrimaryContext + super().__init__(parser) + self.copyFrom(ctx) + + def INT(self): + return self.getToken(ExprParser.INT, 0) + + + + def primary(self): + + localctx = ExprParser.PrimaryContext(self, self._ctx, self.state) + self.enterRule(localctx, 12, self.RULE_primary) + try: + self.state = 78 + self._errHandler.sync(self) + token = self._input.LA(1) + if token in [ExprParser.INT]: + localctx = ExprParser.IntContext(self, localctx) + self.enterOuterAlt(localctx, 1) + self.state = 72 + self.match(ExprParser.INT) + pass + elif token in [ExprParser.ID]: + localctx = ExprParser.IdContext(self, localctx) + self.enterOuterAlt(localctx, 2) + self.state = 73 + self.match(ExprParser.ID) + pass + elif token in [ExprParser.T__1]: + localctx = ExprParser.ParensContext(self, localctx) + self.enterOuterAlt(localctx, 3) + self.state = 74 + self.match(ExprParser.T__1) + self.state = 75 + self.expr(0) + self.state = 76 + self.match(ExprParser.T__3) + pass + else: + raise NoViableAltException(self) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + + def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int): + if self._predicates == None: + self._predicates = dict() + self._predicates[5] = self.expr_sempred + pred = self._predicates.get(ruleIndex, None) + if pred is None: + raise Exception("No predicate with index:" + str(ruleIndex)) + else: + return pred(localctx, predIndex) + + def expr_sempred(self, localctx:ExprContext, predIndex:int): + if predIndex == 0: + return self.precpred(self._ctx, 3) + + + if predIndex == 1: + return self.precpred(self._ctx, 2) + + + + + diff --git a/runtime/Python3/test/run.py b/runtime/Python3/test/run.py new file mode 100644 index 000000000..5aad7896c --- /dev/null +++ b/runtime/Python3/test/run.py @@ -0,0 +1,8 @@ +import sys +import os +src_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'src') +sys.path.insert(0,src_path) +from TestTokenStreamRewriter import TestTokenStreamRewriter +from xpathtest import XPathTest +import unittest +unittest.main() \ No newline at end of file diff --git a/runtime/Python3/test/xpathtest.py b/runtime/Python3/test/xpathtest.py new file mode 100644 index 000000000..03b6101a9 --- /dev/null +++ b/runtime/Python3/test/xpathtest.py @@ -0,0 +1,89 @@ +import antlr4 +from antlr4 import InputStream, CommonTokenStream, TerminalNode +from antlr4.xpath.XPath import XPath +import unittest +from expr.ExprParser import ExprParser +from expr.ExprLexer import ExprLexer + +def tokenToString(token, ruleNames): + if isinstance(token, TerminalNode): + return str(token) + else: + return ruleNames[token.getRuleIndex()] + +class XPathTest(unittest.TestCase): + def setUp(self): + self.input_stream = InputStream( + "def f(x,y) { x = 3+4; y; ; }\n" + "def g(x) { return 1+2*x; }\n" + ) + + # Create the Token Stream + self.lexer = ExprLexer(self.input_stream) + self.stream = CommonTokenStream(self.lexer) + self.stream.fill() + + # Create the parser and expression parse tree + self.parser = ExprParser(self.stream) + self.tree = self.parser.prog() + + def testValidPaths(self): + valid_paths = [ + "/prog/func", # all funcs under prog at root + "/prog/*", # all children of prog at root + "/*/func", # all func kids of any root node + "prog", # prog must be root node + "/prog", # prog must be root node + "/*", # any root + "*", # any root + "//ID", # any ID in tree + "//expr/primary/ID", # any ID child of a primary under any expr + "//body//ID", # any ID under a body + "//'return'", # any 'return' literal in tree, matched by literal name + "//RETURN", # any 'return' literal in tree, matched by symbolic name + "//primary/*", # all kids of any primary + "//func/*/stat", # all stat nodes grandkids of any func node + "/prog/func/'def'", # all def literal kids of func kid of prog + "//stat/';'", # all ';' under any stat node + "//expr/primary/!ID",# anything but ID under primary under any expr node + "//expr/!primary", # anything but primary under any expr node + "//!*", # nothing anywhere + "/!*", # nothing at root + "//expr//ID" # any ID under any expression (tests antlr/antlr4#370) + ] + + expected_results = [ + "[func, func]", + "[func, func]", + "[func, func]", + "[prog]", + "[prog]", + "[prog]", + "[prog]", + "[f, x, y, x, y, g, x, x]", + "[y, x]", + "[x, y, x]", + "[return]", + "[return]", + "[3, 4, y, 1, 2, x]", + "[stat, stat, stat, stat]", + "[def, def]", + "[;, ;, ;, ;]", + "[3, 4, 1, 2]", + "[expr, expr, expr, expr, expr, expr]", + "[]", + "[]", + "[y, x]", + ] + + for path, expected in zip(valid_paths, expected_results): + # Build test string + res = XPath.findAll(self.tree, path, self.parser) + res_str = ", ".join([tokenToString(token, self.parser.ruleNames) for token in res]) + res_str = "[%s]" % res_str + + # Test against expected output + self.assertEqual(res_str, expected, "Failed test %s" % path) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tool-testsuite/test/org/antlr/v4/misc/UtilsTest.java b/tool-testsuite/test/org/antlr/v4/misc/UtilsTest.java new file mode 100644 index 000000000..f9c9b5d50 --- /dev/null +++ b/tool-testsuite/test/org/antlr/v4/misc/UtilsTest.java @@ -0,0 +1,129 @@ +package org.antlr.v4.misc; + +import org.antlr.runtime.Token; +import org.antlr.v4.tool.ast.GrammarAST; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; + +public class UtilsTest { + + @Test + public void testStripFileExtension() { + Assert.assertNull(Utils.stripFileExtension(null)); + Assert.assertEquals("foo", Utils.stripFileExtension("foo")); + Assert.assertEquals("foo", Utils.stripFileExtension("foo.txt")); + } + + @Test + public void testJoin() { + Assert.assertEquals("foobbar", + Utils.join(new String[]{"foo", "bar"}, "b")); + Assert.assertEquals("foo,bar", + Utils.join(new String[]{"foo", "bar"}, ",")); + } + + @Test + public void testSortLinesInString() { + Assert.assertEquals("bar\nbaz\nfoo\n", + Utils.sortLinesInString("foo\nbar\nbaz")); + } + + @Test + public void testNodesToStrings() { + ArrayList values = new ArrayList<>(); + values.add(new GrammarAST(Token.EOR_TOKEN_TYPE)); + values.add(new GrammarAST(Token.DOWN)); + values.add(new GrammarAST(Token.UP)); + + Assert.assertNull(Utils.nodesToStrings(null)); + Assert.assertNotNull(Utils.nodesToStrings(values)); + } + + @Test + public void testCapitalize() { + Assert.assertEquals("Foo", Utils.capitalize("foo")); + } + + @Test + public void testDecapitalize() { + Assert.assertEquals("fOO", Utils.decapitalize("FOO")); + } + + @Test + public void testSelect() { + ArrayList strings = new ArrayList<>(); + strings.add("foo"); + strings.add("bar"); + + Utils.Func1 func1 = new Utils.Func1() { + @Override + public Object exec(Object arg1) { + return "baz"; + } + }; + + ArrayList retval = new ArrayList<>(); + retval.add("baz"); + retval.add("baz"); + + Assert.assertEquals(retval, Utils.select(strings, func1)); + Assert.assertNull(Utils.select(null, null)); + } + + @Test + public void testFind() { + ArrayList strings = new ArrayList<>(); + strings.add("foo"); + strings.add("bar"); + Assert.assertEquals("foo", Utils.find(strings, String.class)); + + Assert.assertNull(Utils.find(new ArrayList<>(), String.class)); + } + + @Test + public void testIndexOf() { + ArrayList strings = new ArrayList<>(); + strings.add("foo"); + strings.add("bar"); + Utils.Filter filter = new Utils.Filter() { + @Override + public boolean select(Object o) { + return true; + } + }; + Assert.assertEquals(0, Utils.indexOf(strings, filter)); + Assert.assertEquals(-1, Utils.indexOf(new ArrayList<>(), null)); + } + + @Test + public void testLastIndexOf() { + ArrayList strings = new ArrayList<>(); + strings.add("foo"); + strings.add("bar"); + Utils.Filter filter = new Utils.Filter() { + @Override + public boolean select(Object o) { + return true; + } + }; + Assert.assertEquals(1, Utils.lastIndexOf(strings, filter)); + Assert.assertEquals(-1, Utils.lastIndexOf(new ArrayList<>(), null)); + } + + @Test + public void testSetSize() { + ArrayList strings = new ArrayList<>(); + strings.add("foo"); + strings.add("bar"); + strings.add("baz"); + Assert.assertEquals(3, strings.size()); + + Utils.setSize(strings, 2); + Assert.assertEquals(2, strings.size()); + + Utils.setSize(strings, 4); + Assert.assertEquals(4, strings.size()); + } +} diff --git a/tool-testsuite/test/org/antlr/v4/test/tool/CharSupportTest.java b/tool-testsuite/test/org/antlr/v4/test/tool/CharSupportTest.java new file mode 100644 index 000000000..e9ceab2ae --- /dev/null +++ b/tool-testsuite/test/org/antlr/v4/test/tool/CharSupportTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2012-2019 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.tool; + +import org.antlr.v4.misc.CharSupport; +import org.antlr.v4.runtime.misc.IntervalSet; +import org.junit.Assert; +import org.junit.Test; + +public class CharSupportTest { + + @Test + public void testGetANTLRCharLiteralForChar() { + Assert.assertEquals("''", + CharSupport.getANTLRCharLiteralForChar(-1)); + Assert.assertEquals("'\\n'", + CharSupport.getANTLRCharLiteralForChar('\n')); + Assert.assertEquals("'\\\\'", + CharSupport.getANTLRCharLiteralForChar('\\')); + Assert.assertEquals("'\\''", + CharSupport.getANTLRCharLiteralForChar('\'')); + Assert.assertEquals("'b'", + CharSupport.getANTLRCharLiteralForChar('b')); + Assert.assertEquals("'\\uFFFF'", + CharSupport.getANTLRCharLiteralForChar(0xFFFF)); + Assert.assertEquals("'\\u{10FFFF}'", + CharSupport.getANTLRCharLiteralForChar(0x10FFFF)); + } + + @Test + public void testGetCharValueFromGrammarCharLiteral() { + Assert.assertEquals(-1, + CharSupport.getCharValueFromGrammarCharLiteral(null)); + Assert.assertEquals(-1, + CharSupport.getCharValueFromGrammarCharLiteral("")); + Assert.assertEquals(-1, + CharSupport.getCharValueFromGrammarCharLiteral("b")); + Assert.assertEquals(111, + CharSupport.getCharValueFromGrammarCharLiteral("foo")); + } + + @Test + public void testGetStringFromGrammarStringLiteral() { + Assert.assertNull(CharSupport + .getStringFromGrammarStringLiteral("foo\\u{bbb")); + Assert.assertNull(CharSupport + .getStringFromGrammarStringLiteral("foo\\u{[]bb")); + Assert.assertNull(CharSupport + .getStringFromGrammarStringLiteral("foo\\u[]bb")); + Assert.assertNull(CharSupport + .getStringFromGrammarStringLiteral("foo\\ubb")); + + Assert.assertEquals("oo»b", CharSupport + .getStringFromGrammarStringLiteral("foo\\u{bb}bb")); + } + + @Test + public void testGetCharValueFromCharInGrammarLiteral() { + Assert.assertEquals(102, + CharSupport.getCharValueFromCharInGrammarLiteral("f")); + + Assert.assertEquals(-1, + CharSupport.getCharValueFromCharInGrammarLiteral("\' ")); + Assert.assertEquals(-1, + CharSupport.getCharValueFromCharInGrammarLiteral("\\ ")); + Assert.assertEquals(39, + CharSupport.getCharValueFromCharInGrammarLiteral("\\\'")); + Assert.assertEquals(10, + CharSupport.getCharValueFromCharInGrammarLiteral("\\n")); + + Assert.assertEquals(-1, + CharSupport.getCharValueFromCharInGrammarLiteral("foobar")); + Assert.assertEquals(4660, + CharSupport.getCharValueFromCharInGrammarLiteral("\\u1234")); + Assert.assertEquals(18, + CharSupport.getCharValueFromCharInGrammarLiteral("\\u{12}")); + + Assert.assertEquals(-1, + CharSupport.getCharValueFromCharInGrammarLiteral("\\u{")); + Assert.assertEquals(-1, + CharSupport.getCharValueFromCharInGrammarLiteral("foo")); + } + + @Test + public void testParseHexValue() { + Assert.assertEquals(-1, CharSupport.parseHexValue("foobar", -1, 3)); + Assert.assertEquals(-1, CharSupport.parseHexValue("foobar", 1, -1)); + Assert.assertEquals(-1, CharSupport.parseHexValue("foobar", 1, 3)); + Assert.assertEquals(35, CharSupport.parseHexValue("123456", 1, 3)); + } + + @Test + public void testCapitalize() { + Assert.assertEquals("Foo", CharSupport.capitalize("foo")); + } + + @Test + public void testGetIntervalSetEscapedString() { + Assert.assertEquals("", + CharSupport.getIntervalSetEscapedString(new IntervalSet())); + Assert.assertEquals("'\\u0000'", + CharSupport.getIntervalSetEscapedString(new IntervalSet(0))); + Assert.assertEquals("'\\u0001'..'\\u0003'", + CharSupport.getIntervalSetEscapedString(new IntervalSet(3, 1, 2))); + } + + @Test + public void testGetRangeEscapedString() { + Assert.assertEquals("'\\u0002'..'\\u0004'", + CharSupport.getRangeEscapedString(2, 4)); + Assert.assertEquals("'\\u0002'", + CharSupport.getRangeEscapedString(2, 2)); + } +} diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/PHP/PHP.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/PHP/PHP.stg new file mode 100644 index 000000000..447e12657 --- /dev/null +++ b/tool/resources/org/antlr/v4/tool/templates/codegen/PHP/PHP.stg @@ -0,0 +1,1233 @@ +/* + * [The "BSD license"] + * Copyright (c) 2012-2016 Terence Parr + * Copyright (c) 2012-2016 Sam Harwell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +phpTypeInitMap ::= [ + "int":"0", + "long":"0", + "float":"0.0", + "double":"0.0", + "boolean":"false", + default:"null" +] + +// args must be , + +ParserFile(file, parser, namedActions, contextSuperClass) ::= << + + +>> + +ListenerFile(file, header, namedActions) ::= << + + +namespace ; + +
+use Antlr\\Antlr4\\Runtime\\Tree\\ParseTreeListener; + +/** + * This interface defines a complete listener for a parse tree produced by + * {@see }. + */ +interface Listener extends ParseTreeListener { + + * Enter a parse tree produced by the `` + * labeled alternative in {@see ::()\}. + + * Enter a parse tree produced by {@see ::()\}. + + * @param $context The parse tree. + */ +public function enter(Context\\Context $context) : void; +/** + + * Exit a parse tree produced by the `` labeled alternative + * in {@see ::()\}. + + * Exit a parse tree produced by {@see ::()\}. + + * @param $context The parse tree. + */ +public function exit(Context\\Context $context) : void;}; separator="\n"> +} +>> + +BaseListenerFile(file, header, namedActions) ::= << + + +namespace ; + +
+ +use Antlr\\Antlr4\\Runtime\\ParserRuleContext; +use Antlr\\Antlr4\\Runtime\\Tree\\ErrorNode; +use Antlr\\Antlr4\\Runtime\\Tree\\TerminalNode; + +/** + * This class provides an empty implementation of {@see Listener}, + * which can be extended to create a listener which only needs to handle a subset + * of the available methods. + */ +class BaseListener implements Listener +{ + (Context\\Context $context) : void {\} + +/** + * {@inheritdoc\} + * + * The default implementation does nothing. + */ +public function exit(Context\\Context $context) : void {\}}; separator="\n"> + + /** + * {@inheritdoc\} + * + * The default implementation does nothing. + */ + public function enterEveryRule(ParserRuleContext $context) : void {} + + /** + * {@inheritdoc\} + * + * The default implementation does nothing. + */ + public function exitEveryRule(ParserRuleContext $context) : void {} + + /** + * {@inheritdoc\} + * + * The default implementation does nothing. + */ + public function visitTerminal(TerminalNode $node) : void {} + + /** + * {@inheritdoc\} + * + * The default implementation does nothing. + */ + public function visitErrorNode(ErrorNode $node) : void {} +} +>> + +VisitorFile(file, header, namedActions) ::= << + + +namespace ; + + +
+use Antlr\\Antlr4\\Runtime\\Tree\\ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced by {@see }. + */ +interface Visitor extends ParseTreeVisitor +{ + + * Visit a parse tree produced by the `` labeled alternative + * in {@see ::()\}. + + * Visit a parse tree produced by {@see ::()\}. + + * + * @param Context\\Context $context The parse tree. + * + * @return mixed The visitor result. + */ +public function visit(Context\\Context $context);}; separator="\n\n"> +} +>> + +BaseVisitorFile(file, header, namedActions) ::= << + + +namespace ; + +
+use Antlr\\Antlr4\\Runtime\\Tree\\AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@see Visitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + */ +class BaseVisitor extends AbstractParseTreeVisitor implements Visitor +{ + (Context\\Context $context) +{ + return $this->visitChildren($context); +\}}; separator="\n\n"> +} +>> + +fileHeader(grammarFileName, ANTLRVersion) ::= << +\ by ANTLR + */ + +>> +Parser(parser, funcs, atn, sempredFuncs, superClass) ::= << + +>> + +Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass) ::= << +namespace { + + use Antlr\\Antlr4\\Runtime\\Atn\\ATN; + use Antlr\\Antlr4\\Runtime\\Atn\\ATNDeserializer; + use Antlr\\Antlr4\\Runtime\\Atn\\ParserATNSimulator; + use Antlr\\Antlr4\\Runtime\\Dfa\\DFA; + use Antlr\\Antlr4\\Runtime\\Error\\Exceptions\\FailedPredicateException; + use Antlr\\Antlr4\\Runtime\\Error\\Exceptions\\NoViableAltException; + use Antlr\\Antlr4\\Runtime\\PredictionContexts\\PredictionContextCache; + use Antlr\\Antlr4\\Runtime\\Error\\Exceptions\\RecognitionException; + use Antlr\\Antlr4\\Runtime\\RuleContext; + use Antlr\\Antlr4\\Runtime\\Token; + use Antlr\\Antlr4\\Runtime\\TokenStream; + use Antlr\\Antlr4\\Runtime\\Vocabulary; + use Antlr\\Antlr4\\Runtime\\VocabularyImpl; + use Antlr\\Antlr4\\Runtime\\RuntimeMetaData; + use Antlr\\Antlr4\\Runtime\\Parser; + + + final class extends + { + + public const = }; separator=", ", wrap, anchor>; + + + public const = }; separator=", ", wrap, anchor>; + + /** + * @var array\ + */ + public const RULE_NAMES = [ + '}; separator=", ", wrap, anchor> + ]; + + + + + protected static $atn; + protected static $decisionToDFA; + protected static $sharedContextCache; + + + + + + + + + private static function initialize() : void + { + if (self::$atn !== null) { + return; + } + + RuntimeMetaData::checkVersion('', RuntimeMetaData::VERSION); + + $atn = (new ATNDeserializer())->deserialize(self::SERIALIZED_ATN); + + $decisionToDFA = []; + for ($i = 0, $count = $atn->getNumberOfDecisions(); $i \< $count; $i++) { + $decisionToDFA[] = new DFA($atn->getDecisionState($i), $i); + } + + self::$atn = $atn; + self::$decisionToDFA = $decisionToDFA; + self::$sharedContextCache = new PredictionContextCache(); + } + + public function getGrammarFileName() : string + { + return ""; + } + + public function getRuleNames() : array + { + return self::RULE_NAMES; + } + + public function getSerializedATN() : string + { + return self::SERIALIZED_ATN; + } + + public function getATN() : ATN + { + return self::$atn; + } + + public function getVocabulary() : Vocabulary + { + static $vocabulary; + + return $vocabulary = $vocabulary ?? new VocabularyImpl(self::LITERAL_NAMES, self::SYMBOLIC_NAMES); + } + + + + + + + public function sempred(?RuleContext $localContext, int $ruleIndex, int $predicateIndex) : bool + { + switch ($ruleIndex) { + : + return $this->sempred($localContext, $predicateIndex);}; separator="\n\n"> + + default: + return true; + } + } + + + + } +} + +namespace \\Context { + use Antlr\\Antlr4\\Runtime\\ParserRuleContext; + use Antlr\\Antlr4\\Runtime\\Token; + use Antlr\\Antlr4\\Runtime\\Tree\\ParseTreeVisitor; + use Antlr\\Antlr4\\Runtime\\Tree\\TerminalNode; + use Antlr\\Antlr4\\Runtime\\Tree\\ParseTreeListener; + use \\; + use \\Visitor; + use \\Listener; + + + + +}; separator="\n\n"> }; separator="\n\n"> +} +>> + +vocabulary(literalNames, symbolicNames) ::= << +/** + * @var array\ + */ +private const LITERAL_NAMES = [ + }; null="null", separator=", ", wrap, anchor> +]; + +/** + * @var array\ + */ +private const SYMBOLIC_NAMES = [ + }; null="null", separator=", ", wrap, anchor> +]; +>> + +dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= << + + +public function action(?RuleContext $localContext, int $ruleIndex, int $actionIndex) : void +{ + switch ($ruleIndex) { + : + $this->action($localContext, $actionIndex); + break;}; separator="\n\n"> + } +} + + + + + +public function sempred(?RuleContext $localContext, int $ruleIndex, int $predicateIndex) : bool +{ + switch ($ruleIndex) { + : + return $this->sempred($localContext, $predicateIndex);}; separator="\n\n"> + } + + return true; +} + + +>> + +parser_ctor(p) ::= << +public function __construct(TokenStream $input) +{ + parent::__construct($input); + + self::initialize(); + + $this->interp = new ParserATNSimulator($this, self::$atn, self::$decisionToDFA, self::$sharedContextCache); +} +>> + +/** + * This generates a private method since the actionIndex is generated, making + * an overriding implementation impossible to maintain. + */ +RuleActionFunction(r, actions) ::= << +private function action(? $localContext, int $actionIndex) : void +{ + switch ($actionIndex) { + : + + + break;}; separator="\n\n"> + } +} +>> + +/** + * This generates a private method since the predicateIndex is generated, making + * an overriding implementation impossible to maintain. + */ +RuleSempredFunction(r, actions) ::= << +private function sempred(?Context\\ $localContext, int $predicateIndex) : bool +{ + switch ($predicateIndex) { + : + return ;}; separator="\n\n"> + } + + return true; +} +>> + +RuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,exceptions,postamble) ::= << +/** + * @throws RecognitionException + */ + }>public function () : Context\\ +{ + $localContext = new Context\\($this->ctx, $this->getState()}>); + + $this->enterRule($localContext, , self::RULE_); + + + + try { + + + + } catch (RecognitionException $exception) { + $localContext->exception = $exception; + $this->errorHandler->reportError($this, $exception); + $this->errorHandler->recover($this, $exception); + } finally { + + $this->exitRule(); + } + + return $localContext; +} +>> + +LeftRecursiveRuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble) ::= << +/** + * @throws RecognitionException + */ + }>public function () : Context\\ +{ + return $this->recursive(0}>); +} + +/** + * @throws RecognitionException + */ +private function recursive(int $precedence}>) : Context\\ +{ + $parentContext = $this->ctx; + $parentState = $this->getState(); + $localContext = new Context\\($this->ctx, $parentState}>); + $previousContext = $localContext; + $startState = ; + $this->enterRecursionRule($localContext, , self::RULE_, $precedence); + + + + try { + + + + } catch (RecognitionException $exception) { + $localContext->exception = $exception; + $this->errorHandler->reportError($this, $exception); + $this->errorHandler->recover($this, $exception); + } finally { + + $this->unrollRecursionContexts($parentContext); + } + + return $localContext; +} +>> + +CodeBlockForOuterMostAlt(currentOuterMostAltCodeBlock, locals, preamble, ops) ::= << +$localContext = new Context\\Context($localContext); +$this->enterOuterAlt($localContext, ); + +>> + +CodeBlockForAlt(currentAltCodeBlock, locals, preamble, ops) ::= << + + + +>> + +LL1AltBlock(choice, preamble, alts, error) ::= << +$this->setState(); +$this->errorHandler->sync($this); + = $this->input->LT(1); + + +switch ($this->input->LA(1)) { + + + break;}; separator="\n\n"> + +default: + +} +>> + +LL1OptionalBlock(choice, alts, error) ::= << +$this->setState(); +$this->errorHandler->sync($this); + +switch ($this->input->LA(1)) { + + + break;}; separator="\n\n"> + +default: + break; +} +>> + +LL1OptionalBlockSingleAlt(choice, expr, alts, preamble, error, followExpr) ::= << +$this->setState(); +$this->errorHandler->sync($this); + + +if () { + +} +>> + +LL1StarBlockSingleAlt(choice, loopExpr, alts, preamble, iteration) ::= << +$this->setState(); +$this->errorHandler->sync($this); + + +while () { + + $this->setState(); + $this->errorHandler->sync($this); + +} +>> + +LL1PlusBlockSingleAlt(choice, loopExpr, alts, preamble, iteration) ::= << +$this->setState(); +$this->errorHandler->sync($this); + + +do { + + $this->setState(); + $this->errorHandler->sync($this); + +} while (); +>> + +// LL(*) stuff + +AltBlock(choice, preamble, alts, error) ::= << +$this->setState(); +$this->errorHandler->sync($this); + = $this->input->LT(1); + + +switch ($this->getInterpreter()->adaptivePredict($this->input, , $this->ctx)) { + : + +break;}; separator="\n\n"> +} +>> + +OptionalBlock(choice, alts, error) ::= << +$this->setState(); +$this->errorHandler->sync($this); + +switch ($this->getInterpreter()->adaptivePredict($this->input, , $this->ctx)) { ++1: + + break;}; separator="\n\n"> +} +>> + +StarBlock(choice, alts, sync, iteration) ::= << +$this->setState(); +$this->errorHandler->sync($this); + +$alt = $this->getInterpreter()->adaptivePredict($this->input, , $this->ctx); + +while ($alt !== && $alt !== ATN::INVALID_ALT_NUMBER) { + if ($alt === 1+1) { + + + } + + $this->setState(); + $this->errorHandler->sync($this); + + $alt = $this->getInterpreter()->adaptivePredict($this->input, , $this->ctx); +} +>> + +PlusBlock(choice, alts, error) ::= << +$this->setState(); +$this->errorHandler->sync($this); + +$alt = 1+1; + +do { + switch ($alt) { + +1: + + break;}; separator="\n\n"> + default: + + } + + $this->setState(); + $this->errorHandler->sync($this); + + $alt = $this->getInterpreter()->adaptivePredict($this->input, , $this->ctx); +} while ($alt !== && $alt !== ATN::INVALID_ALT_NUMBER); +>> + +Sync(s) ::= "sync();" + +ThrowNoViableAlt(t) ::= "throw new NoViableAltException($this);" + +TestSetInline(s) ::= << +}; separator=" || "> +>> + +// Java language spec 15.19 - shift operators mask operands rather than overflow to 0... need range test +testShiftInRange(shiftAmount) ::= << +(() & ~0x3f) === 0 +>> + +// produces smaller bytecode only when bits.ttypes contains more than two items +bitsetBitfieldComparison(s, bits) ::= <% +(})> && ((1 \<\< ) & ()}; separator=" | ">)) !== 0) +%> + +isZero ::= [ +"0":true, +default:false +] + +offsetShiftVar(shiftAmount, offset) ::= <% +($ - )$ +%> +offsetShiftConst(shiftAmount, offset) ::= <% +(self:: - )self:: +%> + +// produces more efficient bytecode when bits.ttypes contains at most two items +bitsetInlineComparison(s, bits) ::= <% + === self::}; separator=" || "> +%> + +cases(ttypes) ::= << +:}; separator="\n"> +>> + +InvokeRule(r, argExprsChunks) ::= << +$this->setState(); + = }>$this->recursive(,); +>> + +MatchToken(m) ::= << +$this->setState(); + = }>$this->match(self::); +>> + +MatchSet(m, expr, capture) ::= "" + +MatchNotSet(m, expr, capture) ::= "" + +CommonSetStuff(m, expr, capture, invert) ::= << +$this->setState(); + + = }>$this->input->LT(1); + + +if ($ \<= 0 || !()) { + = }>$this->errorHandler->recoverInline($this); +} else { + if ($this->input->LA(1) === Token::EOF) { + $this->matchedEOF = true; + } + + $this->errorHandler->reportMatch($this); + $this->consume(); +} +>> + +Wildcard(w) ::= << +$this->setState(); + = }>$this->matchWildcard(); +>> + +// ACTION STUFF + +Action(a, foo, chunks) ::= "" + +ArgAction(a, chunks) ::= "" + +SemPred(p, chunks, failChunks) ::= << +$this->setState(); + +if (!()) { + throw new FailedPredicateException($this, , , ); +} +>> + +ExceptionClause(e, catchArg, catchAction) ::= << +catch () { + +} +>> + +// lexer actions are not associated with model objects + +LexerSkipCommand() ::= "$this->skip();" +LexerMoreCommand() ::= "$this->more();" +LexerPopModeCommand() ::= "$this->popMode();" + +LexerTypeCommand(arg, grammar) ::= "$this->type = ;" +LexerChannelCommand(arg, grammar) ::= "$this->channel = ;" +LexerModeCommand(arg, grammar) ::= "$this->mode = ;" +LexerPushModeCommand(arg, grammar) ::= "$this->pushMode();" + +ActionText(t) ::= "" +ActionTemplate(t) ::= "" +ArgRef(a) ::= "$localContext->" +LocalRef(a) ::= "$localContext->" +RetValueRef(a) ::= "$localContext->" +QRetValueRef(a) ::= "->->" +/** How to translate $tokenLabel */ +TokenRef(t) ::= "->" +LabelRef(t) ::= "->" +ListLabelRef(t) ::= "->" +SetAttr(s,rhsChunks) ::= "-> = ;" + +TokenLabelType() ::= "" +InputSymbolType() ::= "" + +TokenPropertyRef_text(t) ::= "(-> !== null ? ->->getText() : null)" +TokenPropertyRef_type(t) ::= "(-> !== null ? ->->getType() : 0)" +TokenPropertyRef_line(t) ::= "(-> !== null ? ->->getLine() : 0)" +TokenPropertyRef_pos(t) ::= "(-> !== null ? ->->getCharPositionInLine() : 0)" +TokenPropertyRef_channel(t) ::= "(-> !== null ? ->->getChannel() : 0)" +TokenPropertyRef_index(t) ::= "(-> !== null ? ->->getTokenIndex() : 0)" +TokenPropertyRef_int(t) ::= "(-> !== null ? (int) ->->getText() : 0)" + +RulePropertyRef_start(r) ::= "(-> !== null ? (->->start) : null)" +RulePropertyRef_stop(r) ::= "(-> !== null ? (->->stop) : null)" +RulePropertyRef_text(r) ::= "(-> !== null ? $this->input->getTextByTokens(->->start, ->->stop) : null)" +RulePropertyRef_ctx(r) ::= "->" +RulePropertyRef_parser(r)::= "\$this" + +ThisRulePropertyRef_start(r) ::= "$localContext->start" +ThisRulePropertyRef_stop(r) ::= "$localContext->stop" +ThisRulePropertyRef_text(r) ::= "$this->input->getTextByTokens($localContext->start, $this->input->LT(-1))" +ThisRulePropertyRef_ctx(r) ::= "$localContext" +ThisRulePropertyRef_parser(r)::= "$this" + +NonLocalAttrRef(s) ::= "\$this->getInvokingContext()->" +SetNonLocalAttr(s, rhsChunks) ::= "\$this->getInvokingContext()-> = ;" + +AddToLabelList(a) ::= "->[] = ;" + +TokenDecl(t) ::= " $" +TokenTypeDecl(t) ::= "" +TokenListDecl(t) ::= "array $ = []" +RuleContextDecl(r) ::= " $" +RuleContextListDecl(rdecl) ::= "array $ = []" +AttributeDecl(d) ::= " $ = " + +PropertiesDecl(struct) ::= << + + |null $ + */ +public $;}; separator="\n\n"> + + + + + + |null $ + */ +public $;}; separator="\n\n"> + + + + + + |null $ + */ +public $;}; separator="\n\n"> + + + + + + \>|null $ + */ +public $;}; separator="\n\n"> + + + + + + |null $ + */ +public $ = ;}; separator="\n\n"> + + +>> + +ContextTokenGetterDecl(t) ::= << +public function () : ?TerminalNode +{ + return $this->getToken(::, 0); +} +>> + +ContextTokenListGetterDecl(t) ::= << +>> + +ContextTokenListIndexedGetterDecl(t) ::= << +/** + * @return array\|TerminalNode|null + */ +public function (?int $index = null) +{ + if ($index === null) { + return $this->getTokens(::); + } + + return $this->getToken(::, $index); +} +>> + +ContextRuleGetterDecl(r) ::= << +public function () : ? +{ + return $this->getTypedRuleContext(::class, 0); +} +>> + +ContextRuleListGetterDecl(r) ::= << +>> + +ContextRuleListIndexedGetterDecl(r) ::= << +/** + * @return array\<\>||null + */ +public function (?int $index = null) +{ + if ($index === null) { + return $this->getTypedRuleContexts(::class); + } + + return $this->getTypedRuleContext(::class, $index); +} +>> + +LexerRuleContext() ::= "RuleContext" + +/** + * The rule context name is the rule followed by a suffix; e.g., r becomes rContext. + */ +RuleContextNameSuffix() ::= "Context" + +ImplicitTokenLabel(tokenName) ::= "" +ImplicitRuleLabel(ruleName) ::= "" +ImplicitSetLabel(id) ::= "_tset" +ListLabelName(label) ::= "

." +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << public override IToken NextToken() { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Chrome.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Chrome.test.stg index e02457a90..070409c21 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Chrome.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Chrome.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "var = ;" @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%this. = ;%> InitBooleanMember(n,v) ::= <%this. = ;%> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "" + +VarRef(n) ::= "" + GetMember(n) ::= <%this.%> SetMember(n,v) ::= <%this. = ;%> @@ -92,6 +100,8 @@ this.Property = function() { } >> +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << PositionAdjustingLexer.prototype.resetAcceptPosition = function(index, line, column) { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Cpp.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Cpp.test.stg index c2b1a7f84..bd3f0dd79 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Cpp.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Cpp.test.stg @@ -9,6 +9,7 @@ Assert(s) ::= "" Cast(t,v) ::= "dynamic_cast\< *>()" // Should actually use a more specific name. We may have to use other casts as well. Append(a,b) ::= " + ->toString()" Concat(a,b) ::= "" +AppendStr(a,b) ::= " + " DeclareLocal(s,v) ::= " = " @@ -17,6 +18,9 @@ AssignLocal(s,v) ::= " = ;" InitIntMember(n,v) ::= "int = ;" InitBooleanMember(n,v) ::= "bool = ;" +InitIntVar(n,v) ::= <%%> +IntArg(n) ::= "int " +VarRef(n) ::= "" GetMember(n) ::= "" SetMember(n,v) ::= " = ;" @@ -68,6 +72,8 @@ bool Property() { ParserPropertyCall(p, call) ::= "" +PositionAdjustingLexerDef() ::= "" + PositionAdjustingLexer() ::= << protected: class PositionAdjustingLexerATNSimulator : public antlr4::atn::LexerATNSimulator { diff --git a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Explorer.test.stg b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Explorer.test.stg index 6cfe9ba27..a3d4cb026 100644 --- a/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Explorer.test.stg +++ b/runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Explorer.test.stg @@ -14,6 +14,8 @@ Cast(t,v) ::= "" Append(a,b) ::= " + " +AppendStr(a,b) ::= <%%> + Concat(a,b) ::= "" DeclareLocal(s,v) ::= "var = ;" @@ -26,6 +28,12 @@ InitIntMember(n,v) ::= <%this. = ;%> InitBooleanMember(n,v) ::= <%this. = ;%> +InitIntVar(n,v) ::= <%%> + +IntArg(n) ::= "" + +VarRef(n) ::= "" + GetMember(n) ::= <%this.%> SetMember(n,v) ::= <%this. = ;%> @@ -98,6 +106,8 @@ this.Property = function() { ParserPropertyCall(p, call) ::= "