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.

Over the benchmark suite (make bench-python), REAL is 1.98x faster than Python's re at the geometric mean, with identical outputs; the (a+)+b ReDoS case completes in microseconds where re takes over a second.

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)
(?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.

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

Release process (manual + tag-driven, for reliability):

  • Use calendar versioning YYYY.M.PATCH with monthly patch reset (e.g. 2026.6.0 for the first release of June 2026, then 2026.6.1 etc.; next month starts at .0).
  • Update the version in both places:
    • pyproject.toml (the one used by the release guard and PyPI)
    • python/real/__init__.py (the runtime __version__ exposed to users)
  • Commit the change (optionally include [release] in the message as a human signal or for future automation).
  • git tag v2026.6.0
  • git push origin main v2026.6.0

The tag triggers .github/workflows/release.yml:

  • check-version ensures the tag exactly matches the version in pyproject.toml.
  • It builds abi3 wheels with cibuildwheel (Linux/macOS/Windows) + sdist.
  • Publishes to PyPI using Trusted Publishing (OIDC) — no secrets.

We deliberately kept the process simple and explicit (no auto-bump on merge yet) to avoid accidental publishes and keep the history auditable. The tag-based guard + OIDC is the reliable core.

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.0.tar.gz (60.1 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.0-cp310-abi3-win_amd64.whl (237.6 kB view details)

Uploaded CPython 3.10+Windows x86-64

real_regex-2026.6.0-cp310-abi3-win32.whl (235.2 kB view details)

Uploaded CPython 3.10+Windows x86

real_regex-2026.6.0-cp310-abi3-musllinux_1_2_x86_64.whl (1.5 MB view details)

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

real_regex-2026.6.0-cp310-abi3-musllinux_1_2_aarch64.whl (1.4 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

real_regex-2026.6.0-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (478.6 kB view details)

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

real_regex-2026.6.0-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (470.8 kB view details)

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

real_regex-2026.6.0-cp310-abi3-macosx_11_0_x86_64.whl (49.1 kB view details)

Uploaded CPython 3.10+macOS 11.0+ x86-64

real_regex-2026.6.0-cp310-abi3-macosx_11_0_arm64.whl (45.6 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for real_regex-2026.6.0.tar.gz
Algorithm Hash digest
SHA256 98bb7836f17b9d5b64e94515886f33a4f80ef61c23705aa3553d026906238508
MD5 0e93b91e98c7c32b1bc03cb88b51871b
BLAKE2b-256 e34256412cb23f7e3aa5987ea59408d0bfd7a66d0ed4e954f2f3d9c579501517

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 3c1c20df3e12a55b123e87654271a6fb5eb44cb9700e0dc2082fb0cc4d99bc5d
MD5 59d45a66c5a580effa583e468d8878e7
BLAKE2b-256 f0d64b3f5d3d0b458e3eeddaea3bb2dcd6aef645155404bec780e4448d1a41ff

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: real_regex-2026.6.0-cp310-abi3-win32.whl
  • Upload date:
  • Size: 235.2 kB
  • Tags: CPython 3.10+, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-win32.whl
Algorithm Hash digest
SHA256 979d1f9ba732bdcdf69d39cfcaf4a3426b43a5adc88d277a1a9fa73a5e86e9ab
MD5 effbeba076c7bb4586f2504f464d5043
BLAKE2b-256 c043dba4abd48e9ace76f5bcfd9e10c88c2e09100c4316af5326d84cfb42ccfe

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7fcfa76ae0f71c5975d3a6246ba7e8141253756390a2ea9d7085b46e08a03e76
MD5 eae882c548faa7ae92fc2f93525ffc3b
BLAKE2b-256 d822c70b649b939c1387d8f3a87eabb72a4de81bd412ac6f615a16ceda106306

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 ea19589d8cb16a4a3ed2a049ddca4c5f39a0744645ad7415c57c39210a07e019
MD5 21afd270180f39553b308d0e1721647e
BLAKE2b-256 277eed7cc3e5077013485dcb90e74ee00975c651434dcf55a13676e358d7e04c

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7403335423a204bfbca93f48e437564d9366bc84fbbc37f0543b5287722d121a
MD5 581e4a6d73a6ea359f765841493960f2
BLAKE2b-256 eb798c7f3cf7635f8e37dac1fff3b02b60de38f57cce6430e5b870db1f34de1b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 5b1d77bc75d067c1132791cba31f99b650d3c1368aa6745f1be5093955365ac8
MD5 24590e8711d1f081cedccb8b9a4d52ce
BLAKE2b-256 7471b9d61ba1d8722e8d4b1ee1b60fbab0281078a20e0f53dc2ea466b3651781

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 b9bb80ce4befef2a32b77b17e1e9848b18f880d4aa82a604c62c6150b1b3ff48
MD5 3699912e7bf02555e7bb6076508a8201
BLAKE2b-256 ae0f3ef5f65577b6a5c819c73242e40b7d684b89b5414cb3d172ba7f53c6369d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for real_regex-2026.6.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7079efcfdf09701d69fac82893962050f7c7702edeac2f4ad0da51ba3914213b
MD5 0a6d314d8d07833c57975e84651ca0a2
BLAKE2b-256 7d28e5ad10b16ee15201621b9c12fa624c363e0066e8350836b16962c5351247

See more details on using hashes here.

Provenance

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