Skip to content

Commit 77d0d47

Browse files
committed
Optimized + complete TS runtime
Signed-off-by: Mike Lischke <[email protected]>
1 parent 18bb820 commit 77d0d47

File tree

190 files changed

+8194
-5938
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

190 files changed

+8194
-5938
lines changed

.eslintrc.json

+8
Original file line numberDiff line numberDiff line change
@@ -608,11 +608,19 @@
608608
"format": [
609609
"PascalCase"
610610
]
611+
},
612+
{
613+
"selector": "property",
614+
"format": [
615+
"camelCase",
616+
"UPPER_CASE"
617+
]
611618
}
612619
],
613620
"@typescript-eslint/restrict-template-expressions": "off",
614621
"@typescript-eslint/restrict-plus-operands": "off",
615622
"@typescript-eslint/no-base-to-string": "off",
623+
"@typescript-eslint/no-namespace": "off",
616624
"jsdoc/check-alignment": "error",
617625
"jsdoc/check-indentation": "off",
618626
"jsdoc/require-param-type": "off",

.github/workflows/nodejs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ name: Build & Test
55

66
on:
77
push:
8-
branches: [ master, ts-migration ]
8+
branches: [ master, complete ]
99
pull_request:
1010
branches: [ master ]
1111

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ package
44
generated
55
coverage
66
*.tgz
7+
.vscode/numbered-bookmarks.json

