Skip to main content

REAL — linear-time (ReDoS-safe) regex engine with an re-compatible API

Project description

REAL

Regular Expression Algorithmic Library — a header-only C++20 regex engine, constexpr from end to end, with an re-compatible Python binding.

  • Linear time, always. The engine is a Pike VM (Thompson NFA simulation): no backtracking, ReDoS-safe by construction.
  • Constexpr-friendly. Patterns known at compile time are parsed, compiled and matched at compile time.
  • Minimal memory. Static (sizes fixed at compile time, zero allocation), dynamic (storage sized exactly once at pattern compilation), or hybrid (compile-time pattern, runtime text, zero heap allocation).
  • Zero dependencies. One include.

Unsupported syntax is rejected with real::regex_error rather than silently diverging. Deferred (and rejected): lookarounds, backreferences, atomic/possessive groups, Unicode property classes, Unicode case folding, pos/endpos.

Matching is linear in the input length: a Thompson NFA simulation (Pike VM) with marked states, so a pattern such as (a+)+b cannot trigger exponential backtracking. A literal prefilter and several whole-pattern fast paths (literals, fixed-width sequences, ./negated-class runs, alternations of straight-line branches) keep the constant factor low without leaving the linear-time guarantee.

make bench-python compares throughput against Python's re, and make bench-engines compares against std::regex, PCRE2 and RE2 in one C++ process (each engine's match counts are checked equal). Figures depend on the platform, pattern and input; reproduce them locally rather than trusting a number here.

Supported syntax

