Skip to content

Feature matrix

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.

PythonRustTypeScriptC
LALR(1)✓✓✓✓
Earley, with resolve or explicit ambiguity✓✓✓✗
  • Earley, C: not yet. For now C is LALR only.
PythonRustTypeScriptC
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.
PythonRustTypeScriptC
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.
PythonRustTypeScriptC
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.
PythonRustTypeScriptC
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.
PythonRustTypeScriptC
%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/an/an/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.
PythonRustTypeScriptC
Minimum versionCPython 3.10Rust 1.96Node 22Rust 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.

FeatureStatus
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 toolsNot implemented.
ambiguity='forest' and the forest transformerDeferred. 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=TrueNot 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.