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, re.X, pos/endpos. The planned next step is a lazy DFA for the dense-candidate cases where re is still ahead.

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)
(?ims) prefix global flags: i case-insensitive (ASCII), m multiline, s dotall — 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)

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.2.tar.gz (64.9 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.2-cp310-abi3-win_amd64.whl (286.3 kB view details)

Uploaded CPython 3.10+Windows x86-64

real_regex-2026.6.2-cp310-abi3-win32.whl (283.5 kB view details)

Uploaded CPython 3.10+Windows x86

real_regex-2026.6.2-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.2-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.2-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (521.3 kB view details)

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

real_regex-2026.6.2-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (515.8 kB view details)

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

real_regex-2026.6.2-cp310-abi3-macosx_11_0_x86_64.whl (98.0 kB view details)

Uploaded CPython 3.10+macOS 11.0+ x86-64

real_regex-2026.6.2-cp310-abi3-macosx_11_0_arm64.whl (94.3 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: real_regex-2026.6.2.tar.gz
  • Upload date:
  • Size: 64.9 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.2.tar.gz
Algorithm Hash digest
SHA256 f9c1015fc4d6e4e0892599f712f64e2be5a40fb630aae789cb7fbff1d181221f
MD5 a6aa558dbb1f07e49ffd50139bdfbd48
BLAKE2b-256 97be55927da5d8d30e07cd4d2d4155a9149f0dcd3d46097d5abc1bd79315acc2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.2-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 8b19b3a700784be4d24244f54d714acbe9a939f9bf9772233c194c5aad346f13
MD5 b2fe71ded1448ca5aaefad6f60c9d5b5
BLAKE2b-256 a314a603dad97034526a1bfbf818efedb91808a9bc48fc9e7e070b70179afcf0

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: real_regex-2026.6.2-cp310-abi3-win32.whl
  • Upload date:
  • Size: 283.5 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.2-cp310-abi3-win32.whl
Algorithm Hash digest
SHA256 ec91ac0bc5a652280f76a9e1689b4826ee1c652abd3d82a92b7fe3d45efba4c7
MD5 da194404a9b5833d5c462b5ddcbc6812
BLAKE2b-256 40d513c1964efca7834fd9be2732bbaa6a6fa630ab1d0e6d54b9084941c0ed12

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.2-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8436cb277c0ceae0f43dd8da70d2258216d71b4e7f8c1fa64abf77750dd5b7a1
MD5 136d78dfcf4af6ac2f0e2072502459c3
BLAKE2b-256 7cb209f23c2380b1fad522c4064fd2dd0bae42a833eb1ab67d8e0c726d9cd01d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.2-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 b1194a01959f7c651ac5f52d1999236201afde28081c48e1ed3f4d279f9794be
MD5 298005852795f32dca8ef4a3a149f4f4
BLAKE2b-256 ffd7d40e98695d191c33fb6aab868ef11a264bcb666d8003aab550111b3832d6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.2-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 26d85edf1d6802dfebb15dc1104ebc9bdcd4797cefb833f314ea968901066a16
MD5 a715b7f1059debeff4402ea9574ac986
BLAKE2b-256 5a073fa54cd14ae7fa2f70990d46875bf84f596e56075f9db743b78751ae0690

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.2-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2c39092f965324f0eb9e2361fc89964b98cabd3e493b987d8067f878327d9369
MD5 b7e4d2109163312880356b7dfbc58a16
BLAKE2b-256 f7cac78a97654533c325cdc7874e5c1bc13ca5923e88ef1eef973aca2ba98b92

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.2-cp310-abi3-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 921b7e593adc044edd58dfb47d4acac63e29932a5be5dd2a3b47c6b97db66dd0
MD5 51f2555e7954c696b4921d9248f3bbb5
BLAKE2b-256 5c1d81f36f76d8f3bffa660bec98a8179d7c2b94f9bcd16ceacd57cbd57ab98c

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.2-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5442044b43ad5cb920602e11b82a592103c9683077d9f6a5f06598c4faa1ef61
MD5 05a856deea32c84ab4c672de6ef621b3
BLAKE2b-256 f52f9f1f2c7b0b1b9766eff4429fef7d490a73c183cf83dcd36d4d0e63fda264

See more details on using hashes here.

Provenance

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