Syntax Meaning
abc literal bytes (UTF-8 patterns match their UTF-8 bytes)
\. \* \\ escaped metacharacter, matched literally
. any codepoint except \n
[abc] [a-z] [^abc] character class (members must be ASCII); [^…] matches any codepoint outside the set
\d \D \w \W \s \S digit / word / space classes (ASCII sets, like Python's re.ASCII)
\n \t \r \f \v \a \0 \xHH control and hex escapes
x* x+ x? quantifiers (greedy; append ? for lazy)
x{n} x{n,} x{,m} x{n,m} counted repetition (greedy or lazy; counts capped at 1000)
a|b alternation, leftmost branch preferred
(…) (?:…) capturing / non-capturing group
(?P<name>…) (?<name>…) named capturing group (Python and .NET styles)
^ $ line/text anchors (Python semantics: $ also matches before a final \n)
\A \Z strict text start / end
\b \B word boundary / non-boundary (ASCII word characters)
\< \> start / end of word (REAL extension, not in Python re)
(?imsx) prefix global flags: i case-insensitive (ASCII), m multiline, s dotall, x verbose (ignore unescaped whitespace and # comments outside classes) — also real::flags on the constructor

Unicode model: matching is UTF-8 byte-based, but every construct consumes whole codepoints (multi-byte sequences compile to byte-level alternatives), so match boundaries never split a character. Class members and the \d \w \s sets are ASCII by design; [^…], \D \W \S and . do match non-ASCII codepoints.

Divergence from Python: when a nullable loop body ends with an empty iteration — e.g. (a*)* on "aa" — Python captures that final empty iteration (''); REAL, like Perl/PCRE, keeps the last non-empty one ("aa"). Group 0 is identical either way.

C++ API

#include <real/real.hpp>

real::regex rx("hello");     // runtime pattern, storage sized exactly once
rx.match("hello world");     // anchored at the start   (Python re.match)
rx.fullmatch("hello");       // whole text              (Python re.fullmatch)
rx.search("say hello");      // leftmost match anywhere (Python re.search)

match/fullmatch/search return a real::match_result: matched(), operator bool, start(g), end(g), m[g] (a std::string_view into the searched text, which must outlive the result), and the same accessors by group name (m["year"], group_index).

for (auto& m : rx.find_iter(text)) {  }      // lazy, Python finditer rules
rx.find_all(text);                            // eager vector<match_result>
rx.replace(text, "$2:$1");                    // $&, $1…, ${name}, $$ — re.sub
rx.replace(text, "#", 2);                     // count limit
rx.split(text);                               // Python re.split, with groups

Empty matches follow Python's rules: they are yielded (even right after a non-empty match) and the scan then advances one whole codepoint. find_iter/find_all cannot be called on a temporary regex, and match/search/split cannot take a temporary std::string.

Three memory modes

// Static: pattern compiled at compile time into exactly-sized constexpr
// arrays; an invalid pattern is a *compile error*.
constexpr real::static_regex<"(\\d{4})-(\\d{2})"> date;
static_assert(date.search("on 2026-06-10")[1] == "2026");  // constexpr match

// Hybrid: compile-time pattern, runtime text — matching performs zero heap
// allocations (state lives on the stack).
date.search(runtime_text);

// Dynamic: everything at runtime; the program is sized exactly once at
// compilation, match state is per-run scratch.
real::regex rx2(user_pattern, real::flags::icase);

The pure library is standard C++20 with no platform dependencies. real::real is the CMake FetchContent/find_package target.

Python binding

An re-compatible module backed by the C++ engine (CPython Limited API, one abi3 extension, zero dependencies):

import real

real.search(r"(?P<y>\d{4})-(?P<m>\d{2})", "on 2026-06-10").groupdict()
real.compile(r"\w+").findall(text)         # findall/finditer/split/sub/subn
real.sub(r"\s+", " ", text)                # templates: \1, \g<name>, callables
real.compile(rb"[^;]+").findall(raw)       # bytes patterns: raw-byte semantics

str matching is UTF-8 with character indices in start/end/span; bytes patterns get re's exact raw-byte semantics. Unsupported re features raise real.error at compile time. Build with make python && make python-test.

pip install real-regex installs one cp310-abi3 wheel per platform (CPython 3.10+; the self-contained sdist compiles where no wheel matches).

Embedding the C++ library through the Python package

The wheel also ships the C++ headers, so a project can compile against REAL located through its Python install — the convention used by petsc4py and slepc4py:

c++ -std=c++20 $(python -c "import real; print(real.get_include())") app.cpp

real.get_config() returns the version, the include directory and the required C++ standard.

Releasing. Run make release. It computes the next calendar version YYYY.M.PATCH — the patch resets each month, the first release of a month is .0 (PEP 440 drops leading zeros, so 2026.6.1, never 2026.06.001) — bumps it in pyproject.toml and python/real/__init__.py, then commits, tags and pushes. The tag drives release.yml, which checks the tag matches the version, builds abi3 wheels (cibuildwheel, Linux/macOS/Windows) and the sdist, and publishes to PyPI via Trusted Publishing (OIDC, no stored secret). The pushed tag is the single thing that triggers a publish.

Development

make help        # list all targets
make test        # build and run the test suite
make coverage    # line coverage report (LLVM)
make sanitize    # tests under ASan + UBSan
make lint        # clang-tidy
make misra       # MISRA C++:2023-oriented analysis
make fuzz        # libFuzzer robustness fuzzing (clang)
make doc         # API reference (Doxygen)
make format      # Uncrustify, in place
make format-check  # Uncrustify, dry-run; exits non-zero on diff

The API reference is published at https://reche23.github.io/real-regex/.

Select the compiler with make test CXX=g++-14. Every behaviour is tested at runtime and in constexpr (static_assert) under Clang and GCC; an equivalence suite checks the prefilter and fast paths never change results; a parity suite and a randomized differential fuzzer compare Python outputs against re.

CI exercises:

Platform Architecture Compiler
Linux x86-64 GCC, Clang
Linux AArch64 GCC
macOS Apple Silicon (arm64) Apple Clang
Windows x86-64 MSVC

IntelLLVM (icpx), x86-64 macOS and the BSDs share the Clang flag set and are supported by the build configuration but not exercised in CI.

License

MIT — Copyright (c) 2026 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

real_regex-2026.6.4.tar.gz (70.8 kB view details)

Uploaded Source

Built Distributions

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

real_regex-2026.6.4-cp310-abi3-win_amd64.whl (289.2 kB view details)

Uploaded CPython 3.10+Windows x86-64

real_regex-2026.6.4-cp310-abi3-win32.whl (287.1 kB view details)

Uploaded CPython 3.10+Windows x86

real_regex-2026.6.4-cp310-abi3-musllinux_1_2_x86_64.whl (1.6 MB view details)

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

real_regex-2026.6.4-cp310-abi3-musllinux_1_2_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

real_regex-2026.6.4-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (526.9 kB view details)

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

real_regex-2026.6.4-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (517.6 kB view details)

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

real_regex-2026.6.4-cp310-abi3-macosx_11_0_x86_64.whl (102.1 kB view details)

Uploaded CPython 3.10+macOS 11.0+ x86-64

real_regex-2026.6.4-cp310-abi3-macosx_11_0_arm64.whl (98.6 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for real_regex-2026.6.4.tar.gz
Algorithm Hash digest
SHA256 aeed3c3f7293844debaa8dfe71d1a41c902fdf76daa43b07163f15e3b9425b2f
MD5 2b9dc98f09630227efe39d5cf9e3839f
BLAKE2b-256 33022f7789c29dc8c6a4e555e8dd69c0af9671b4a677fa58becefafe6dd6fb01

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

File hashes

Hashes for real_regex-2026.6.4-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 91aa9c03296eafd0ecea4d0fa52149856c326f1daf9772426fdd7120fdafb736
MD5 5e0fa4bcf26c7956e1547dd968474e4d
BLAKE2b-256 3a24d6fb58d41623f363f23fe659729201af3a778a519508bd6e6da4c212c090

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

  • Download URL: real_regex-2026.6.4-cp310-abi3-win32.whl
  • Upload date:
  • Size: 287.1 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 real_regex-2026.6.4-cp310-abi3-win32.whl
Algorithm Hash digest
SHA256 e1439015eb526d9c91a575abdb2b28c224cbc71442e41e1a839cdd3f893b3c44
MD5 0d0acec087f1edf5f860d5a959e620df
BLAKE2b-256 c37047cd54156d867d4772b4ae6e0153886bab2783a78b7a5ee831d5aeac77f2

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

File hashes

Hashes for real_regex-2026.6.4-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a65ccb4940f90d7686f2490026346fa8c30ecd2031a316d01ef5bacc531c782b
MD5 97c7b61cec57e69c24b8455daeb0513d
BLAKE2b-256 033d8bde4e1e1455d627c9cd624a9c3710326bcc64b032f1883826c41d981d95

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

File hashes

Hashes for real_regex-2026.6.4-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a63d2ee59c400259011f135f1f4dfe8208a61b0a11869da094349eee52a3c0a9
MD5 6d4f2f9cfa4cab3ac791f7a49a46dc22
BLAKE2b-256 4b4fb032554f8bb2d320b355bd8fec7219d48fe891dc23a9e110314c10a1a383

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

File hashes

Hashes for real_regex-2026.6.4-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ddb8c76ff247e63f23fb6c82fe250548898aa2f118c67d3b7d14dfd1a0c544b7
MD5 84fbb0d9fa9eb10c39920ee7f3d25765
BLAKE2b-256 b3470e5abf776a94da84cd5effa95c2a9e58f52b859085d75c9267648c08842b

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

File hashes

Hashes for real_regex-2026.6.4-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8d6cdb6b6ca2c86dc2784f9c1947d43ceb7b029791f4a6d317985324c7d117f2
MD5 ea2adba5b75ff357de268e1d84ce6513
BLAKE2b-256 70bc26a40a8f27f7493ab4a65c492cc82519192195ae0f593212dfe4a29b488b

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

File hashes

Hashes for real_regex-2026.6.4-cp310-abi3-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 180be7c41749926fc8d72df359bac6a938010bde280c152b265a2889b3ecd015
MD5 9d7403cf68634affa4719c49ee58f511
BLAKE2b-256 87b7a777775a6cc40d3e8db5a82e32c3c077d8bfa7dad69f851a702f00f81ce5

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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

File details

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

File metadata

File hashes

Hashes for real_regex-2026.6.4-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 30c651b72e57fd0611a61c59ede546ffeb7d612d5dc48fe3a7bccfcfe3363286
MD5 57a22aa4f8bde7c64d3fc7c8cc26a989
BLAKE2b-256 33c08548455b15d71557674c4ecfb4065027f84c53ad1f9071e06292da1711c1

See more details on using hashes here.

Provenance

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

Publisher: release.yml on RECHE23/real-regex

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