What each target supports in 0.1.0-beta.3 (0.1.0b3 on PyPI), and the Lark
features no target implements. Every supported feature is checked against
a pinned Lark version’s output
(Lark compatibility,
How compatibility is checked).
Legend: ✓ supported. ◐ supported with a limit, noted under the table.
✗ not available. n/a not applicable.
| Python | Rust | TypeScript | C |
|---|
| LALR(1) | ✓ | ✓ | ✓ | ✓ |
Earley, with resolve or explicit ambiguity | ✓ | ✓ | ✓ | ✗ |
- Earley, C: not yet. For now C is LALR only.
| Python | Rust | TypeScript | C |
|---|
basic and contextual | ✓ | ✓ | ✓ | ◐ |
dynamic and dynamic_complete (Earley) | ✓ | ✓ | ✓ | ✗ |
| Custom lexer | ✓ | ✓ | ✓ | ✗ |
Postlex (rewrite the token stream before parsing) and Indenter | ◐ | ✓ | ◐ | ✗ |
Call a function on each token of a given type (lexer_callbacks) | ✓ | ✓ | ✗ | ✗ |
Lex text into tokens without parsing (lex) | ✓ | ✓ | ✓ | ✗ |
basic and contextual, C: no lexer option. lark_from_source uses the
contextual lexer; lark_from_json uses the lexer the grammar was saved
with.
dynamic and dynamic_complete, C: not yet; they need Earley.
- Postlex, Python, Rust and TypeScript: not with the dynamic lexers.
- Custom postlex, Python and Rust: a postlex that reads the next token before
yielding the current one runs ahead of the parser, so a terminal that
depends on parser state can fail to match.
- Postlex, Python: when
process() restarts, and what copy() carries into
a fork, differ from Lark. See Divergences.
- Postlex, TypeScript: only the built-in preset
indenter: "python", with
fixed terminal names and tab width. See
Indentation.
lex, C: no lexer-only call. lark_interactive_feed_next returns each
token as the parse consumes it.
| Python | Rust | TypeScript | C |
|---|
| Interactive parser, one token at a time (LALR) | ✓ | ✓ | ✓ | ✓ |
Error recovery with on_error (LALR) | ◐ | ✓ | ◐ | ✗ |
match_examples error classification (LALR) | ✓ | ✗ | ✗ | ✗ |
- Interactive parser, every target: needs LALR and the built-in lexer;
anything else is an error. See
Interactive parsing.
- Error recovery, Python: the
on_error handler can feed tokens through
e.interactive_parser, except with a custom lexer, where it can only skip
the token or stop
(divergences).
- Error recovery, Rust: the handler can feed tokens through
cx.interactive_parser().
- Error recovery, TypeScript: the handler can only skip or stop.
- Error recovery, C: no
on_error. After a LARK_UNEXPECTED_TOKEN status,
keep calling lark_interactive_feed_next, which skips the rejected token;
stop on LARK_UNEXPECTED_CHARACTERS, because the unmatched character is
not consumed. See
Recovering from errors.
| Python | Rust | TypeScript | C |
|---|
| Tree walks, queries by rule or token type, pretty-printing | ✓ | ✓ | ✓ | ✓ |
Node positions (propagate_positions) | ✓ | ✓ | ✓ | ✗ |
| Transform, visit and evaluate a tree after the parse | ✓ | ✓ | ✓ | ◐ |
| Transform during the parse (LALR) | ✓ | ◐ | ✓ | ✓ |
Choose how callbacks receive children (v_args) and drop nodes (Discard) | ✓ | n/a | ✓ | n/a |
Merge several transformers into one (merge_transformers) | ✓ | n/a | ✗ | n/a |
- Node positions, C: no accessor for a rule node’s positions yet, though
LARK_OPT_PROPAGATE_POSITIONS is accepted. Token positions come from
lark_node_token_positions.
- Transform, visit and evaluate:
Transformer, Visitor and Interpreter in
Python and TypeScript; fold or fold_fn, Cursor walks and eval in
Rust. See Transformers.
- Transform, visit and evaluate, C:
lark_fold_* with lark_fold_apply is a
bottom-up transform, one callback per rule and token type, computing a
value per node. Cursor walks cover visiting, and lark_cursor_skip_children
skips a subtree. No Interpreter equivalent.
- Transform during the parse:
transformer= in Python, parse_fold_fn in
Rust, the transformer option of parse or the constructor in
TypeScript, lark_parse_fold in C.
- Transform during the parse, Rust: not with a custom lexer;
parse_fold_fn
returns ParseError::Unsupported.
| Python | Rust | TypeScript | C |
|---|
| Save (LALR grammars) | ✓ | ✓ | ✗ | ✗ |
| Load | ✓ | ✓ | ✓ | ✓ |
Cache the compiled grammar on disk between runs (cache=) | ✓ | ✗ | ✗ | ✗ |
- Save and load:
to_json in Python and to_canonical_json in Rust write
JSON. Every target loads it: from_json_str in Python and Rust,
Lark.fromJSON in TypeScript and lark_from_json in C. For a browser or a
C program, save from Python or Rust and ship the JSON.
Python’s save and load wrap the JSON in a pickle that only Python reads.
- Cache, Rust: save once and load from the JSON.
| Python | Rust | TypeScript | C |
|---|
%import from the embedded standard library (common, unicode, python, lark) | ✓ | ✓ | ✓ | ✓ |
%import from your own grammar files | ✓ | ◐ | ✓ | ✗ |
%import from an installed package (open_from_package or FromPackageLoader) | ✓ | n/a | n/a | n/a |
Unicode property escapes (\p{...}) in terminals | ✓ | ✓ | ✓ | ✓ |
edit_terminals (edit the compiled terminals before the parser is built) | ✗ | ✓ | ✗ | ✗ |
List all the errors in a grammar (find_grammar_errors) | ✓ | ✓ | ✗ | ✗ |
- Own grammar files, Rust: no filesystem loader ships.
import_paths takes
any GrammarLoader you implement.
- Own grammar files, TypeScript: the
import_loader option, with
fsLoader(rootDir) (Node only) and mapLoader(sources) ready-made.
edit_terminals, Python: a truthy value raises ConfigurationError.
| Python | Rust | TypeScript | C |
|---|
| Minimum version | CPython 3.10 | Rust 1.96 | Node 22 | Rust 1.96 to build |
TypeScript also runs in browsers, bundlers, Deno, Bun and edge runtimes
through @hyperlark/hyperlark/web. See
Browsers and other runtimes.
None of these is implemented on any target. In Python, each option in the
table raises ConfigurationError: the listed parser and ambiguity
values, a callable propagate_positions, and a truthy value for any of the
others. Divergences lists the
Python-specific differences.
| Feature | Status |
|---|
Reconstructor (Tree back to source text) | Deferred. |
Tree templates (lark.tree_templates) | Deferred. |
| Standalone tool (a generated, self-contained parser) | Deferred. |
| The nearley and serialize tools | Not implemented. |
ambiguity='forest' and the forest transformer | Deferred. resolve and explicit work. |
parser=None (lexer-only mode) | Deferred. Build a parser whose rules use every terminal you need, and call lex. |
cache_grammar= (keep the unanalyzed grammar in the cache, for the reconstructor) | Deferred. cache= works in Python. |
strict= (raise on any potential ambiguity, including shift/reduce conflicts and regex collisions) | Deferred. |
regex= (the third-party regex module) | Deferred. A terminal that uses syntax only the regex module has, such as the recursive subpattern (?&NAME), is an error. |
TextSlice inputs (parse part of a larger string) | Deferred. Pass the substring. |
use_bytes=True | Not planned. Input is str, so decode bytes before parsing. Setting Rust’s LarkOptions::use_bytes to true is also an error. |
CYK parser (parser='cyk') | Not planned. |
propagate_positions with a callable (Lark’s node filter) | Deferred. True and False work. |