ANTLR 4 JavaScript Runtime
The `antlr4` package provides the JavaScript runtime libraries for ANTLR 4, a powerful parser generator tool. It enables parsing various languages and data formats in Node.js (requiring Node.js >= 16) and major browsers like Safari, Firefox, and Chrome. The current stable version is 4.13.2, with minor updates released periodically. A key differentiator is its role as the official runtime for grammars defined using the ANTLR tool, supporting 10 target languages. Due to this multi-target consistency, ANTLR's versioning does not strictly follow npm semantic versioning, meaning minor version bumps can introduce breaking changes across targets; users are strongly advised to pin exact versions. The library ships with comprehensive TypeScript type definitions, making it suitable for modern TypeScript development.
Common errors
-
Error: The '`MyLexer`' class extends '`Lexer`' but is missing the following properties from type '`Lexer`': `tokenFactory`
cause This error typically occurs in TypeScript projects when the generated lexer/parser files (e.g., `MyLexer.js` or `MyLexer.ts`) are out of sync with the `antlr4` runtime library's type definitions. This happens after upgrading the `antlr4` package without regenerating the grammar files.fixRegenerate your lexer and parser JavaScript/TypeScript files using the ANTLR tool that matches the version of your `antlr4` npm package. For example, if you updated to `antlr4@4.13.2`, use `antlr-4.13.2-complete.jar` to generate your grammar files. -
TypeError: Cannot read properties of undefined (reading 'CommonTokenStream')
cause This usually indicates an incorrect CommonJS `require` call where the named export is not directly accessible or a missing dependency.fixFor CommonJS, use `const { CommonTokenStream } = require('antlr4');` or `const antlr4 = require('antlr4'); const CommonTokenStream = antlr4.CommonTokenStream;`. Ensure `antlr4` is installed. -
Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. Instead change the require of ... to a dynamic import()
cause This error occurs in a CommonJS context when a module, explicitly marked as ESM-only, is attempted to be `require()`-d. While `antlr4` supports both, specific deep imports or usage in older build tools might trigger this.fixIf your project is CommonJS-based, ensure you are using `const { NamedExport } = require('antlr4');`. If this specific error persists for deep imports, consider refactoring the affected part of your code to use dynamic `import()` or switch your project to ES Modules.
Warnings
- breaking ANTLR's versioning does not strictly follow npm semantic versioning, prioritizing consistency across its 10 target languages. This means minor version updates (e.g., 4.x.0 to 4.y.0) can introduce breaking changes. Developers are strongly advised to remove the `^` or `~` from `antlr4` entries in `package.json` to pin specific versions (e.g., `"antlr4": "4.13.2"`) and manually update.
- breaking Starting with ANTLR 4.10.0, lexers and parsers generated by the ANTLR tool are often incompatible with code generated by previous versions of the tool. While the JavaScript runtime specifically noted 'except probably javascript' for 4.10.0, this general rule applies across targets. If you upgrade the `antlr4` runtime, you should also regenerate all your grammar-based lexer and parser code using the ANTLR tool (e.g., the `antlr4` JAR) of the *same major version* as the runtime to ensure compatibility.
- breaking The `antlr4` package requires Node.js version 16 or newer. Using it with older Node.js versions will result in runtime errors or failures during installation.
- deprecated The `ANTLRInputStream` class, used for creating input streams, has been deprecated in favor of `CharStreams.fromString()` (or other `CharStreams` methods for files/buffers). While still functional, using `ANTLRInputStream` directly is discouraged.
Install
-
npm install antlr4 -
yarn add antlr4 -
pnpm add antlr4
Imports
- CharStreams
import { ANTLRInputStream } from 'antlr4'; // ANTLRInputStream is deprecatedimport { CharStreams } from 'antlr4'; - CommonTokenStream
const CommonTokenStream = require('antlr4').CommonTokenStream;import { CommonTokenStream } from 'antlr4'; - ParserRuleContext
import { ParserRuleContext } from 'antlr4'; - error.ErrorListener
import { error } from 'antlr4'; const { ErrorListener } = error;
Quickstart
import { CharStreams, CommonTokenStream, error } from 'antlr4';
// IMPORTANT: MyLexer and MyParser are GENERATED by the ANTLR tool from your grammar.
// For example, if you have 'Hello.g4', run 'antlr4 -Dlanguage=JavaScript Hello.g4'
// This will create 'HelloLexer.js', 'HelloParser.js', etc. in your output directory.
// Replace './MyLexer' and './MyParser' with the correct paths to your generated files.
// A minimal mock for demonstration. In a real app, these would be generated.
class MyLexer extends error.DefaultErrorListener {
constructor(input) { super(input); this.tokenFactory = null; this.charPositionInLine = 0; this.line = 1; }
nextToken() { return null; /* Real lexer logic */ }
getAllTokens() { return [{ type: 1, text: 'hello' }, { type: 2, text: 'world' }]; }
}
class MyParser extends error.DefaultErrorListener {
constructor(tokens) { super(tokens); this.ruleNames = ['start']; this.errorHandler = null; this.tokenStream = tokens; }
start() { return { text: 'parsed hello world' }; /* Real parser logic */ }
}
class CustomErrorListener extends error.ErrorListener {
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) {
console.error(`Line ${line}, column ${charPositionInLine}: ${msg}`);
}
}
// 1. Create an input stream from your source code
const input = CharStreams.fromString('hello world');
// 2. Create a lexer (tokenizer) from the input stream
// (Replace MyLexer with your generated lexer, e.g., 'HelloLexer')
const lexer = new MyLexer(input);
lexer.removeErrorListeners(); // Remove default console error listener
lexer.addErrorListener(new CustomErrorListener());
// 3. Create a token stream from the lexer
const tokens = new CommonTokenStream(lexer);
// 4. Create a parser from the token stream
// (Replace MyParser with your generated parser, e.g., 'HelloParser')
const parser = new MyParser(tokens);
parser.removeErrorListeners(); // Remove default console error listener
parser.addErrorListener(new CustomErrorListener());
// 5. Invoke the parser's entry rule (e.g., 'start')
const tree = parser.start();
console.log('Successfully attempted to parse:', input.getText());
// In a real scenario, 'tree' would be a parse tree object
// console.log('Parse tree:', tree.toStringTree(parser.ruleNames));