Skip to main content

SciLex — a generic, linear-time maximal-munch lexer built on REAL

Project description

SciLex

A small, header-only C++20 maximal-munch lexer built on REAL.

  • Linear-time and ReDoS-safe by construction (via REAL).
  • Eager tokenize or lazy scan.
  • Optional indentation layout for significant-whitespace languages.
  • C++20 header-only + abi3 Python binding (CPython 3.10+).
  • Zero dependencies beyond REAL headers.

Define an ordered set of token rules — each a (kind, regex, skip) triple — and SciLex tokenizes by maximal munch: the longest anchored match wins, with rule order breaking ties. Because it is a thin layer over REAL, tokenization is linear and ReDoS-safe by construction.

This follows the same design principles as REAL: purity, simplicity, and measured optimality.

Capabilities

  • Ordered token rules: (kind, real::regex, skip)
  • Maximal-munch matching (longest match wins, rule order for ties)
  • Source positions (byte offset, line, column)
  • Eager (tokenize) and lazy (scan) APIs
  • Optional END_OF_INPUT token
  • Optional indentation layout (NEWLINE / INDENT / DEDENT)
  • Positioned errors with context snippet
  • Linear-time / ReDoS-safe (via REAL)

Not yet: modes, static_lexer, codepoint columns.

See the guided tour for details.

C++ API

#include <scilex/scilex.hpp>

std::vector<scilex::rule> rules = {
    {0, real::regex("\\s+"), true},           // whitespace (skip)
    {1, real::regex("if")},                   // keyword before identifier
    {2, real::regex("[a-z_][a-z0-9_]*")},     // identifier
    {3, real::regex("[0-9]+")},               // number
};

scilex::lexer lexer(std::move(rules));

// Eager
for (const auto& tok : lexer.tokenize("if x + 42")) { ... }

// Lazy (preferred for parsers)
for (const auto& tok : lexer.scan("if x + 42")) { ... }

See docs/design.dox for the complete C++ API (lexer, token, position, layout, lex_error).

Python binding

An abi3 CPython extension (CPython 3.10+, Limited API).

import scilex

lx = scilex.Lexer([
    (0, r"\s+", True),                 # whitespace (skip)
    (1, r"[0-9]+", False),             # number
    (2, r"[A-Za-z_][A-Za-z0-9_]*", False),
])

# Eager
tokens = lx.tokenize("foo 42", eof=True)

# Lazy (generator)
for tok in lx.scan("foo 42"):
    print(tok.kind, tok.lexeme, tok.position)

# Errors with context
try:
    lx.tokenize("foo @")
except scilex.error as e:
    e.position
    e.context

For significant indentation:

laid = scilex.Layout().apply(lx.tokenize(src, eof=True))

pip install scilex (wheels + sdist). Use scilex.get_include() to compile C++ code against the installed headers.

Build locally: make python && make python-test.

CLI

scilex is a command-line lexer — make cli builds it, make install puts it on your PATH (PREFIX=/BINDIR= to choose where). It has two input modes.

Built-in grammars — a showcase over the seven example languages (JSON, Python, C++, SQL, CSS, Lisp, math):

$ scilex --list                       # the built-in grammars
$ scilex --example json file.json     # lex a file …
$ scilex --example python --layout    # … or its bundled sample, with INDENT/DEDENT

