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.5.tar.gz (71.5 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.5-cp310-abi3-win_amd64.whl (289.8 kB view details)

Uploaded CPython 3.10+Windows x86-64

real_regex-2026.6.5-cp310-abi3-win32.whl (287.6 kB view details)

Uploaded CPython 3.10+Windows x86

real_regex-2026.6.5-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.5-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.5-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (528.2 kB view details)

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

real_regex-2026.6.5-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (518.2 kB view details)

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

real_regex-2026.6.5-cp310-abi3-macosx_11_0_x86_64.whl (102.7 kB view details)

Uploaded CPython 3.10+macOS 11.0+ x86-64

real_regex-2026.6.5-cp310-abi3-macosx_11_0_arm64.whl (99.1 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: real_regex-2026.6.5.tar.gz
  • Upload date:
  • Size: 71.5 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.5.tar.gz
Algorithm Hash digest
SHA256 32392a0bd6bdbbe098e1757dfe2b625cb624bb117a41c7a488f99f593c4b4225
MD5 7eaaffcf71d7fca7e5f679d6c0967661
BLAKE2b-256 327b033f643eea8c94fa08d294df9d34c297a4e9ab81d1f238f2300e41740c26

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5.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.5-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for real_regex-2026.6.5-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 6cb40cd9709de2a33dfed7b2650f39b0a65672cbf84ccf2b9abdaa92d13c256f
MD5 8a8b27a35e50b2f915501a0b8cc7aee4
BLAKE2b-256 aa2ab60481c9620331a5a1572a0ae5ed167faf718a308d4fc95dd0ecfeb43e5a

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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.5-cp310-abi3-win32.whl.

File metadata

  • Download URL: real_regex-2026.6.5-cp310-abi3-win32.whl
  • Upload date:
  • Size: 287.6 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.5-cp310-abi3-win32.whl
Algorithm Hash digest
SHA256 a6f421ace98ea3328148e4835a3c02374422fa68ee3405a1b8b1f22edc4fcada
MD5 03f10fb8fef29f87acf151b3fafa881a
BLAKE2b-256 68a1fea996fa137f23a577894c2a5421fdfe74efe4ebf8d0f4610f1a9e3efa72

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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.5-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for real_regex-2026.6.5-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 43835632fcf9031cdc431306c5cdb5065d4b1156a12b104039c7ca28b6a6420a
MD5 cc1c08dca19e51654a0052b88acc0d0c
BLAKE2b-256 ccd340c8beb6a739bc553c683404a550606c263237ffbf2a553da7a86a256ed5

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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.5-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for real_regex-2026.6.5-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 d947e895e9155e9de0ccac1df04956bf07908690295217c047159f2971f4a22f
MD5 001653cf8e0df1fec7f57d52520fb658
BLAKE2b-256 ec2476cbefcccb3509f3fd556d8cf5a72cc3143a645382ae1fdb5fdb14cfd3e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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.5-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for real_regex-2026.6.5-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d9364f88cddecb8a86ee1a47dceb1a2e76f55d0e3dc370ae69cf5ff8cd4b348c
MD5 708c3ddb9396d8f91f5743071da49114
BLAKE2b-256 bd96fc57f285b6ba566613ef276a2aa3e174fa3b2a4372a6929036166b013e59

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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.5-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for real_regex-2026.6.5-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ee0ff3a986474abe4e64d04643b24c02329fa30b2dc3e48803ef610c2015311b
MD5 4d9961d70c2dd105aac1e2a6753f3089
BLAKE2b-256 497f7dff51dc4817a00863c00938b275f7dc5696b3094825ab475ec39a8ae9af

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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.5-cp310-abi3-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for real_regex-2026.6.5-cp310-abi3-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 0a1c7b66ea07745cd1332d5275369188990e6777ff18a8b39eb959c4fffdd3b6
MD5 190f7a447ffd77ec617d988cf7dc38cc
BLAKE2b-256 2bf1f6b18b7be93c9b08ef3e3ca8175b4bd2bae24e3c87157f909d047dd2e045

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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.5-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for real_regex-2026.6.5-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ad762aa15eabf31d7e219d23c41149667b43d287b57b0434beeaab339ddc02e6
MD5 8b09fab2e996b028370efde11f727853
BLAKE2b-256 7d1e02184bcc1dd282102f6a400632fb679c5a517ecff5d04ea5cde3d8a6eb1d

See more details on using hashes here.

Provenance

The following attestation bundles were made for real_regex-2026.6.5-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