Skip to main content

lectes: name the rules, get the tokens

▶ Playground  ·  Documentation  ·  PyPI

lectes

Name the rules. Get the tokens. lectes is a small Python scanner (lexer) generator. Give it named regexes, and it yields tokens.

  • No dependencies. It uses only the standard library and needs Python 3.13+.
  • Predictable matching. The longest match wins, and a tie goes to the earlier rule.
  • Grammar files. Write one NAME regex rule per line, in Python or in a .lectes file.
  • A lectes command. Scan files or stdin from the shell, as aligned text or JSON Lines.
  • Locations included. Every token carries its offset, line and column.
  • Unmatched text is reported. By default it raises an error, but you can skip it or handle it yourself.

Try it in the playground: lectes.dev lets you write a grammar and see the tokens as you type, right in your browser. Hover a token to see which rules fought for it.

Installation

As a library:

pip install lectes   # or: uv add lectes

As a command-line tool:

uv tool install lectes                # or: pipx install lectes
uvx lectes grammar.lectes input.txt   # run once without installing

Quick start

from lectes import Configuration, Scanner

config = Configuration.from_text(r"""
# Longest match wins; on a tie, the earlier rule wins.
FOR     for
IN      in
ID      [a-zA-Z_][a-zA-Z0-9_]*
INT     [0-9]+
WS      [ ]+
""")

scanner = Scanner(config)

for token in scanner.scan("for item in items format 42"):
    if token.rule.name != "WS":
        print(token.location.column, token.rule.name, repr(token.literal))
1 FOR 'for'
5 ID 'item'
10 IN 'in'
13 ID 'items'
19 ID 'format'
26 INT '42'

for matches both FOR and ID with the same length, so the earlier rule, FOR, wins. format is an ID, because the longer match always wins.

You can also build the rules in Python:

from lectes import Configuration, Regex, Rule

config = Configuration(
    [
        Rule(name="FOR", regex=Regex("for")),
        Rule(name="ID", regex=Regex("[a-zA-Z_][a-zA-Z0-9_]*")),
    ]
)

The usage guide covers grammar errors and warnings, custom handlers, unmatched text and debugging.

Command line

The lectes command scans a file, or stdin, with a grammar file:

$ cat arithmetic.lectes
INT     [0-9]+
PLUS    \+
WS      \s+

$ echo '12 + 3' | lectes arithmetic.lectes
1:1     INT   '12'
1:3     WS    ' '
1:4     PLUS  '+'
1:5     WS    ' '
1:6     INT   '3'
1:7     WS    '\n'

Use --format json for JSON Lines output, and --check to validate a grammar without scanning. The exit codes are 0 on success, 1 for unmatched text, and 2 for a usage, grammar or I/O error. See the command-line docs for every option.

License

MIT

Metadata

Release files for lectes 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lectes 0.5.0
File Size Uploaded Provenance Actions
lectes-0.5.0.tar.gz 28.7 kB Without provenance Details for lectes-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for lectes 0.5.0
File Interpreter ABI Platform Actions
lectes-0.5.0-py3-none-any.whl Python 3 none any Details for lectes-0.5.0-py3-none-any.whl

Total release size: 62.8 kB

Release files / lectes-0.5.0.tar.gz

Download URL lectes-0.5.0.tar.gz
Size 28.7 kB
Tags Source
SHA-256 checksum
How to use checksums
d1ff0f460bcafa7507f6533e9a82609006c988ecbd88577533a02d6608db5910
BLAKE2b-256 checksum
How to use checksums
4819fee39fa1ce3c9a30462417fbb22f162f84702cbd2988ff93d22a4ac8e825
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"21.3","id":"virginia","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / lectes-0.5.0-py3-none-any.whl

Download URL lectes-0.5.0-py3-none-any.whl
Size 34.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af9b55eb72bfa481d8eaeae0dfee811d6198842725142158c368c0faadd04985
BLAKE2b-256 checksum
How to use checksums
284a2360885c42c0e9e80fc2a49215969fb87371a830450f309e7dc59b3d3870
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"21.3","id":"virginia","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for lectes 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page