Your own grammar — the universal mode: bring a .lex file and lex anything. A grammar is one rule per line — name, a tab, regex, then an optional tab and skip (# comments and blank lines are ignored):

$ cat my.lex
WS	\s+	skip
NUMBER	[0-9]+(\.[0-9]+)?
IDENT	[A-Za-z_][A-Za-z0-9_]*
OP	<=|>=|==|!=|[-+*/%=<>]

$ echo 'x = 41 + 1' | scilex my.lex        # stdin when no file is given
IDENT	x	1:1
OP	=	1:3
NUMBER	41	1:5
OP	+	1:8
NUMBER	1	1:10

Output is one token per line — the kind, a tab, the lexeme, a tab, then line:col; --layout adds the indentation tokens. A malformed grammar is reported with a clear, positioned error (my.lex:3: invalid regex: …) — never a crash. See examples/sample.lex for a worked file.

This .lex format is a tool convenience parsed by the CLI; the library itself stays plain C++ rule lists (std::vector<scilex::rule>) — no spec language is embedded.

Dependencies

SciLex is header-only and depends only on REAL's headers (the package real-regex on PyPI / https://github.com/RECHE23/real-regex).

By default the build looks for them in a sibling checkout:

~/Projects/
├── real-regex/   # REAL (https://github.com/RECHE23/real-regex)
└── scilex/       # SciLex  (uses ../real-regex/include by default)

Point the build elsewhere with REAL_INCLUDE (Makefile) or -DSCILEX_REAL_INCLUDE=... (CMake) — for instance at the path printed by python -c "import real; print(real.get_include())" when REAL is installed via pip.

For CI or a reproducible build — where no on-disk layout can be assumed — fetch REAL with CMake FetchContent instead (make build FETCH=1, or -DSCILEX_FETCH_DEPS=ON); point it at a remote and pin a tag with -DSCILEX_REAL_REPO=https://… -DSCILEX_REAL_TAG=v2026.6.9.

Development

make test        # build and run the test suite
make coverage    # line-coverage summary + HTML report
make sanitize    # tests under AddressSanitizer + UndefinedBehaviorSanitizer
make lint        # clang-tidy
make format      # uncrustify, in place
make doc         # API reference (Doxygen) with embedded coverage

The API reference is published at https://reche23.github.io/scilex/.

Override the compiler with make test CXX=g++-14.

Coverage bar. SciLex holds the SciLang-stack gate — 100% on all four dimensions (lines, functions, regions and branches) of include/, checked by make coverage and enforced by make full-local-gate (using Apple clang 16). The published report on GitHub Pages / the doc tarball (built on clang 18) reads mid-90s (newer clang instruments more branches). This is the documented toolchain distinction; see the live report for exact figures. (REAL is the other documented exception to the 100% gate — see its README.)

scilex::scilex is the CMake target — add_subdirectory, FetchContent, or an installed config package. The config calls find_dependency(real), so installing REAL's config package alongside (on the same prefix) makes the whole chain resolve from one find_package:

# With REAL and SciLex installed under <prefix>:
find_package(scilex CONFIG REQUIRED)   # pulls in real:: transitively
target_link_libraries(app PRIVATE scilex::scilex)

Releasing

make release computes the next calendar version YYYY.M.PATCH (the patch resets each month; PEP 440 drops leading zeros). The pushed tag drives the release workflow — wheels + sdist + the API-reference tarball + a GitHub Release, published via Trusted Publishing — while docs.yml deploys the reference to GitHub Pages.

Design

A guided tour of how SciLex works (maximal munch, REAL foundation, layout, C++/Python API, current scope) lives in docs/design.dox (also rendered by make doc).

Performance

See BENCHMARKS.md. On normal input re is faster. On adversarial input SciLex stays linear while re explodes. See the benchmarks for details.

License

MIT — see LICENSE.

Author

René Chenard

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scilex-2026.6.4.tar.gz (37.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

scilex-2026.6.4-cp310-abi3-win_amd64.whl (245.7 kB view details)

Uploaded CPython 3.10+Windows x86-64

scilex-2026.6.4-cp310-abi3-win32.whl (243.2 kB view details)

Uploaded CPython 3.10+Windows x86

scilex-2026.6.4-cp310-abi3-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

scilex-2026.6.4-cp310-abi3-musllinux_1_2_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

scilex-2026.6.4-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (440.7 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.24+ x86-64manylinux: glibc 2.28+ x86-64

scilex-2026.6.4-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (430.8 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.24+ ARM64manylinux: glibc 2.28+ ARM64

scilex-2026.6.4-cp310-abi3-macosx_11_0_x86_64.whl (58.1 kB view details)

Uploaded CPython 3.10+macOS 11.0+ x86-64

scilex-2026.6.4-cp310-abi3-macosx_11_0_arm64.whl (55.4 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file scilex-2026.6.4.tar.gz.

File metadata

  • Download URL: scilex-2026.6.4.tar.gz
  • Upload date:
  • Size: 37.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for scilex-2026.6.4.tar.gz
Algorithm Hash digest
SHA256 e3068a782e2b0ff4fdffe1934668b716596f1618b0c0cea58482612295a5fa8b
MD5 c12a8da2b538062535b9e68f0c60e6e2
BLAKE2b-256 8b6a34b1d5109db5ea91d717e3870de22430815675904a0606333991fa0b0f0f

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4.tar.gz:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: scilex-2026.6.4-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 245.7 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 0e7622d5cbd65e93bf6dc7e9380cac7173055771583bc78c0a467568f8b2f77d
MD5 2c2667adcad41d36250032ccad1c80b9
BLAKE2b-256 86c21a7edf770c4cc45f5689bb6661390db37e16b9be81afa82cd2fd1f592666

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-win_amd64.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-win32.whl.

File metadata

  • Download URL: scilex-2026.6.4-cp310-abi3-win32.whl
  • Upload date:
  • Size: 243.2 kB
  • Tags: CPython 3.10+, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-win32.whl
Algorithm Hash digest
SHA256 56b7dcba429c93a285f8b69f18dcd86eb7203cf3eb95b27d7ddd5881308cfabd
MD5 676b78ddab01f8f0c1fbbefbf831ab95
BLAKE2b-256 d0b30e7208a769dcca46c2f39bc6783b1c64045429308d09f77a29da13a2f5ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-win32.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 239e540a6a0273f712402364634bf49c198a1f65c39eb881e19c95bc4ff214ee
MD5 a0422bab712b8efb64be097af82431bf
BLAKE2b-256 9d9e983da330a36c1396b438ce77683a2507eac9e83afbb48c317b7f25e47000

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-musllinux_1_2_x86_64.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 f2c5d39b0321452ecff1c478df9980c377ed08795678bc73df67882f91a1c8c9
MD5 2d297bdf367f7b04a03689a1244eaa64
BLAKE2b-256 b6f23054ae66129035ef098dc9c0e3751822236f5b7fcd62a47f2662e5085f07

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-musllinux_1_2_aarch64.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c0759fd9c9185a1d3c75ff64ed042f2c9767d46d52da8dd915998042f39d3b7f
MD5 1b87908fcb9310864a36cac39ca92c95
BLAKE2b-256 886185082fd0188aa73715ca0c35a708a10d47d328126b000d3c7fe9a032471c

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ebe520913a899d07184570004075ad51367b5eb3fedfc744b75c464bca051b61
MD5 482dfa0e78588e853d0c174340ed0681
BLAKE2b-256 ba7702390cb24341f0c8d6ea8582dea64489885a0802f57cc997f2e0d22d01af

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 f166388410286221cd32892521aa02c4cc32e6e0e34f218576da16c55994e9c3
MD5 3c249eb30990414dfa1706aeb3921ff2
BLAKE2b-256 e8fdd617c77b2a53686a3de032dfbf6d255989b6ab0c482bdda0cc79c9125b6b

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-macosx_11_0_x86_64.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scilex-2026.6.4-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for scilex-2026.6.4-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 12f4f95c5dd3ad3d31a99245b1441c1a714f55aec94f70982051059fae217cdc
MD5 24a6eff3375f04fa994da5609fde81a3
BLAKE2b-256 d371f02c14aab115ce40e1d0d94818c92d20630088cdb6512fbeea3aefaed0cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for scilex-2026.6.4-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on RECHE23/scilex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page