ANTLR
ANTLR (ANother Tool for Language Recognition) is a parser generator: you describe a language's syntax in a grammar file, and ANTLR generates a lexer and parser that turn source text into a parse tree. It is used to build query languages, configuration formats, domain-specific languages, code analysis tools, and translators — Hive and Spark SQL, Presto, and many IDE plugins have parsers generated by ANTLR. One grammar can generate parsers for Java, Python, JavaScript and TypeScript, C#, Go, C++, Swift, Dart, and PHP.
ANTLR 4's adaptive parsing strategy accepts grammars written naturally — including directly left-recursive expression rules — so you spend time on the language, not on contorting rules to satisfy the parsing algorithm. Its generated listeners and visitors separate parsing from what you do with the tree.
TL;DR
- A
.g4grammar contains parser rules (lowercase) and lexer rules (uppercase). - ANTLR 4 uses **ALL(\*) adaptive parsing and supports direct left recursion**, so expression precedence follows rule order.
- Generated code includes a lexer, a parser, and listener and visitor interfaces for walking the parse tree.
- Labeled alternatives (
# Add) give each alternative its own callback. - Lexer modes and channels handle embedded languages, whitespace, and comments.
- Add custom error listeners, test grammars against example inputs, and check for ambiguities early.
Quick Example
An expression language with assignments, written as a grammar:
Generate a Python parser and evaluate input with a visitor:
Because MulDiv appears before AddSub, multiplication binds tighter — precedence comes from the order of alternatives.
Core Concepts
Lexer and Parser Rules
The lexer picks the longest match, breaking ties by rule order — so keywords must be defined before a general identifier rule. Literals in parser rules ('=') create implicit tokens.
Adaptive Parsing and Left Recursion
ANTLR 4's ALL(\*) strategy looks ahead as far as needed at runtime to choose between alternatives, caching decisions for speed. It rewrites directly left-recursive rules such as expr : expr '*' expr | ... automatically; alternatives listed first get higher precedence, and <assoc=right> marks right-associative operators such as exponentiation. Indirect left recursion across several rules is not supported.
Parse Trees, Listeners, and Visitors
Most language tools convert the parse tree into their own abstract syntax tree early, so later stages do not depend on grammar details. See Abstract Syntax Trees.
Lexer Modes and Channels
Lexer modes switch token rules in context — inside a string template, a tag, or an embedded language — using pushMode and popMode. Channels keep tokens out of the parser's way without discarding them: sending comments and whitespace to a hidden channel lets formatters and documentation tools still find them.
Error Handling
By default, ANTLR reports syntax errors to the console and recovers by inserting or deleting tokens. Language tools should replace the default error listener with one that collects errors with line and column information, and choose a strategy: keep recovering to report many errors (editors), or stop at the first error with BailErrorStrategy (configuration loaders).
Testing and Performance
- Test grammars with representative valid and invalid inputs, asserting on parse trees or the ASTs you build; the community grammars-v4 repository shows how large grammars are tested.
- Inspect trees with the
antlr4-parsetool from antlr4-tools, or IDE plugins for IntelliJ and VS Code that visualize parse trees. - Detect ambiguities with a diagnostic error listener during development.
- Performance: use two-stage parsing (fast SLL mode first, falling back to full LL on errors), reuse parsers where safe, and avoid ambiguous or overly general rules that force deep lookahead.
ANTLR or a Hand-Written Parser
Many production compilers use hand-written recursive descent parsers; many data and tooling projects use ANTLR. See Lexers and Parsers and Tree-sitter.
Best Practices
Keep Grammars Free of Application Logic
Avoid embedded actions and semantic predicates where possible; do the work in listeners or visitors so the grammar stays reusable across targets.
Label Alternatives
Labels produce specific callback methods (visitAddSub) and context classes, making tree-walking code far clearer than inspecting children by position.
Order Lexer Rules Carefully
Put keywords before identifiers and longer operators before their prefixes, and test tokenization separately from parsing.
Build Your Own AST
Translate the parse tree into a stable AST so grammar refactoring does not ripple through every later stage.
Common Mistakes
Identifier Rule Before Keywords
Swallowing Errors
Logic Inside the Grammar
FAQ
What is ANTLR used for?
Generating lexers and parsers from grammar files to build domain-specific languages, query languages, configuration formats, code analyzers, translators, and IDE support.
Which languages can ANTLR generate parsers for?
ANTLR 4 targets include Java, C#, Python, JavaScript, TypeScript, Go, C++, Swift, Dart, and PHP, all from the same grammar.
What is the difference between a listener and a visitor in ANTLR?
A listener is called automatically as a tree walker enters and exits nodes, which suits collecting data. A visitor lets your code decide which children to visit and return values, which suits evaluation and AST construction.
Does ANTLR support left recursion?
ANTLR 4 supports direct left recursion within a rule, rewriting it automatically, with precedence determined by the order of alternatives. Indirect left recursion across multiple rules is not supported.
Is ANTLR fast enough for production?
For most uses, yes, especially with two-stage SLL/LL parsing and well-structured grammars. Highly performance-sensitive or editor-incremental use cases may prefer hand-written parsers or Tree-sitter.
Related Topics
- Lexers and Parsers — Parsing techniques in general
- Abstract Syntax Trees — Representing parsed programs
- Tree-sitter — Incremental parsing for editors
- Interpreters — Executing parsed programs
- Compilers & Language Implementation — The full compiler pipeline
- Regular Expressions — The basis of lexer rules