.vscode/launch.json

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
"tests/benchmarks/run-benchmarks.ts",
4141
],
4242
"sourceMaps": true,
43+
"resolveSourceMapLocations": [
44+
"${workspaceFolder}/**",
45+
"!**/node_modules/**"
46+
],
4347
},
4448
{
4549
"type": "node",

.vscode/numbered-bookmarks.json

-49
This file was deleted.

ReadMe.md

+25-34
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,12 @@
66

77
# TypeScript Runtime for ANTLR 4
88

9-
This package is a fork of the official ANTLR4 JavaScript runtime and has been fully transformed to TypeScript. Other improvements are:
9+
This package started as a fork of the official ANTLR4 JavaScript runtime and has been fully implemented in TypeScript. It implements everything what the Java runtime does, except for the `UnbufferedCharStream` class, which requires a streaming source compatible with both Node.js and browsers. Other notable differences from the original JS source.
1010

11-
- XPath implementation.
12-
- Vocabulary implementation.
13-
- Complete Interval implementation.
14-
- Parser and lexer interpreters.
15-
- Profiler implementation.
1611
- Numerous bug fixes and other changes.
17-
- Smaller node package (no test specs or other unnecessary files).
1812
- No differentiation between node and browser environments.
19-
- InterpreterDataReader implementation.
2013
- Includes the `antlr4ng-cli` tool to generate parser files compatible with this runtime. This tool uses a custom build of the ANTLR4 tool.
2114

22-
This package is a blend of the original JS implementation and antlr4ts, which is a TypeScript implementation of the ANTLR4 runtime, but was abandoned. It tries to keep the best of both worlds, while following the Java runtime as close as possible. It's a bit slower than the JS runtime, but faster than antlr4ts.
23-
2415
## Installation
2516

2617
To install the package, run the following command:
@@ -72,12 +63,12 @@ WS: [ \t\r\n]+ -> skip;
7263
```
7364

7465
```typescript
75-
import { CharStreams, CommonTokenStream } from "antlr4ng";
66+
import { CharStream, CommonTokenStream } from "antlr4ng";
7667
import { ExpressionLexer } from "./generated/ExpressionLexer.js";
7768
import { ExpressionParser } from "./generated/ExpressionParser.js";
7869

7970
const input = "1 + 2 * 3";
80-
const inputStream = CharStreams.fromString(input);
71+
const inputStream = CharStream.fromString(input);
8172
const lexer = new ExpressionLexer(inputStream);
8273
const tokenStream = new CommonTokenStream(lexer);
8374
const parser = new ExpressionParser(tokenStream);
@@ -128,7 +119,7 @@ npm run generate-runtime-tests
128119
and the build of the package:
129120

130121
```bash
131-
npm run build-minified
122+
npm run build
132123
```
133124

134125
After that you can either execute different suites separately or as a whole.
@@ -140,35 +131,33 @@ After that you can either execute different suites separately or as a whole.
140131
|Real world example|`npm run run-benchmarks`|
141132
| All together|`npm run full-test`|
142133

143-
The unit tests consist of tests for individual classes in the runtime (API tests) and the runtime test suite ported from Java. They execute in about 10s.
144-
145-
### Real World Example
134+
The unit tests consist of tests for individual classes in the runtime (API tests) and the runtime test suite ported from Java.
146135

147-
The following tables show the results of the benchmarks previously run on the JS runtime and on last release of this one. Warm times were taken from 5 runs with the 2 slowest stripped off and averaged.
136+
This suite consists of 530 tests and runs in about 9s.
148137

149-
Pure JavaScript release (with type definitions):
138+
### Real World Example
150139

151-
| Test | Cold Run | Warm Run|
152-
| ---- | -------- | ------- |
153-
| Query Collection| 8464 ms | 230 ms |
154-
| Example File | 1043 ms | 112 ms |
155-
| Large Inserts | 11022 ms | 10616 ms |
156-
| Total | 20599 ms | 10978 ms |
140+
The following table shows the results of the benchmarks that were executed in the [antlr4wasm project](https://github.com/mike-lischke/antlr4wasm/tree/master/benchmarks/mysql). The column for antlr4ng, howevever, contains the current results of this runtime.
157141

158-
Last release (pure TypeScript):
142+
| | C++ |antlr4ng|antlr4|antlr4ts|antl4wasm|
143+
|---:|---:|---:|---:|---:|---:|
144+
|Query Collection (cold)|1340 ms| <ins>181/2167 (2348) ms</ins>| 7984 ms| 3402 ms| 3331 ms|
145+
| Bitrix Queries (cold)| 195 ms| <ins>67/271 (338) ms</ins>| 1134 ms| 444 ms| 998 ms|
146+
| Large Inserts (cold)|4981 ms|<ins>6249/2282 (8531) ms</ins>|10695 ms|11483 ms|34243 ms|
147+
|Query Collection (warm)| 133 ms| 129/99 (228) ms| <ins>223 ms</ins>| 259 ms| 1177 ms|
148+
| Bitrix Queries (warm)| 70 ms| 63/73 (136) ms| <ins>110 ms</ins>| 131 ms| 815 ms|
149+
| Large Inserts (warm)|4971 ms|<ins>6249/2269 (8518) ms</ins>|10593 ms|11287 ms|36317 ms|
150+
|||||||
151+
|Total (cold) |6546 ms|<ins>6497/4720 (11217) ms</ins>|19878 ms|15403 ms|38641 ms|
152+
|Total (warm) |5198 ms|<ins>6441/2445 (8886) ms</ins>|10944 ms|11697 ms|38329 ms|
159153

160-
| Test | Cold Run | Warm Run|
161-
| ---- | -------- | ------- |
162-
| Query Collection| 6089 ms | 331 ms |
163-
| Example File | 1064 ms | 191 ms |
164-
| Large Inserts | 14742 ms | 14326 ms |
165-
| Total | 21954 ms | 14869 ms |
154+
Underlined entries are the smallest (not counting C++, which beats them all). For antlr4ng, the times are split into lexing and parsing. Note the high lexer execution times, caused by the large number of predicates (126) + lexer actions (40) in the MySQL lexer.
166155

167-
The benchmarks consist of a set of query files, which are parsed by a MySQL parser. The MySQL grammar is one of the largest and most complex grammars you can find for ANTLR4, which, I think, makes it a perfect test case for parser tests.
156+
The benchmarks consist of a set of query files parsed by a MySQL parser. The MySQL grammar is one of the largest and most complex grammars you can find for ANTLR4, which I think makes it a perfect test case for parser testing.
168157

169-
The query collection file contains more than 900 MySQL queries of all kinds, from very simple comments-only statements to complex stored procedures, including some deeply nested select queries that can easily exhaust the available stack space (in certain situations, such as parsing in a thread with default stack size). The minimum MySQL server version used was 8.0.0.
158+
The query collection file contains more than 900 MySQL queries of all kinds, from very simple comments-only statements to complex stored procedures, including some deeply nested select queries that can easily exhaust the available stack space (in certain situations, such as parsing in a thread with default stack size). The MySQL server version used was 8.2 (the grammar allows dynamic switching of server versions).
170159

171-
The large binary inserts file contains only a few dozen queries, but they are really large with deep recursions, so they stress the prediction engine of the parser. In addition, one query contains binary (image) data containing input characters from the entire UTF-8 range.
160+
The large binary inserts file contains only a few dozen queries, but they are really large with deep recursions, so they stress the parser's prediction engine and often touch uncached DFA states because of the lexer predicates. In addition, one query contains binary (image) data with input characters from the entire UTF-8 range.
172161

173162
The example file is a copy of the largest test file in [this repository](https://github.com/antlr/grammars-v4/tree/master/sql/mysql/Positive-Technologies/examples), and is known to be very slow to parse with other MySQL grammars. The one used here, however, is fast.
174163

@@ -212,6 +201,8 @@ The execute times on last release of this runtime have been measured as:
212201
lexNewGraphemeUTF8 average time 387µs over 400 runs of 85 symbols from emoji.txt DFA cleared
213202
```
214203

204+
Note: Some of the corpus sizes differ due to the restructuring of the test. However, the numbers are not directly comparable anyway, as they were taken on different machines.
205+
215206
## Release Notes
216207

217208
### 2.0.11

build/generate-test-parsers.sh

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11

2-
printf "\x1b[1m\x1b[34mGenerating test parsers...\x1b[0m\n\n"
2+
printf "\x1b[1m\x1b[34mGenerating test parsers...\x1b[0m\n\n"
33

4-
antlr4ng -Dlanguage=TypeScript -visitor -Xexact-output-dir -o ./tests/generated ./tests/fixtures/grammars/*.g4
5-
antlr4ng -Dlanguage=TypeScript -o tests/benchmarks/generated -visitor -listener -Xexact-output-dir tests/benchmarks/MySQLLexer.g4 tests/benchmarks/MySQLParser.g4
4+
# Temporarily copy the ANTLR4 jar to the antlr4ng-cli directory, to allow using a newer version, not yet published to npm.
5+
cp cli/antlr4-4.13.2-SNAPSHOT-complete.jar node_modules/antlr4ng-cli/antlr4-4.13.2-SNAPSHOT-complete.jar
66

7-
printf "done\n\n"
7+
java -jar cli/antlr4-4.13.2-SNAPSHOT-complete.jar -Dlanguage=TypeScript -visitor -Xexact-output-dir -o ./tests/generated ./tests/fixtures/grammars/*.g4
8+
java -jar cli/antlr4-4.13.2-SNAPSHOT-complete.jar -Dlanguage=TypeScript -o tests/benchmarks/generated -visitor -listener -Xexact-output-dir tests/benchmarks/MySQLLexer.g4 tests/benchmarks/MySQLParser.g4
9+
10+
printf "done\n\n"
-18 Bytes
Binary file not shown.

cspell.json

+3
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919
"ignoreWords": [
2020
"AMBIG",
2121
"Dlanguage",
22+
"Evals",
2223
"Grosch",
2324
"Harwell",
2425
"Hashable",
2526
"IATN",
27+
"LLATN",
2628
"Nondisjoint",
2729
"Preds",
30+
"SLLATN",
2831
"Sethi",
2932
"Ullman",
3033
"Wirth",

package-lock.json

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+11-10
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,21 @@
4343
},
4444
"scripts": {
4545
"prepublishOnly": "npm run build && npm run test",
46-
"tsc": "tsc --watch",
47-
"build": "npm run generate-test-parsers && tsc && npm run build-cjs && npm run build-mjs",
48-
"build-bundle": "esbuild ./src/index.js --main-fields=module,main --bundle --target=esnext --keep-names",
49-
"build-mjs": "npm run build-bundle -- --outfile=dist/index.mjs --format=esm",
50-
"build-cjs": "npm run build-bundle -- --outfile=dist/index.cjs --format=cjs",
51-
"generate-xpath-lexer": "node cli/index.js -Dlanguage=TypeScript -o src/tree/xpath/generated -no-visitor -no-listener -Xexact-output-dir src/tree/xpath/XPathLexer.g4",
52-
"full-test": "npm run test && npm run run-benchmarks && npm run time-lexer-speed",
46+
"build": "tsc && npm run build-cjs && npm run build-mjs",
47+
"build-with-maps": "tsc && npm run build-mjs -- --sourcemap=external",
48+
"build-and-test": "npm run build && npm run test",
5349
"test": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --no-coverage",
54-
"generate-test-parsers": "./build/generate-test-parsers.sh",
55-
"generate-runtime-tests": "antlr-tgen --config tests/fixtures/config.json",
50+
"full-test": "npm run test && npm run run-benchmarks && npm run time-lexer-speed",
5651
"run-benchmarks": "node --no-warnings --experimental-vm-modules --loader ts-node/esm tests/benchmarks/run-benchmarks.ts",
5752
"time-lexer-speed": "node --no-warnings --experimental-vm-modules --loader ts-node/esm tests/api/perf/TimeLexerSpeed.ts",
53+
"generate-test-parsers": "./build/generate-test-parsers.sh",
54+
"generate-runtime-tests": "antlr-tgen --config tests/fixtures/config.json",
55+
"build-bundle": "esbuild ./src/index.js --main-fields=module,main --bundle --target=esnext --external:immutable --keep-names",
56+
"build-mjs": "npm run build-bundle -- --outfile=dist/index.mjs --format=esm",
57+
"build-cjs": "npm run build-bundle -- --outfile=dist/index.cjs --format=cjs",
58+
"generate-xpath-lexer": "node cli/index.js -Dlanguage=TypeScript -o src/tree/xpath/generated -no-visitor -no-listener -Xexact-output-dir src/tree/xpath/XPathLexer.g4",
5859
"profile benchmarks": "node --no-warnings --experimental-vm-modules --prof --loader ts-node/esm tests/benchmarks/run-benchmarks.ts",
59-
"process profile tick file": " node --prof-process isolate-0x130008000-75033-v8.log > processed.txt"
60+
"process profile tick file": " node --prof-process isolate-0x140008000-94064-v8.log > processed.txt"
6061
},
6162
"exports": {
6263
"types": "./dist/index.d.ts",

0 commit comments

Comments
 (0)