forked from jasder/antlr
Merge pull request #2931 from ericvergnaud/javascript-es6-migration
Javascript es6 migration
This commit is contained in:
commit
9e64dfc6e9
|
@ -203,6 +203,9 @@ matrix:
|
|||
jdk: openjdk8
|
||||
env: TARGET=javascript
|
||||
stage: main-test
|
||||
before_install:
|
||||
- nvm install 14 # otherwise it runs by default on node 8
|
||||
- f="./.travis/before-install-linux-javascript.sh"; ! [ -x "$f" ] || "$f"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
jdk: openjdk8
|
||||
|
@ -215,7 +218,7 @@ before_install:
|
|||
script:
|
||||
- |
|
||||
cd runtime-testsuite;
|
||||
travis_wait 40 ../.travis/run-tests-$TARGET.sh;
|
||||
rc=$?;
|
||||
cat target/surefire-reports/*.dumpstream || true;
|
||||
travis_wait 40 ../.travis/run-tests-$TARGET.sh
|
||||
rc=$?
|
||||
cat target/surefire-reports/*.dumpstream || true
|
||||
exit $rc
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
sudo apt-get update -qq
|
||||
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
|
||||
sudo apt-get install -qq nodejs
|
||||
node --version
|
||||
# use v14 and check
|
||||
echo node version: $(node --version)
|
||||
|
||||
|
|
|
@ -2,4 +2,8 @@
|
|||
|
||||
set -euo pipefail
|
||||
|
||||
mvn -q -Dparallel=methods -DthreadCount=4 -Dtest=javascript.* test
|
||||
cd ../runtime/JavaScript
|
||||
npm install
|
||||
npm link
|
||||
cd ../../runtime-testsuite
|
||||
mvn -q -Dparallel=methods -DthreadCount=1 -Dtest=javascript.* test
|
||||
|
|
|
@ -16,7 +16,7 @@ build_script:
|
|||
after_build:
|
||||
- msbuild /target:pack /property:Configuration=Release /verbosity:detailed runtime/CSharp/runtime/CSharp/Antlr4.dotnet.sln
|
||||
test_script:
|
||||
- mvn install -Dantlr-php-php="C:\tools\php\php.exe" -Dantlr-dart-dart="C:\tools\dart-sdk\bin\dart.exe" -Dantlr-dart-pub="C:\tools\dart-sdk\bin\pub.bat" -Dantlr-dart-dart2native="C:\tools\dart-sdk\bin\dart2native.bat" -Dantlr-python2-python="C:\Python27\python.exe" -Dantlr-python3-python="C:\Python35\python.exe" -Dantlr-javascript-nodejs="C:\Program Files (x86)\nodejs\node.exe" --batch-mode
|
||||
- mvn install -Dantlr-php-php="C:\tools\php\php.exe" -Dantlr-dart-dart="C:\tools\dart-sdk\bin\dart.exe" -Dantlr-dart-pub="C:\tools\dart-sdk\bin\pub.bat" -Dantlr-dart-dart2native="C:\tools\dart-sdk\bin\dart2native.bat" -Dantlr-python2-python="C:\Python27\python.exe" -Dantlr-python3-python="C:\Python35\python.exe" --batch-mode
|
||||
artifacts:
|
||||
- path: 'runtime\**\*.nupkg'
|
||||
name: NuGet
|
|
@ -11,11 +11,18 @@ In practice, this target has been extensively tested against:
|
|||
* Chrome 39.0.2171
|
||||
* Explorer 11.0.3
|
||||
|
||||
The tests were conducted using Selenium. No issue was found, so you should find that the runtime works pretty much against any recent JavaScript engine.
|
||||
The above tests were conducted using Selenium. No issue was found, so you should find that the runtime works pretty much against any recent JavaScript engine.
|
||||
|
||||
## Is NodeJS supported?
|
||||
|
||||
The runtime has also been extensively tested against Node.js 10 LTS. No issue was found.
|
||||
The runtime has also been extensively tested against Node.js 14 LTS. No issue was found.
|
||||
NodeJS together with a packaging tool is now the preferred development path, developers are encouraged to follow it.
|
||||
|
||||
## What about modules?
|
||||
|
||||
Starting with version 8.1, Antlr4 JavaScript runtime follows esm semantics (see https://tc39.es/ecma262/#sec-modules for details)
|
||||
Generated lexers, parsers, listeners and visitors also follow this new standard.
|
||||
If you have used previous versions of the runtime, you will need to migrate and make your parser a module.
|
||||
|
||||
## How to create a JavaScript lexer or parser?
|
||||
|
||||
|
@ -80,18 +87,18 @@ Let's suppose that your grammar is named, as above, "MyGrammar". Let's suppose t
|
|||
Now a fully functioning script might look like the following:
|
||||
|
||||
```javascript
|
||||
var antlr4 = require('antlr4');
|
||||
var MyGrammarLexer = require('./MyGrammarLexer').MyGrammarLexer;
|
||||
var MyGrammarParser = require('./MyGrammarParser').MyGrammarParser;
|
||||
var MyGrammarListener = require('./MyGrammarListener').MyGrammarListener;
|
||||
import antlr4 from 'antlr4';
|
||||
import MyGrammarLexer from './MyGrammarLexer.js');
|
||||
import MyGrammarParser from './MyGrammarParser.js';
|
||||
import MyGrammarListener from './MyGrammarListener.js';
|
||||
|
||||
var input = "your text to parse here"
|
||||
var chars = new antlr4.InputStream(input);
|
||||
var lexer = new MyGrammarLexer(chars);
|
||||
var tokens = new antlr4.CommonTokenStream(lexer);
|
||||
var parser = new MyGrammarParser(tokens);
|
||||
const input = "your text to parse here"
|
||||
const chars = new antlr4.InputStream(input);
|
||||
const lexer = new MyGrammarLexer(chars);
|
||||
const tokens = new antlr4.CommonTokenStream(lexer);
|
||||
const parser = new MyGrammarParser(tokens);
|
||||
parser.buildParseTrees = true;
|
||||
var tree = parser.MyStartRule();
|
||||
const tree = parser.MyStartRule();
|
||||
```
|
||||
|
||||
This program will work. But it won't be useful unless you do one of the following:
|
||||
|
@ -105,19 +112,19 @@ This program will work. But it won't be useful unless you do one of the followin
|
|||
## How do I create and run a visitor?
|
||||
```javascript
|
||||
// test.js
|
||||
var antlr4 = require('antlr4');
|
||||
var MyGrammarLexer = require('./QueryLexer').QueryLexer;
|
||||
var MyGrammarParser = require('./QueryParser').QueryParser;
|
||||
var MyGrammarListener = require('./QueryListener').QueryListener;
|
||||
import antlr4 from 'antlr4';
|
||||
import MyGrammarLexer from './QueryLexer.js';
|
||||
import MyGrammarParser from './QueryParser.js';
|
||||
import MyGrammarListener from './QueryListener.js';
|
||||
|
||||
|
||||
var input = "field = 123 AND items in (1,2,3)"
|
||||
var chars = new antlr4.InputStream(input);
|
||||
var lexer = new MyGrammarLexer(chars);
|
||||
var tokens = new antlr4.CommonTokenStream(lexer);
|
||||
var parser = new MyGrammarParser(tokens);
|
||||
const input = "field = 123 AND items in (1,2,3)"
|
||||
const chars = new antlr4.InputStream(input);
|
||||
const lexer = new MyGrammarLexer(chars);
|
||||
const tokens = new antlr4.CommonTokenStream(lexer);
|
||||
const parser = new MyGrammarParser(tokens);
|
||||
parser.buildParseTrees = true;
|
||||
var tree = parser.query();
|
||||
const tree = parser.query();
|
||||
|
||||
class Visitor {
|
||||
visitChildren(ctx) {
|
||||
|
@ -145,40 +152,37 @@ tree.accept(new Visitor());
|
|||
Let's suppose your MyGrammar grammar comprises 2 rules: "key" and "value". The antlr4 tool will have generated the following listener:
|
||||
|
||||
```javascript
|
||||
MyGrammarListener = function(ParseTreeListener) {
|
||||
// some code here
|
||||
}
|
||||
// some code here
|
||||
MyGrammarListener.prototype.enterKey = function(ctx) {};
|
||||
MyGrammarListener.prototype.exitKey = function(ctx) {};
|
||||
MyGrammarListener.prototype.enterValue = function(ctx) {};
|
||||
MyGrammarListener.prototype.exitValue = function(ctx) {};
|
||||
class MyGrammarListener extends ParseTreeListener {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
enterKey(ctx) {}
|
||||
exitKey(ctx) {}
|
||||
enterValue(ctx) {}
|
||||
exitValue(ctx) {}
|
||||
}
|
||||
```
|
||||
|
||||
In order to provide custom behavior, you might want to create the following class:
|
||||
|
||||
```javascript
|
||||
var KeyPrinter = function() {
|
||||
MyGrammarListener.call(this); // inherit default listener
|
||||
return this;
|
||||
};
|
||||
class KeyPrinter extends MyGrammarListener {
|
||||
|
||||
// continue inheriting default listener
|
||||
KeyPrinter.prototype = Object.create(MyGrammarListener.prototype);
|
||||
KeyPrinter.prototype.constructor = KeyPrinter;
|
||||
|
||||
// override default listener behavior
|
||||
KeyPrinter.prototype.exitKey = function(ctx) {
|
||||
console.log("Oh, a key!");
|
||||
};
|
||||
// override default listener behavior
|
||||
exitKey(ctx) {
|
||||
console.log("Oh, a key!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In order to execute this listener, you would simply add the following lines to the above code:
|
||||
|
||||
```javascript
|
||||
...
|
||||
tree = parser.StartRule() // only repeated here for reference
|
||||
var printer = new KeyPrinter();
|
||||
...
|
||||
tree = parser.StartRule() // only repeated here for reference
|
||||
const printer = new KeyPrinter();
|
||||
antlr4.tree.ParseTreeWalker.DEFAULT.walk(printer, tree);
|
||||
```
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
|
|||
|
||||
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
|
||||
|
||||
ImportListener(X) ::= <<var <X>Listener = require('./<X>Listener').<X>Listener;>>
|
||||
ImportListener(X) ::= ""
|
||||
|
||||
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"
|
||||
|
||||
|
|
|
@ -76,11 +76,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
|
|||
|
||||
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
|
||||
|
||||
ImportListener(X) ::= <<
|
||||
@parser::header {
|
||||
var <X>Listener = require('./<X>Listener').<X>Listener;
|
||||
}
|
||||
>>
|
||||
ImportListener(X) ::= ""
|
||||
|
||||
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"
|
||||
|
||||
|
|
|
@ -74,11 +74,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
|
|||
|
||||
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
|
||||
|
||||
ImportListener(X) ::= <<
|
||||
@parser::header {
|
||||
var <X>Listener = require('./<X>Listener').<X>Listener;
|
||||
}
|
||||
>>
|
||||
ImportListener(X) ::= ""
|
||||
|
||||
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"
|
||||
|
||||
|
|
|
@ -74,11 +74,7 @@ LANotEquals(i, v) ::= <%this._input.LA(<i>)!=<v>%>
|
|||
|
||||
TokenStartColumnEquals(i) ::= <%this._tokenStartColumn===<i>%>
|
||||
|
||||
ImportListener(X) ::= <<
|
||||
@parser::header {
|
||||
var <X>Listener = require('./<X>Listener').<X>Listener;
|
||||
}
|
||||
>>
|
||||
ImportListener(X) ::= ""
|
||||
|
||||
GetExpectedTokenNames() ::= "this.getExpectedTokens().toString(this.literalNames)"
|
||||
|
||||
|
|
|
@ -46,13 +46,14 @@ import static org.junit.Assume.assumeFalse;
|
|||
public abstract class BaseRuntimeTest {
|
||||
public final static String[] Targets = {
|
||||
"Cpp",
|
||||
"Java",
|
||||
"Go",
|
||||
"CSharp",
|
||||
"Python2", "Python3",
|
||||
"PHP",
|
||||
"Dart",
|
||||
"Go",
|
||||
"Java",
|
||||
"Node",
|
||||
"Dart"
|
||||
"PHP",
|
||||
"Python2", "Python3",
|
||||
"Swift"
|
||||
};
|
||||
|
||||
static {
|
||||
|
@ -95,10 +96,17 @@ public abstract class BaseRuntimeTest {
|
|||
public void setUp() throws Exception {
|
||||
// From http://junit.sourceforge.net/javadoc/org/junit/Assume.html
|
||||
// "The default JUnit runner treats tests with failing assumptions as ignored"
|
||||
assumeFalse(descriptor.ignore(descriptor.getTarget()));
|
||||
assumeFalse(checkIgnored());
|
||||
delegate.testSetUp();
|
||||
}
|
||||
|
||||
public boolean checkIgnored() {
|
||||
boolean ignored = !TestContext.isSupportedTarget(descriptor.getTarget()) || descriptor.ignore(descriptor.getTarget());
|
||||
if(ignored)
|
||||
System.out.println("Ignore " + descriptor);
|
||||
return ignored;
|
||||
}
|
||||
|
||||
@Rule
|
||||
public final TestRule testWatcher = new TestWatcher() {
|
||||
@Override
|
||||
|
@ -112,7 +120,7 @@ public abstract class BaseRuntimeTest {
|
|||
public void testOne() throws Exception {
|
||||
// System.out.println(delegate.getTmpDir());
|
||||
if ( descriptor.ignore(descriptor.getTarget()) ) {
|
||||
System.out.printf("Ignore "+descriptor);
|
||||
System.out.println("Ignore " + descriptor);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -273,6 +281,8 @@ public abstract class BaseRuntimeTest {
|
|||
// ---- support ----
|
||||
|
||||
public static RuntimeTestDescriptor[] getRuntimeTestDescriptors(Class<?> clazz, String targetName) {
|
||||
if(!TestContext.isSupportedTarget(targetName))
|
||||
return new RuntimeTestDescriptor[0];
|
||||
Class<?>[] nestedClasses = clazz.getClasses();
|
||||
List<RuntimeTestDescriptor> descriptors = new ArrayList<RuntimeTestDescriptor>();
|
||||
for (Class<?> nestedClass : nestedClasses) {
|
||||
|
@ -280,8 +290,10 @@ public abstract class BaseRuntimeTest {
|
|||
if ( RuntimeTestDescriptor.class.isAssignableFrom(nestedClass) && !Modifier.isAbstract(modifiers) ) {
|
||||
try {
|
||||
RuntimeTestDescriptor d = (RuntimeTestDescriptor) nestedClass.newInstance();
|
||||
d.setTarget(targetName);
|
||||
descriptors.add(d);
|
||||
if(!d.ignore(targetName)) {
|
||||
d.setTarget(targetName);
|
||||
descriptors.add(d);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package org.antlr.v4.test.runtime;
|
||||
|
||||
public abstract class TestContext {
|
||||
|
||||
public static boolean isTravisCI() {
|
||||
return "true".equals(String.valueOf(System.getenv("TRAVIS")).toLowerCase());
|
||||
}
|
||||
|
||||
public static boolean isAppVeyorCI() {
|
||||
return "true".equals(String.valueOf(System.getenv("APPVEYOR")).toLowerCase());
|
||||
}
|
||||
|
||||
public static boolean isSupportedTarget(String target) {
|
||||
if(isAppVeyorCI())
|
||||
return !target.matches("Swift|Node");
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import org.antlr.v4.semantics.SemanticPipeline;
|
|||
import org.antlr.v4.test.runtime.ErrorQueue;
|
||||
import org.antlr.v4.test.runtime.RuntimeTestSupport;
|
||||
import org.antlr.v4.test.runtime.StreamVacuum;
|
||||
import org.antlr.v4.test.runtime.TestContext;
|
||||
import org.antlr.v4.tool.ANTLRMessage;
|
||||
import org.antlr.v4.tool.DOTGenerator;
|
||||
import org.antlr.v4.tool.Grammar;
|
||||
|
@ -45,6 +46,7 @@ import org.stringtemplate.v4.STGroup;
|
|||
import org.stringtemplate.v4.STGroupString;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -55,6 +57,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.antlr.v4.test.runtime.BaseRuntimeTest.antlrOnString;
|
||||
import static org.antlr.v4.test.runtime.BaseRuntimeTest.writeFile;
|
||||
|
@ -128,16 +131,6 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
return antlrToolErrors.toString();
|
||||
}
|
||||
|
||||
protected org.antlr.v4.Tool newTool(String[] args) {
|
||||
Tool tool = new Tool(args);
|
||||
return tool;
|
||||
}
|
||||
|
||||
protected Tool newTool() {
|
||||
org.antlr.v4.Tool tool = new Tool(new String[] { "-o", tmpdir });
|
||||
return tool;
|
||||
}
|
||||
|
||||
protected ATN createATN(Grammar g, boolean useSerializer) {
|
||||
if (g.atn == null) {
|
||||
semanticProcess(g);
|
||||
|
@ -179,57 +172,6 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
}
|
||||
}
|
||||
|
||||
IntegerList getTypesFromString(Grammar g, String expecting) {
|
||||
IntegerList expectingTokenTypes = new IntegerList();
|
||||
if (expecting != null && !expecting.trim().isEmpty()) {
|
||||
for (String tname : expecting.replace(" ", "").split(",")) {
|
||||
int ttype = g.getTokenType(tname);
|
||||
expectingTokenTypes.add(ttype);
|
||||
}
|
||||
}
|
||||
return expectingTokenTypes;
|
||||
}
|
||||
|
||||
public IntegerList getTokenTypesViaATN(String input,
|
||||
LexerATNSimulator lexerATN) {
|
||||
ANTLRInputStream in = new ANTLRInputStream(input);
|
||||
IntegerList tokenTypes = new IntegerList();
|
||||
int ttype;
|
||||
do {
|
||||
ttype = lexerATN.match(in, Lexer.DEFAULT_MODE);
|
||||
tokenTypes.add(ttype);
|
||||
} while (ttype != Token.EOF);
|
||||
return tokenTypes;
|
||||
}
|
||||
|
||||
public List<String> getTokenTypes(LexerGrammar lg, ATN atn, CharStream input) {
|
||||
LexerATNSimulator interp = new LexerATNSimulator(atn,
|
||||
new DFA[] { new DFA(
|
||||
atn.modeToStartState.get(Lexer.DEFAULT_MODE)) }, null);
|
||||
List<String> tokenTypes = new ArrayList<String>();
|
||||
int ttype;
|
||||
boolean hitEOF = false;
|
||||
do {
|
||||
if (hitEOF) {
|
||||
tokenTypes.add("EOF");
|
||||
break;
|
||||
}
|
||||
int t = input.LA(1);
|
||||
ttype = interp.match(input, Lexer.DEFAULT_MODE);
|
||||
if (ttype == Token.EOF) {
|
||||
tokenTypes.add("EOF");
|
||||
}
|
||||
else {
|
||||
tokenTypes.add(lg.typeToTokenList.get(ttype));
|
||||
}
|
||||
|
||||
if (t == IntStream.EOF) {
|
||||
hitEOF = true;
|
||||
}
|
||||
} while (ttype != Token.EOF);
|
||||
return tokenTypes;
|
||||
}
|
||||
|
||||
protected String execLexer(String grammarFileName, String grammarStr,
|
||||
String lexerName, String input) {
|
||||
return execLexer(grammarFileName, grammarStr, lexerName, input, false);
|
||||
|
@ -243,8 +185,9 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
assertTrue(success);
|
||||
writeFile(tmpdir, "input", input);
|
||||
writeLexerTestFile(lexerName, showDFA);
|
||||
writeFile(tmpdir, "package.json", "{\"type\": \"module\"}");
|
||||
String output = execModule("Test.js");
|
||||
if ( output.length()==0 ) {
|
||||
if ( output!=null && output.length()==0 ) {
|
||||
output = null;
|
||||
}
|
||||
return output;
|
||||
|
@ -262,6 +205,7 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
writeFile(tmpdir, "input", input);
|
||||
rawBuildRecognizerTestFile(parserName, lexerName, listenerName,
|
||||
visitorName, startRuleName, showDiagnosticErrors);
|
||||
writeFile(tmpdir, "package.json", "{\"type\": \"module\"}");
|
||||
return execRecognizer();
|
||||
}
|
||||
|
||||
|
@ -323,17 +267,21 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
}
|
||||
|
||||
public String execModule(String fileName) {
|
||||
String nodejsPath = locateNodeJS();
|
||||
String runtimePath = locateRuntime();
|
||||
String modulePath = new File(new File(tmpdir), fileName)
|
||||
.getAbsolutePath();
|
||||
String inputPath = new File(new File(tmpdir), "input")
|
||||
.getAbsolutePath();
|
||||
try {
|
||||
String npmPath = locateNpm();
|
||||
if(!TestContext.isTravisCI()) {
|
||||
installRuntime(npmPath);
|
||||
registerRuntime(npmPath);
|
||||
}
|
||||
String modulePath = new File(new File(tmpdir), fileName)
|
||||
.getAbsolutePath();
|
||||
linkRuntime(npmPath);
|
||||
String nodejsPath = locateNodeJS();
|
||||
String inputPath = new File(new File(tmpdir), "input")
|
||||
.getAbsolutePath();
|
||||
ProcessBuilder builder = new ProcessBuilder(nodejsPath, modulePath,
|
||||
inputPath);
|
||||
builder.environment().put("NODE_PATH",
|
||||
runtimePath + File.pathSeparator + tmpdir);
|
||||
builder.environment().put("NODE_PATH", tmpdir);
|
||||
builder.directory(new File(tmpdir));
|
||||
Process process = builder.start();
|
||||
StreamVacuum stdoutVacuum = new StreamVacuum(
|
||||
|
@ -342,7 +290,10 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
process.getErrorStream());
|
||||
stdoutVacuum.start();
|
||||
stderrVacuum.start();
|
||||
// TODO switch to jdk 8
|
||||
process.waitFor();
|
||||
// if(!process.waitFor(1L, TimeUnit.MINUTES))
|
||||
// process.destroyForcibly();
|
||||
stdoutVacuum.join();
|
||||
stderrVacuum.join();
|
||||
String output = stdoutVacuum.toString();
|
||||
|
@ -353,22 +304,59 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
this.stderrDuringParse = stderrVacuum.toString();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
System.err.println("can't exec recognizer");
|
||||
e.printStackTrace(System.err);
|
||||
System.err.println();
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String locateTool(String tool) {
|
||||
String[] roots = { "/usr/bin/", "/usr/local/bin/" };
|
||||
for (String root : roots) {
|
||||
if (new File(root + tool).exists()) {
|
||||
return root + tool;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
private void installRuntime(String npmPath) throws IOException, InterruptedException {
|
||||
String runtimePath = locateRuntime();
|
||||
ProcessBuilder builder = new ProcessBuilder(npmPath, "install");
|
||||
builder.directory(new File(runtimePath));
|
||||
builder.redirectError(new File(tmpdir, "error.txt"));
|
||||
builder.redirectOutput(new File(tmpdir, "output.txt"));
|
||||
Process process = builder.start();
|
||||
// TODO switch to jdk 8
|
||||
process.waitFor();
|
||||
// if(!process.waitFor(30L, TimeUnit.SECONDS))
|
||||
// process.destroyForcibly();
|
||||
int error = process.exitValue();
|
||||
if(error!=0)
|
||||
throw new IOException("'npm install' failed");
|
||||
}
|
||||
|
||||
private void registerRuntime(String npmPath) throws IOException, InterruptedException {
|
||||
String runtimePath = locateRuntime();
|
||||
ProcessBuilder builder = new ProcessBuilder(npmPath, "link");
|
||||
builder.directory(new File(runtimePath));
|
||||
builder.redirectError(new File(tmpdir, "error.txt"));
|
||||
builder.redirectOutput(new File(tmpdir, "output.txt"));
|
||||
Process process = builder.start();
|
||||
// TODO switch to jdk 8
|
||||
process.waitFor();
|
||||
// if(!process.waitFor(30L, TimeUnit.SECONDS))
|
||||
// process.destroyForcibly();
|
||||
int error = process.exitValue();
|
||||
if(error!=0)
|
||||
throw new IOException("'npm link' failed");
|
||||
}
|
||||
|
||||
private void linkRuntime(String npmPath) throws IOException, InterruptedException {
|
||||
ProcessBuilder builder = new ProcessBuilder(npmPath, "link", "antlr4");
|
||||
builder.directory(new File(tmpdir));
|
||||
builder.redirectError(new File(tmpdir, "error.txt"));
|
||||
builder.redirectOutput(new File(tmpdir, "output.txt"));
|
||||
Process process = builder.start();
|
||||
// TODO switch to jdk 8
|
||||
process.waitFor();
|
||||
// if(!process.waitFor(30L, TimeUnit.SECONDS))
|
||||
// process.destroyForcibly();
|
||||
int error = process.exitValue();
|
||||
if(error!=0)
|
||||
throw new IOException("'npm link antlr4' failed");
|
||||
}
|
||||
|
||||
private boolean canExecute(String tool) {
|
||||
|
@ -378,21 +366,29 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
Process process = builder.start();
|
||||
StreamVacuum vacuum = new StreamVacuum(process.getInputStream());
|
||||
vacuum.start();
|
||||
// TODO switch to jdk 8
|
||||
process.waitFor();
|
||||
// if(!process.waitFor(30L, TimeUnit.SECONDS))
|
||||
// process.destroyForcibly();
|
||||
vacuum.join();
|
||||
return process.exitValue() == 0;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
catch (Exception e) {
|
||||
;
|
||||
}
|
||||
|
||||
private String locateNpm() {
|
||||
// typically /usr/local/bin/npm
|
||||
String prop = System.getProperty("antlr-javascript-npm");
|
||||
if ( prop!=null && prop.length()!=0 ) {
|
||||
return prop;
|
||||
}
|
||||
return false;
|
||||
return "npm"; // everywhere
|
||||
}
|
||||
|
||||
private String locateNodeJS() {
|
||||
// typically /usr/local/bin/node
|
||||
String propName = "antlr-javascript-nodejs";
|
||||
String prop = System.getProperty(propName);
|
||||
|
||||
String prop = System.getProperty("antlr-javascript-nodejs");
|
||||
if ( prop!=null && prop.length()!=0 ) {
|
||||
return prop;
|
||||
}
|
||||
|
@ -404,7 +400,7 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
|
||||
private String locateRuntime() {
|
||||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
final URL runtimeSrc = loader.getResource("JavaScript/src");
|
||||
final URL runtimeSrc = loader.getResource("JavaScript");
|
||||
if ( runtimeSrc==null ) {
|
||||
throw new RuntimeException("Cannot find JavaScript runtime");
|
||||
}
|
||||
|
@ -418,213 +414,16 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
return System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
}
|
||||
|
||||
// void ambig(List<Message> msgs, int[] expectedAmbigAlts, String
|
||||
// expectedAmbigInput)
|
||||
// throws Exception
|
||||
// {
|
||||
// ambig(msgs, 0, expectedAmbigAlts, expectedAmbigInput);
|
||||
// }
|
||||
|
||||
// void ambig(List<Message> msgs, int i, int[] expectedAmbigAlts, String
|
||||
// expectedAmbigInput)
|
||||
// throws Exception
|
||||
// {
|
||||
// List<Message> amsgs = getMessagesOfType(msgs, AmbiguityMessage.class);
|
||||
// AmbiguityMessage a = (AmbiguityMessage)amsgs.get(i);
|
||||
// if ( a==null ) assertNull(expectedAmbigAlts);
|
||||
// else {
|
||||
// assertEquals(a.conflictingAlts.toString(),
|
||||
// Arrays.toString(expectedAmbigAlts));
|
||||
// }
|
||||
// assertEquals(expectedAmbigInput, a.input);
|
||||
// }
|
||||
|
||||
// void unreachable(List<Message> msgs, int[] expectedUnreachableAlts)
|
||||
// throws Exception
|
||||
// {
|
||||
// unreachable(msgs, 0, expectedUnreachableAlts);
|
||||
// }
|
||||
|
||||
// void unreachable(List<Message> msgs, int i, int[]
|
||||
// expectedUnreachableAlts)
|
||||
// throws Exception
|
||||
// {
|
||||
// List<Message> amsgs = getMessagesOfType(msgs,
|
||||
// UnreachableAltsMessage.class);
|
||||
// UnreachableAltsMessage u = (UnreachableAltsMessage)amsgs.get(i);
|
||||
// if ( u==null ) assertNull(expectedUnreachableAlts);
|
||||
// else {
|
||||
// assertEquals(u.conflictingAlts.toString(),
|
||||
// Arrays.toString(expectedUnreachableAlts));
|
||||
// }
|
||||
// }
|
||||
|
||||
List<ANTLRMessage> getMessagesOfType(List<ANTLRMessage> msgs,
|
||||
Class<? extends ANTLRMessage> c) {
|
||||
List<ANTLRMessage> filtered = new ArrayList<ANTLRMessage>();
|
||||
for (ANTLRMessage m : msgs) {
|
||||
if (m.getClass() == c)
|
||||
filtered.add(m);
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
void checkRuleATN(Grammar g, String ruleName, String expecting) {
|
||||
ParserATNFactory f = new ParserATNFactory(g);
|
||||
ATN atn = f.createATN();
|
||||
|
||||
DOTGenerator dot = new DOTGenerator(g);
|
||||
System.out
|
||||
.println(dot.getDOT(atn.ruleToStartState[g.getRule(ruleName).index]));
|
||||
|
||||
Rule r = g.getRule(ruleName);
|
||||
ATNState startState = atn.ruleToStartState[r.index];
|
||||
ATNPrinter serializer = new ATNPrinter(g, startState);
|
||||
String result = serializer.asString();
|
||||
|
||||
// System.out.print(result);
|
||||
assertEquals(expecting, result);
|
||||
}
|
||||
|
||||
public void testActions(String templates, String actionName, String action,
|
||||
String expected) throws org.antlr.runtime.RecognitionException {
|
||||
int lp = templates.indexOf('(');
|
||||
String name = templates.substring(0, lp);
|
||||
STGroup group = new STGroupString(templates);
|
||||
ST st = group.getInstanceOf(name);
|
||||
st.add(actionName, action);
|
||||
String grammar = st.render();
|
||||
ErrorQueue equeue = new ErrorQueue();
|
||||
Grammar g = new Grammar(grammar, equeue);
|
||||
if (g.ast != null && !g.ast.hasErrors) {
|
||||
SemanticPipeline sem = new SemanticPipeline(g);
|
||||
sem.process();
|
||||
|
||||
ATNFactory factory = new ParserATNFactory(g);
|
||||
if (g.isLexer())
|
||||
factory = new LexerATNFactory((LexerGrammar) g);
|
||||
g.atn = factory.createATN();
|
||||
|
||||
CodeGenerator gen = new CodeGenerator(g);
|
||||
ST outputFileST = gen.generateParser();
|
||||
String output = outputFileST.render();
|
||||
// System.out.println(output);
|
||||
String b = "#" + actionName + "#";
|
||||
int start = output.indexOf(b);
|
||||
String e = "#end-" + actionName + "#";
|
||||
int end = output.indexOf(e);
|
||||
String snippet = output.substring(start + b.length(), end);
|
||||
assertEquals(expected, snippet);
|
||||
}
|
||||
if (equeue.size() > 0) {
|
||||
System.err.println(equeue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkGrammarSemanticsError(ErrorQueue equeue,
|
||||
GrammarSemanticsMessage expectedMessage) throws Exception {
|
||||
ANTLRMessage foundMsg = null;
|
||||
for (int i = 0; i < equeue.errors.size(); i++) {
|
||||
ANTLRMessage m = equeue.errors.get(i);
|
||||
if (m.getErrorType() == expectedMessage.getErrorType()) {
|
||||
foundMsg = m;
|
||||
}
|
||||
}
|
||||
assertNotNull("no error; " + expectedMessage.getErrorType()
|
||||
+ " expected", foundMsg);
|
||||
assertTrue("error is not a GrammarSemanticsMessage",
|
||||
foundMsg instanceof GrammarSemanticsMessage);
|
||||
assertEquals(Arrays.toString(expectedMessage.getArgs()),
|
||||
Arrays.toString(foundMsg.getArgs()));
|
||||
if (equeue.size() != 1) {
|
||||
System.err.println(equeue);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkGrammarSemanticsWarning(ErrorQueue equeue,
|
||||
GrammarSemanticsMessage expectedMessage) throws Exception {
|
||||
ANTLRMessage foundMsg = null;
|
||||
for (int i = 0; i < equeue.warnings.size(); i++) {
|
||||
ANTLRMessage m = equeue.warnings.get(i);
|
||||
if (m.getErrorType() == expectedMessage.getErrorType()) {
|
||||
foundMsg = m;
|
||||
}
|
||||
}
|
||||
assertNotNull("no error; " + expectedMessage.getErrorType()
|
||||
+ " expected", foundMsg);
|
||||
assertTrue("error is not a GrammarSemanticsMessage",
|
||||
foundMsg instanceof GrammarSemanticsMessage);
|
||||
assertEquals(Arrays.toString(expectedMessage.getArgs()),
|
||||
Arrays.toString(foundMsg.getArgs()));
|
||||
if (equeue.size() != 1) {
|
||||
System.err.println(equeue);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkError(ErrorQueue equeue, ANTLRMessage expectedMessage)
|
||||
throws Exception {
|
||||
// System.out.println("errors="+equeue);
|
||||
ANTLRMessage foundMsg = null;
|
||||
for (int i = 0; i < equeue.errors.size(); i++) {
|
||||
ANTLRMessage m = equeue.errors.get(i);
|
||||
if (m.getErrorType() == expectedMessage.getErrorType()) {
|
||||
foundMsg = m;
|
||||
}
|
||||
}
|
||||
assertTrue("no error; " + expectedMessage.getErrorType() + " expected",
|
||||
!equeue.errors.isEmpty());
|
||||
assertTrue("too many errors; " + equeue.errors,
|
||||
equeue.errors.size() <= 1);
|
||||
assertNotNull(
|
||||
"couldn't find expected error: "
|
||||
+ expectedMessage.getErrorType(), foundMsg);
|
||||
/*
|
||||
* assertTrue("error is not a GrammarSemanticsMessage", foundMsg
|
||||
* instanceof GrammarSemanticsMessage);
|
||||
*/
|
||||
assertArrayEquals(expectedMessage.getArgs(), foundMsg.getArgs());
|
||||
}
|
||||
|
||||
public static class FilteringTokenStream extends CommonTokenStream {
|
||||
public FilteringTokenStream(TokenSource src) {
|
||||
super(src);
|
||||
}
|
||||
|
||||
Set<Integer> hide = new HashSet<Integer>();
|
||||
|
||||
@Override
|
||||
protected boolean sync(int i) {
|
||||
if (!super.sync(i)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Token t = get(i);
|
||||
if (hide.contains(t.getType())) {
|
||||
((WritableToken) t).setChannel(Token.HIDDEN_CHANNEL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setTokenTypeChannel(int ttype, int channel) {
|
||||
hide.add(ttype);
|
||||
}
|
||||
}
|
||||
|
||||
protected void mkdir(String dir) {
|
||||
File f = new File(dir);
|
||||
f.mkdirs();
|
||||
}
|
||||
|
||||
protected void writeParserTestFile(String parserName, String lexerName,
|
||||
String listenerName, String visitorName,
|
||||
String parserStartRuleName, boolean debug) {
|
||||
ST outputFileST = new ST(
|
||||
"var antlr4 = require('antlr4');\n"
|
||||
+ "var <lexerName> = require('./<lexerName>');\n"
|
||||
+ "var <parserName> = require('./<parserName>');\n"
|
||||
+ "var <listenerName> = require('./<listenerName>').<listenerName>;\n"
|
||||
+ "var <visitorName> = require('./<visitorName>').<visitorName>;\n"
|
||||
"import antlr4 from 'antlr4';\n"
|
||||
+ "import <lexerName> from './<lexerName>.js';\n"
|
||||
+ "import <parserName> from './<parserName>.js';\n"
|
||||
+ "import <listenerName> from './<listenerName>.js';\n"
|
||||
+ "import <visitorName> from './<visitorName>.js';\n"
|
||||
+ "\n"
|
||||
+ "class TreeShapeListener extends antlr4.tree.ParseTreeListener {\n" +
|
||||
" enterEveryRule(ctx) {\n" +
|
||||
|
@ -640,11 +439,11 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
+ "\n"
|
||||
+ "function main(argv) {\n"
|
||||
+ " var input = new antlr4.FileStream(argv[2], true);\n"
|
||||
+ " var lexer = new <lexerName>.<lexerName>(input);\n"
|
||||
+ " var lexer = new <lexerName>(input);\n"
|
||||
+ " var stream = new antlr4.CommonTokenStream(lexer);\n"
|
||||
+ "<createParser>"
|
||||
+ " parser.buildParseTrees = true;\n"
|
||||
+ " printer = function() {\n"
|
||||
+ " const printer = function() {\n"
|
||||
+ " this.println = function(s) { console.log(s); }\n"
|
||||
+ " this.print = function(s) { process.stdout.write(s); }\n"
|
||||
+ " return this;\n"
|
||||
|
@ -654,10 +453,10 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
+ " antlr4.tree.ParseTreeWalker.DEFAULT.walk(new TreeShapeListener(), tree);\n"
|
||||
+ "}\n" + "\n" + "main(process.argv);\n" + "\n");
|
||||
ST createParserST = new ST(
|
||||
" var parser = new <parserName>.<parserName>(stream);\n");
|
||||
" var parser = new <parserName>(stream);\n");
|
||||
if (debug) {
|
||||
createParserST = new ST(
|
||||
" var parser = new <parserName>.<parserName>(stream);\n"
|
||||
" var parser = new <parserName>(stream);\n"
|
||||
+ " parser.addErrorListener(new antlr4.error.DiagnosticErrorListener());\n");
|
||||
}
|
||||
outputFileST.add("createParser", createParserST);
|
||||
|
@ -671,12 +470,12 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
|
||||
protected void writeLexerTestFile(String lexerName, boolean showDFA) {
|
||||
ST outputFileST = new ST(
|
||||
"var antlr4 = require('antlr4');\n"
|
||||
+ "var <lexerName> = require('./<lexerName>');\n"
|
||||
"import antlr4 from 'antlr4';\n"
|
||||
+ "import <lexerName> from './<lexerName>.js';\n"
|
||||
+ "\n"
|
||||
+ "function main(argv) {\n"
|
||||
+ " var input = new antlr4.FileStream(argv[2], true);\n"
|
||||
+ " var lexer = new <lexerName>.<lexerName>(input);\n"
|
||||
+ " var lexer = new <lexerName>(input);\n"
|
||||
+ " var stream = new antlr4.CommonTokenStream(lexer);\n"
|
||||
+ " stream.fill();\n"
|
||||
+ " for(var i=0; i\\<stream.tokens.length; i++) {\n"
|
||||
|
@ -689,28 +488,6 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
writeFile(tmpdir, "Test.js", outputFileST.render());
|
||||
}
|
||||
|
||||
public void writeRecognizer(String parserName, String lexerName,
|
||||
String listenerName, String visitorName,
|
||||
String parserStartRuleName, boolean debug) {
|
||||
if (parserName == null) {
|
||||
writeLexerTestFile(lexerName, debug);
|
||||
}
|
||||
else {
|
||||
writeParserTestFile(parserName, lexerName, listenerName,
|
||||
visitorName, parserStartRuleName, debug);
|
||||
}
|
||||
}
|
||||
|
||||
protected void eraseFiles(final String filesEndingWith) {
|
||||
File tmpdirF = new File(tmpdir);
|
||||
String[] files = tmpdirF.list();
|
||||
for (int i = 0; files != null && i < files.length; i++) {
|
||||
if (files[i].endsWith(filesEndingWith)) {
|
||||
new File(tmpdir + "/" + files[i]).delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void eraseFiles(File dir) {
|
||||
String[] files = dir.list();
|
||||
for (int i = 0; files != null && i < files.length; i++) {
|
||||
|
@ -734,153 +511,10 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
}
|
||||
}
|
||||
|
||||
public String getFirstLineOfException() {
|
||||
if (this.stderrDuringParse == null) {
|
||||
return null;
|
||||
}
|
||||
String[] lines = this.stderrDuringParse.split("\n");
|
||||
String prefix = "Exception in thread \"main\" ";
|
||||
return lines[0].substring(prefix.length(), lines[0].length());
|
||||
}
|
||||
|
||||
/**
|
||||
* When looking at a result set that consists of a Map/HashTable we cannot
|
||||
* rely on the output order, as the hashing algorithm or other aspects of
|
||||
* the implementation may be different on differnt JDKs or platforms. Hence
|
||||
* we take the Map, convert the keys to a List, sort them and Stringify the
|
||||
* Map, which is a bit of a hack, but guarantees that we get the same order
|
||||
* on all systems. We assume that the keys are strings.
|
||||
*
|
||||
* @param m
|
||||
* The Map that contains keys we wish to return in sorted order
|
||||
* @return A string that represents all the keys in sorted order.
|
||||
*/
|
||||
public <K, V> String sortMapToString(Map<K, V> m) {
|
||||
// Pass in crap, and get nothing back
|
||||
//
|
||||
if (m == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
System.out.println("Map toString looks like: " + m.toString());
|
||||
|
||||
// Sort the keys in the Map
|
||||
//
|
||||
TreeMap<K, V> nset = new TreeMap<K, V>(m);
|
||||
|
||||
System.out.println("Tree map looks like: " + nset.toString());
|
||||
return nset.toString();
|
||||
}
|
||||
|
||||
public List<String> realElements(List<String> elements) {
|
||||
return elements.subList(Token.MIN_USER_TOKEN_TYPE, elements.size());
|
||||
}
|
||||
|
||||
public void assertNotNullOrEmpty(String message, String text) {
|
||||
assertNotNull(message, text);
|
||||
assertFalse(message, text.isEmpty());
|
||||
}
|
||||
|
||||
public void assertNotNullOrEmpty(String text) {
|
||||
assertNotNull(text);
|
||||
assertFalse(text.isEmpty());
|
||||
}
|
||||
|
||||
public static class IntTokenStream implements TokenStream {
|
||||
IntegerList types;
|
||||
int p = 0;
|
||||
|
||||
public IntTokenStream(IntegerList types) {
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void consume() {
|
||||
p++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int LA(int i) {
|
||||
return LT(i).getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int mark() {
|
||||
return index();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int index() {
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release(int marker) {
|
||||
seek(marker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seek(int index) {
|
||||
p = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return types.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token LT(int i) {
|
||||
CommonToken t;
|
||||
int rawIndex = p + i - 1;
|
||||
if (rawIndex >= types.size())
|
||||
t = new CommonToken(Token.EOF);
|
||||
else
|
||||
t = new CommonToken(types.get(rawIndex));
|
||||
t.setTokenIndex(rawIndex);
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token get(int i) {
|
||||
return new org.antlr.v4.runtime.CommonToken(types.get(i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenSource getTokenSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
throw new UnsupportedOperationException("can't give strings");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Interval interval) {
|
||||
throw new UnsupportedOperationException("can't give strings");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(RuleContext ctx) {
|
||||
throw new UnsupportedOperationException("can't give strings");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Token start, Token stop) {
|
||||
throw new UnsupportedOperationException("can't give strings");
|
||||
}
|
||||
}
|
||||
|
||||
/** Sort a list */
|
||||
public <T extends Comparable<? super T>> List<T> sort(List<T> data) {
|
||||
List<T> dup = new ArrayList<T>();
|
||||
dup.addAll(data);
|
||||
List<T> dup = new ArrayList<T>(data);
|
||||
Collections.sort(dup);
|
||||
return dup;
|
||||
}
|
||||
|
@ -889,8 +523,7 @@ public class BaseNodeTest implements RuntimeTestSupport {
|
|||
public <K extends Comparable<? super K>, V> LinkedHashMap<K, V> sort(
|
||||
Map<K, V> data) {
|
||||
LinkedHashMap<K, V> dup = new LinkedHashMap<K, V>();
|
||||
List<K> keys = new ArrayList<K>();
|
||||
keys.addAll(data.keySet());
|
||||
List<K> keys = new ArrayList<K>(data.keySet());
|
||||
Collections.sort(keys);
|
||||
for (K k : keys) {
|
||||
dup.put(k, data.get(k));
|
||||
|
|
|
@ -2468,7 +2468,8 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -2489,12 +2490,14 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -2509,17 +2512,20 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -2636,7 +2642,8 @@
|
|||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -2648,6 +2655,7 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -2662,6 +2670,7 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -2669,12 +2678,14 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -2693,6 +2704,7 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -2782,7 +2794,8 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -2794,6 +2807,7 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -2879,7 +2893,8 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -2915,6 +2930,7 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -2934,6 +2950,7 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -2977,12 +2994,14 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -27,6 +27,6 @@
|
|||
"build": "webpack"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
"node": ">=14"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ const RuleContext = require('./RuleContext');
|
|||
const {Hash, Map, equalArrays} = require('./Utils');
|
||||
|
||||
class PredictionContext {
|
||||
|
||||
constructor(cachedHashCode) {
|
||||
this.cachedHashCode = cachedHashCode;
|
||||
}
|
||||
|
@ -83,6 +84,7 @@ function calculateHashString(parent, returnState) {
|
|||
* can be used for both lexers and parsers.
|
||||
*/
|
||||
class PredictionContextCache {
|
||||
|
||||
constructor() {
|
||||
this.cache = new Map();
|
||||
}
|
||||
|
@ -115,6 +117,7 @@ class PredictionContextCache {
|
|||
|
||||
|
||||
class SingletonPredictionContext extends PredictionContext {
|
||||
|
||||
constructor(parent, returnState) {
|
||||
let hashCode = 0;
|
||||
const hash = new Hash();
|
||||
|
@ -182,6 +185,7 @@ class SingletonPredictionContext extends PredictionContext {
|
|||
}
|
||||
|
||||
class EmptyPredictionContext extends SingletonPredictionContext {
|
||||
|
||||
constructor() {
|
||||
super(null, PredictionContext.EMPTY_RETURN_STATE);
|
||||
}
|
||||
|
@ -211,6 +215,7 @@ class EmptyPredictionContext extends SingletonPredictionContext {
|
|||
PredictionContext.EMPTY = new EmptyPredictionContext();
|
||||
|
||||
class ArrayPredictionContext extends PredictionContext {
|
||||
|
||||
constructor(parents, returnStates) {
|
||||
/**
|
||||
* Parent can be null only if full ctx mode and we make an array
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
const {RuleNode} = require('./tree/Tree');
|
||||
const {INVALID_INTERVAL} = require('./tree/Tree');
|
||||
const INVALID_ALT_NUMBER = require('./atn/ATN').INVALID_ALT_NUMBER || 0; // TODO: solve cyclic dependency to avoid || 0
|
||||
const Trees = require('./tree/Trees');
|
||||
|
||||
class RuleContext extends RuleNode {
|
||||
|
@ -98,7 +97,10 @@ class RuleContext extends RuleNode {
|
|||
* option contextSuperClass.
|
||||
* to set it.
|
||||
*/
|
||||
getAltNumber() { return INVALID_ALT_NUMBER; }
|
||||
getAltNumber() {
|
||||
// use constant value of ATN.INVALID_ALT_NUMBER to avoid circular dependency
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the outer alternative number for this context node. Default
|
||||
|
|
|
@ -8,8 +8,8 @@ const {IntervalSet} = require('./../IntervalSet');
|
|||
const {Token} = require('./../Token');
|
||||
|
||||
class ATN {
|
||||
constructor(grammarType , maxTokenType) {
|
||||
|
||||
constructor(grammarType , maxTokenType) {
|
||||
/**
|
||||
* Used for runtime deserialization of ATNs from strings
|
||||
* The type of the ATN.
|
||||
|
|
|
@ -18,7 +18,7 @@ const PredictionMode = require('./PredictionMode');
|
|||
const RuleContext = require('./../RuleContext');
|
||||
const ParserRuleContext = require('./../ParserRuleContext');
|
||||
const {SemanticContext} = require('./SemanticContext');
|
||||
const PredictionContext = require('./../PredictionContext');
|
||||
const {PredictionContext} = require('./../PredictionContext');
|
||||
const {Interval} = require('./../IntervalSet');
|
||||
const {Transition, SetTransition, NotSetTransition, RuleTransition, ActionTransition} = require('./Transition');
|
||||
const {NoViableAltException} = require('./../error/Errors');
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
const Utils = require('./../Utils');
|
||||
const {Token} = require('./../Token');
|
||||
const {ErrorNode, TerminalNode, RuleNode} = require('./Tree');
|
||||
const ATN = require('./../atn/ATN');
|
||||
|
||||
/** A set of utility routines useful for all kinds of ANTLR trees. */
|
||||
const Trees = {
|
||||
|
@ -50,7 +49,8 @@ const Trees = {
|
|||
if (t instanceof RuleNode) {
|
||||
const context = t.getRuleContext()
|
||||
const altNumber = context.getAltNumber();
|
||||
if ( altNumber != (ATN.INVALID_ALT_NUMBER || 0) ) { // TODO: solve cyclic dependency to avoid || 0
|
||||
// use const value of ATN.INVALID_ALT_NUMBER to avoid circular dependency
|
||||
if ( altNumber != 0 ) {
|
||||
return ruleNames[t.ruleIndex]+":"+altNumber;
|
||||
}
|
||||
return ruleNames[t.ruleIndex];
|
||||
|
|
|
@ -48,12 +48,12 @@ javascriptTypeInitMap ::= [
|
|||
|
||||
ParserFile(file, parser, namedActions, contextSuperClass) ::= <<
|
||||
<fileHeader(file.grammarFileName, file.ANTLRVersion)>
|
||||
var antlr4 = require('antlr4/index');
|
||||
import antlr4 from 'antlr4';
|
||||
<if(file.genListener)>
|
||||
var <file.grammarName>Listener = require('./<file.grammarName>Listener').<file.grammarName>Listener;
|
||||
import <file.grammarName>Listener from './<file.grammarName>Listener.js';
|
||||
<endif>
|
||||
<if(file.genVisitor)>
|
||||
var <file.grammarName>Visitor = require('./<file.grammarName>Visitor').<file.grammarName>Visitor;
|
||||
import <file.grammarName>Visitor from './<file.grammarName>Visitor.js';
|
||||
<endif>
|
||||
|
||||
<namedActions.header>
|
||||
|
@ -62,54 +62,43 @@ var <file.grammarName>Visitor = require('./<file.grammarName>Visitor').<file.gra
|
|||
|
||||
ListenerFile(file, header, namedActions) ::= <<
|
||||
<fileHeader(file.grammarFileName, file.ANTLRVersion)>
|
||||
var antlr4 = require('antlr4/index');
|
||||
import antlr4 from 'antlr4';
|
||||
|
||||
// This class defines a complete listener for a parse tree produced by <file.parserName>.
|
||||
function <file.grammarName>Listener() {
|
||||
return this;
|
||||
}
|
||||
|
||||
<file.grammarName>Listener.prototype = Object.create(antlr4.tree.ParseTreeListener.prototype);
|
||||
<file.grammarName>Listener.prototype.constructor = <file.grammarName>Listener;
|
||||
export default class <file.grammarName>Listener extends antlr4.tree.ParseTreeListener {
|
||||
|
||||
<file.listenerNames:{lname |
|
||||
// Enter a parse tree produced by <file.parserName>#<lname>.
|
||||
<file.grammarName>Listener.prototype.enter<lname; format="cap"> = function(ctx) {
|
||||
\};
|
||||
// Enter a parse tree produced by <file.parserName>#<lname>.
|
||||
enter<lname; format="cap">(ctx) {
|
||||
\}
|
||||
|
||||
// Exit a parse tree produced by <file.parserName>#<lname>.
|
||||
<file.grammarName>Listener.prototype.exit<lname; format="cap"> = function(ctx) {
|
||||
\};
|
||||
// Exit a parse tree produced by <file.parserName>#<lname>.
|
||||
exit<lname; format="cap">(ctx) {
|
||||
\}
|
||||
|
||||
}; separator="\n">
|
||||
|
||||
exports.<file.grammarName>Listener = <file.grammarName>Listener;
|
||||
}
|
||||
>>
|
||||
|
||||
|
||||
VisitorFile(file, header, namedActions) ::= <<
|
||||
<fileHeader(file.grammarFileName, file.ANTLRVersion)>
|
||||
var antlr4 = require('antlr4/index');
|
||||
import antlr4 from 'antlr4';
|
||||
|
||||
// This class defines a complete generic visitor for a parse tree produced by <file.parserName>.
|
||||
|
||||
function <file.grammarName>Visitor() {
|
||||
antlr4.tree.ParseTreeVisitor.call(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
<file.grammarName>Visitor.prototype = Object.create(antlr4.tree.ParseTreeVisitor.prototype);
|
||||
<file.grammarName>Visitor.prototype.constructor = <file.grammarName>Visitor;
|
||||
export default class <file.grammarName>Visitor extends antlr4.tree.ParseTreeVisitor {
|
||||
|
||||
<file.visitorNames:{lname |
|
||||
// Visit a parse tree produced by <file.parserName>#<lname>.
|
||||
<file.grammarName>Visitor.prototype.visit<lname; format="cap"> = function(ctx) {
|
||||
return this.visitChildren(ctx);
|
||||
\};
|
||||
// Visit a parse tree produced by <file.parserName>#<lname>.
|
||||
visit<lname; format="cap">(ctx) {
|
||||
return this.visitChildren(ctx);
|
||||
\}
|
||||
|
||||
}; separator="\n">
|
||||
|
||||
exports.<file.grammarName>Visitor = <file.grammarName>Visitor;
|
||||
}
|
||||
>>
|
||||
|
||||
|
||||
|
@ -120,32 +109,30 @@ fileHeader(grammarFileName, ANTLRVersion) ::= <<
|
|||
|
||||
Parser(parser, funcs, atn, sempredFuncs, superClass) ::= <<
|
||||
<if(superClass)>
|
||||
var <superClass> = require('./<superClass>').<superClass>;
|
||||
import <superClass> from './<superClass>.js';
|
||||
<endif>
|
||||
|
||||
var grammarFileName = "<parser.grammarFileName; format="java-escape">";
|
||||
|
||||
<atn>
|
||||
|
||||
var atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
|
||||
const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
|
||||
|
||||
var decisionsToDFA = atn.decisionToState.map( function(ds, index) { return new antlr4.dfa.DFA(ds, index); });
|
||||
const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
|
||||
|
||||
var sharedContextCache = new antlr4.PredictionContextCache();
|
||||
const sharedContextCache = new antlr4.PredictionContextCache();
|
||||
|
||||
var literalNames = [ <parser.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
export default class <parser.name> extends <superClass; null="antlr4.Parser"> {
|
||||
|
||||
var symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
static grammarFileName = "<parser.grammarFileName; format="java-escape">";
|
||||
static literalNames = [ <parser.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
static symbolicNames = [ <parser.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
static ruleNames = [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
|
||||
|
||||
var ruleNames = [ <parser.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
|
||||
|
||||
class <parser.name> extends <superClass; null="antlr4.Parser"> {
|
||||
constructor(input) {
|
||||
super(input);
|
||||
this._interp = new antlr4.atn.ParserATNSimulator(this, atn, decisionsToDFA, sharedContextCache);
|
||||
this.ruleNames = ruleNames;
|
||||
this.literalNames = literalNames;
|
||||
this.symbolicNames = symbolicNames;
|
||||
this.ruleNames = <parser.name>.ruleNames;
|
||||
this.literalNames = <parser.name>.literalNames;
|
||||
this.symbolicNames = <parser.name>.symbolicNames;
|
||||
<namedActions.members>
|
||||
}
|
||||
|
||||
|
@ -161,10 +148,13 @@ class <parser.name> extends <superClass; null="antlr4.Parser"> {
|
|||
default:
|
||||
throw "No predicate with index:" + ruleIndex;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
<sempredFuncs.values; separator="\n">
|
||||
<endif>
|
||||
|
||||
<funcs; separator="\n">
|
||||
|
||||
}
|
||||
|
||||
<parser.name>.EOF = antlr4.Token.EOF;
|
||||
|
@ -174,12 +164,19 @@ class <parser.name> extends <superClass; null="antlr4.Parser"> {
|
|||
|
||||
<parser.rules:{r | <parser.name>.RULE_<r.name> = <r.index>;}; separator="\n", wrap, anchor>
|
||||
|
||||
<funcs; separator="\n">
|
||||
<funcs:{f | <ruleContexts(f)>}; separator="\n">
|
||||
|
||||
module.exports.<parser.name> = <parser.name>;
|
||||
<! Define fields of this parser to export the context classes !>
|
||||
<parser.funcs:{f | <parser.name>.<f.ctxType> = <f.ctxType>; }; separator="\n">
|
||||
|
||||
>>
|
||||
|
||||
ruleContexts(currentRule) ::= <<
|
||||
<currentRule.ruleCtx>
|
||||
|
||||
<currentRule.altLabelCtxs:{l | <currentRule.altLabelCtxs.(l)>}; separator="\n">
|
||||
>>
|
||||
|
||||
dumpActions(recog, argFuncs, actionFuncs, sempredFuncs) ::= <<
|
||||
<if(actionFuncs)>
|
||||
<lexer.name>.prototype.action = function(localctx, ruleIndex, actionIndex) {
|
||||
|
@ -244,16 +241,9 @@ RuleSempredFunction(r, actions) ::= <<
|
|||
|
||||
RuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,finallyAction,postamble,exceptions) ::= <<
|
||||
|
||||
<ruleCtx>
|
||||
|
||||
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
|
||||
|
||||
<! Define fields of this parser to export the context classes !>
|
||||
<parser.name>.<currentRule.ctxType> = <currentRule.ctxType>;
|
||||
|
||||
<parser.name>.prototype.<currentRule.name> = function(<currentRule.args:{a | <a.name>}; separator=", ">) {
|
||||
|
||||
var localctx = new <currentRule.ctxType>(this, this._ctx, this.state<currentRule.args:{a | , <a.name>}>);
|
||||
<currentRule.name>(<currentRule.args:{a | <a.name>}; separator=", ">) {
|
||||
let localctx = new <currentRule.ctxType>(this, this._ctx, this.state<currentRule.args:{a | , <a.name>}>);
|
||||
this.enterRule(localctx, <currentRule.startState>, <parser.name>.RULE_<currentRule.name>);
|
||||
<namedActions.init>
|
||||
<locals; separator="\n">
|
||||
|
@ -277,7 +267,7 @@ RuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,namedActions,fina
|
|||
this.exitRule();
|
||||
}
|
||||
return localctx;
|
||||
};
|
||||
}
|
||||
|
||||
>>
|
||||
|
||||
|
@ -285,18 +275,15 @@ LeftRecursiveRuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,
|
|||
namedActions,finallyAction,postamble) ::=
|
||||
<<
|
||||
|
||||
<ruleCtx>
|
||||
<altLabelCtxs:{l | <altLabelCtxs.(l)>}; separator="\n">
|
||||
|
||||
<parser.name>.prototype.<currentRule.name> = function(_p<if(currentRule.args)>, <args:{a | , <a>}><endif>) {
|
||||
<currentRule.name>(_p<if(currentRule.args)>, <args:{a | , <a>}><endif>) {
|
||||
if(_p===undefined) {
|
||||
_p = 0;
|
||||
}
|
||||
var _parentctx = this._ctx;
|
||||
var _parentState = this.state;
|
||||
var localctx = new <currentRule.ctxType>(this, this._ctx, _parentState<args:{a | , <a.name>}>);
|
||||
var _prevctx = localctx;
|
||||
var _startState = <currentRule.startState>;
|
||||
const _parentctx = this._ctx;
|
||||
const _parentState = this.state;
|
||||
let localctx = new <currentRule.ctxType>(this, this._ctx, _parentState<args:{a | , <a.name>}>);
|
||||
let _prevctx = localctx;
|
||||
const _startState = <currentRule.startState>;
|
||||
this.enterRecursionRule(localctx, <currentRule.startState>, <parser.name>.RULE_<currentRule.name>, _p);
|
||||
<namedActions.init>
|
||||
<locals; separator="\n">
|
||||
|
@ -317,7 +304,7 @@ LeftRecursiveRuleFunction(currentRule,args,code,locals,ruleCtx,altLabelCtxs,
|
|||
this.unrollRecursionContexts(_parentctx)
|
||||
}
|
||||
return localctx;
|
||||
};
|
||||
}
|
||||
|
||||
>>
|
||||
|
||||
|
@ -424,7 +411,7 @@ if(la_===<i><if(!choice.ast.greedy)>+1<endif>) {
|
|||
StarBlock(choice, alts, sync, iteration) ::= <<
|
||||
this.state = <choice.stateNumber>;
|
||||
this._errHandler.sync(this);
|
||||
var _alt = this._interp.adaptivePredict(this._input,<choice.decision>,this._ctx)
|
||||
let _alt = this._interp.adaptivePredict(this._input,<choice.decision>,this._ctx)
|
||||
while(_alt!=<choice.exitAlt> && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
|
||||
if(_alt===1<if(!choice.ast.greedy)>+1<endif>) {
|
||||
<iteration>
|
||||
|
@ -440,7 +427,7 @@ while(_alt!=<choice.exitAlt> && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) {
|
|||
PlusBlock(choice, alts, error) ::= <<
|
||||
this.state = <choice.blockStartStateNumber>; <! alt block decision !>
|
||||
this._errHandler.sync(this);
|
||||
var _alt = 1<if(!choice.ast.greedy)>+1<endif>;
|
||||
let _alt = 1<if(!choice.ast.greedy)>+1<endif>;
|
||||
do {
|
||||
switch (_alt) {
|
||||
<alts:{alt|
|
||||
|
@ -604,15 +591,16 @@ RuleContextDecl(r) ::= "this.<r.name> = null; // <r.ctxName>"
|
|||
RuleContextListDecl(rdecl) ::= "this.<rdecl.name> = []; // of <rdecl.ctxName>s"
|
||||
|
||||
ContextTokenGetterDecl(t) ::= <<
|
||||
<t.name> = function() {
|
||||
<t.name>() {
|
||||
return this.getToken(<parser.name>.<t.name>, 0);
|
||||
};
|
||||
>>
|
||||
|
||||
// should never be called
|
||||
ContextTokenListGetterDecl(t) ::= <<
|
||||
def <t.name>_list(self):
|
||||
return self.getTokens(<parser.name>.<t.name>)
|
||||
<t.name>_list() {
|
||||
return this.getTokens(<parser.name>.<t.name>);
|
||||
}
|
||||
>>
|
||||
|
||||
ContextTokenListIndexedGetterDecl(t) ::= <<
|
||||
|
@ -630,16 +618,16 @@ ContextTokenListIndexedGetterDecl(t) ::= <<
|
|||
>>
|
||||
|
||||
ContextRuleGetterDecl(r) ::= <<
|
||||
<r.name> = function() {
|
||||
<r.name>() {
|
||||
return this.getTypedRuleContext(<r.ctxName>,0);
|
||||
};
|
||||
>>
|
||||
|
||||
// should never be called
|
||||
ContextRuleListGetterDecl(r) ::= <<
|
||||
def <r.name>_list(self):
|
||||
return self.getTypedRuleContexts(<parser.name>.<r.ctxName>)
|
||||
|
||||
<r.name>_list() {
|
||||
return this.getTypedRuleContexts(<parser.name>.<r.ctxName>);
|
||||
}
|
||||
>>
|
||||
|
||||
ContextRuleListIndexedGetterDecl(r) ::= <<
|
||||
|
@ -672,6 +660,7 @@ CaptureNextTokenType(d) ::= "<d.varName> = this._input.LA(1);"
|
|||
|
||||
StructDecl(struct,ctorAttrs,attrs,getters,dispatchMethods,interfaces,extensionMembers) ::= <<
|
||||
class <struct.name> extends <if(contextSuperClass)><contextSuperClass><else>antlr4.ParserRuleContext<endif> {
|
||||
|
||||
constructor(parser, parent, invokingState<struct.ctorAttrs:{a | , <a.name>}>) {
|
||||
if(parent===undefined) {
|
||||
parent = null;
|
||||
|
@ -685,58 +674,59 @@ class <struct.name> extends <if(contextSuperClass)><contextSuperClass><else>antl
|
|||
<attrs:{a | <a>}; separator="\n">
|
||||
<struct.ctorAttrs:{a | this.<a.name> = <a.name> || null;}; separator="\n">
|
||||
}
|
||||
|
||||
<getters:{g | <g>}; separator="\n\n">
|
||||
|
||||
<if(struct.provideCopyFrom)> <! don't need copy unless we have subclasses !>
|
||||
copyFrom(ctx) {
|
||||
super.copyFrom(ctx);
|
||||
<struct.attrs:{a | this.<a.name> = ctx.<a.name>;}; separator="\n">
|
||||
}
|
||||
<endif>
|
||||
<dispatchMethods; separator="\n">
|
||||
<extensionMembers; separator="\n">
|
||||
|
||||
}
|
||||
|
||||
<getters:{g | <struct.name>.prototype.<g>}; separator="\n\n">
|
||||
|
||||
<if(struct.provideCopyFrom)> <! don't need copy unless we have subclasses !>
|
||||
<struct.name>.prototype.copyFrom = function(ctx) {
|
||||
<if(contextSuperClass)><contextSuperClass><else>antlr4.ParserRuleContext<endif>.prototype.copyFrom.call(this, ctx);
|
||||
<struct.attrs:{a | this.<a.name> = ctx.<a.name>;}; separator="\n">
|
||||
};
|
||||
<endif>
|
||||
<dispatchMethods; separator="\n">
|
||||
<extensionMembers; separator="\n">
|
||||
|
||||
>>
|
||||
|
||||
AltLabelStructDecl(struct,attrs,getters,dispatchMethods) ::= <<
|
||||
class <struct.name> extends <currentRule.name; format="cap">Context {
|
||||
class <struct.name> extends <struct.parentRule; format="cap">Context {
|
||||
|
||||
constructor(parser, ctx) {
|
||||
super(parser);
|
||||
<attrs:{a | <a>;}; separator="\n">
|
||||
<currentRule.name; format="cap">Context.prototype.copyFrom.call(this, ctx);
|
||||
super.copyFrom(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
<struct.name>.prototype = Object.create(<currentRule.name; format="cap">Context.prototype);
|
||||
<struct.name>.prototype.constructor = <struct.name>;
|
||||
<getters:{g | <g>}; separator="\n\n">
|
||||
|
||||
<dispatchMethods; separator="\n">
|
||||
|
||||
}
|
||||
|
||||
<! Define fields of this parser to export this struct/context class !>
|
||||
<parser.name>.<struct.name> = <struct.name>;
|
||||
|
||||
<getters:{g | <struct.name>.prototype.<g>}; separator="\n\n">
|
||||
<dispatchMethods; separator="\n">
|
||||
|
||||
>>
|
||||
|
||||
ListenerDispatchMethod(method) ::= <<
|
||||
<struct.name>.prototype.<if(method.isEnter)>enter<else>exit<endif>Rule = function(listener) {
|
||||
<if(method.isEnter)>enter<else>exit<endif>Rule(listener) {
|
||||
if(listener instanceof <parser.grammarName>Listener ) {
|
||||
listener.<if(method.isEnter)>enter<else>exit<endif><struct.derivedFromName; format="cap">(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
>>
|
||||
|
||||
VisitorDispatchMethod(method) ::= <<
|
||||
<struct.name>.prototype.accept = function(visitor) {
|
||||
accept(visitor) {
|
||||
if ( visitor instanceof <parser.grammarName>Visitor ) {
|
||||
return visitor.visit<struct.derivedFromName; format="cap">(this);
|
||||
} else {
|
||||
return visitor.visitChildren(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
>>
|
||||
|
||||
|
@ -787,7 +777,7 @@ _prevctx = localctx;
|
|||
|
||||
LexerFile(lexerFile, lexer, namedActions) ::= <<
|
||||
<fileHeader(lexerFile.grammarFileName, lexerFile.ANTLRVersion)>
|
||||
var antlr4 = require('antlr4/index');
|
||||
import antlr4 from 'antlr4';
|
||||
|
||||
<namedActions.header>
|
||||
|
||||
|
@ -797,32 +787,28 @@ var antlr4 = require('antlr4/index');
|
|||
|
||||
Lexer(lexer, atn, actionFuncs, sempredFuncs, superClass) ::= <<
|
||||
<if(superClass)>
|
||||
var <superClass> = require('./<superClass>').<superClass>;
|
||||
import <superClass> from './<superClass>.js';
|
||||
<endif>
|
||||
|
||||
<atn>
|
||||
|
||||
var atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
|
||||
const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN);
|
||||
|
||||
var decisionsToDFA = atn.decisionToState.map( function(ds, index) { return new antlr4.dfa.DFA(ds, index); });
|
||||
const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) );
|
||||
|
||||
export default class <lexer.name> extends <if(superClass)><superClass><else>antlr4.Lexer<endif> {
|
||||
|
||||
static grammarFileName = "<lexer.grammarFileName>";
|
||||
static channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN"<if (lexer.channels)>, <lexer.channels:{c| "<c>"}; separator=", ", wrap, anchor><endif> ];
|
||||
static modeNames = [ <lexer.modes:{m| "<m>"}; separator=", ", wrap, anchor> ];
|
||||
static literalNames = [ <lexer.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
static symbolicNames = [ <lexer.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
static ruleNames = [ <lexer.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
|
||||
|
||||
class <lexer.name> extends <if(superClass)><superClass><else>antlr4.Lexer<endif> {
|
||||
constructor(input) {
|
||||
super(input)
|
||||
this._interp = new antlr4.atn.LexerATNSimulator(this, atn, decisionsToDFA, new antlr4.PredictionContextCache());
|
||||
<namedActions.members>
|
||||
|
||||
this.channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN"<if (lexer.channels)>, <lexer.channels:{c| "<c>"}; separator=", ", wrap, anchor><endif> ];
|
||||
|
||||
this.modeNames = [ <lexer.modes:{m| "<m>"}; separator=", ", wrap, anchor> ];
|
||||
|
||||
this.literalNames = [ <lexer.literalNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
|
||||
this.symbolicNames = [ <lexer.symbolicNames:{t | <t>}; null="null", separator=", ", wrap, anchor> ];
|
||||
|
||||
this.ruleNames = [ <lexer.ruleNames:{r | "<r>"}; separator=", ", wrap, anchor> ];
|
||||
|
||||
this.grammarFileName = "<lexer.grammarFileName>";
|
||||
}
|
||||
|
||||
get atn() {
|
||||
|
@ -844,14 +830,13 @@ class <lexer.name> extends <if(superClass)><superClass><else>antlr4.Lexer<endif>
|
|||
|
||||
<dumpActions(lexer, "", actionFuncs, sempredFuncs)>
|
||||
|
||||
module.exports.<lexer.name> = <lexer.name>;
|
||||
|
||||
>>
|
||||
|
||||
SerializedATN(model) ::= <<
|
||||
<! only one segment, can be inlined !>
|
||||
|
||||
var serializedATN = ["<model.serialized; wrap={",<\n> "}>"].join("");
|
||||
const serializedATN = ["<model.serialized; wrap={",<\n> "}>"].join("");
|
||||
|
||||
>>
|
||||
|
||||
|
|
Loading…
Reference in New Issue