Skip to content

Python

Hyperlark is a Rust reimplementation of the Lark parsing toolkit. Hyperlark implements the vast majority of Lark’s features, and can often be used as a drop-in replacement, with none or very few code changes.

Terminal window
pip install hyperlark

Wheels cover CPython 3.10 and later on:

  • Linux: glibc and musl, x86-64 and aarch64
  • macOS 13 and later: x86-64 and arm64
  • Windows: x64

Elsewhere pip install fails: there is no source distribution. PyPy and free-threaded 3.13 are not supported. Free-threaded 3.14 (python3.14t) has its own wheel.

import hyperlark
parser = hyperlark.Lark(r"""
start: "hello" NAME
NAME: /\w+/
%ignore " "
""", parser="lalr")
tree = parser.parse("hello world")
print(tree.pretty())
start world

start is a rule, NAME a terminal. Terminals define the alphabet of your language, while rules define its structure; terminals are written in UPPER-CASE, rules in lower-case. %ignore " " tells the parser to ignore spaces. The literal "hello" is matched, but filtered out of the tree as punctuation.

The sample selects LALR(1) with parser="lalr"; the default, as in Lark, is Earley, which accepts any context-free grammar, even ambiguous ones. LALR is much faster, with some grammar restrictions; we recommend starting with it. How it works compares the two.

A failed parse raises a subclass of UnexpectedInput. Errors lists them and shows how to catch them.

Tokens, such as world in the tree, are FastTokens by default: equal to their text (tok == "world"), with every str method, but not str instances. So anything that needs a real str, such as "".join(tokens), json.dumps(tok) or tok in s, raises TypeError; pass tok.value instead. fast_tokens=False makes every token a Token, a str subclass as in Lark, and is slower.

A Lark instance can be shared between threads. On free-threaded Python 3.14 (python3.14t), parses run in parallel, Python callbacks included.

On free-threaded Python, each garbage-collector run pauses every thread. If you parse on many threads, raise the collector’s threshold at startup:

import gc
gc.set_threshold(200_000)

Cyclic garbage is then freed later. The setting is process-wide, so Hyperlark leaves it to you.