{"id":51394932,"url":"https://github.com/reche23/real-regex","last_synced_at":"2026-07-15T00:00:51.179Z","repository":{"id":364761614,"uuid":"1268531343","full_name":"RECHE23/real-regex","owner":"RECHE23","description":"Linear-time, ReDoS-safe C++20 header-only regex engine with bounded lookarounds + an re-compatible Python binding","archived":false,"fork":false,"pushed_at":"2026-07-04T00:16:25.000Z","size":1231,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-04T02:02:40.785Z","etag":null,"topics":["constexpr","cpp","cpp20","header-only","lexer","linear-time","pike-vm","python","redos","redos-safe","regex","regex-engine","regular-expressions","thompson-nfa"],"latest_commit_sha":null,"homepage":"https://reche23.github.io/real-regex/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RECHE23.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-13T16:37:17.000Z","updated_at":"2026-07-04T00:16:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"9b7c130c-34b3-44a6-94da-fce2b5f399b5","html_url":"https://github.com/RECHE23/real-regex","commit_stats":null,"previous_names":["reche23/real-regex"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/RECHE23/real-regex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RECHE23%2Freal-regex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RECHE23%2Freal-regex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RECHE23%2Freal-regex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RECHE23%2Freal-regex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RECHE23","download_url":"https://codeload.github.com/RECHE23/real-regex/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RECHE23%2Freal-regex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35483857,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-14T02:00:06.603Z","response_time":114,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["constexpr","cpp","cpp20","header-only","lexer","linear-time","pike-vm","python","redos","redos-safe","regex","regex-engine","regular-expressions","thompson-nfa"],"created_at":"2026-07-04T02:00:57.002Z","updated_at":"2026-07-15T00:00:51.172Z","avatar_url":"https://github.com/RECHE23.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# REAL\n\n[![CI](https://github.com/RECHE23/real-regex/actions/workflows/ci.yml/badge.svg)](https://github.com/RECHE23/real-regex/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/real-regex)](https://pypi.org/project/real-regex/)\n[![release](https://img.shields.io/github/v/release/RECHE23/real-regex)](https://github.com/RECHE23/real-regex/releases)\n[![C++20](https://img.shields.io/badge/C%2B%2B-20-blue)](https://en.cppreference.com/w/cpp/20)\n![header-only](https://img.shields.io/badge/header--only-yes-green)\n[![coverage](https://img.shields.io/badge/coverage-%E2%89%A595%25-brightgreen)](https://reche23.github.io/real-regex/)\n[![license](https://img.shields.io/badge/license-MIT-blue)](https://github.com/RECHE23/real-regex/blob/main/LICENSE)\n\nLinear-time, ReDoS-safe C++20 regex with bounded lookarounds — RE2's safety plus the\nlookarounds RE2 can't do — and a drop-in `re`-compatible Python binding.\n\n**Regular Expression Algorithmic Library** — a header-only C++20 regex engine, constexpr\nfrom end to end, with an `re`-compatible Python binding.\n\n- **Linear time, always.** The engine is a Pike VM (Thompson NFA simulation):\n  no backtracking, ReDoS-safe by construction.\n- **Constexpr-friendly.** Patterns known at compile time are parsed, compiled\n  and matched at compile time.\n- **Minimal memory.** Static (sizes fixed at compile time, zero allocation),\n  dynamic (storage sized exactly once at pattern compilation), or hybrid\n  (compile-time pattern, runtime text, zero heap allocation).\n- **Zero dependencies.** One include.\n\n## The problem\n\nBacktracking engines — PCRE, `std::regex`, Python `re` — are vulnerable to **ReDoS**: a\npattern like `(a+)+b` takes exponential time on a hostile input. The linear-time engines\nthat fix this — **RE2**, Rust's `regex` — buy safety by **dropping lookarounds** entirely.\n\nREAL gives you **both**: linear-time, ReDoS-safe matching *with* bounded lookarounds.\n\n## How it compares\n\n| | **REAL** | std::regex | RE2 | Rust `regex` | PCRE2-JIT | Python re |\n|---|:---:|:---:|:---:|:---:|:---:|:---:|\n| Linear-time, ReDoS-safe       | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |\n| Lookarounds                   | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ |\n| Possessive quantifiers / atomic groups | ✅⁶ | ❌ | ❌ | ❌ | ✅ | ✅ |\n| Header-only, zero-dependency  | ✅ | ✅¹ | ❌ | ❌ | ❌ | — |\n| Constexpr (compile-time match)| ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |\n| Drop-in Python `re`           | ✅² | ❌ | ❌ | ❌ | ❌ | ✅ |\n| Raw throughput                | fast³ | 6–55× slower⁴ | 1.2–9× slower | mixed⁵ | fast | slow |\n\n¹ part of the C++ standard library. ² for the supported subset (no backreferences, etc.).\n³ REAL-vs-PCRE2-JIT on class scans is **ISA-dependent**: on **x86-64** REAL leads (`[a-z]+` **1.9×**,\n`[0-9]+` **1.9×**), on **arm64** PCRE2's JIT retakes them (0.86–0.92×) — same engine, same version, purely the\nJIT's per-ISA codegen (§A). PCRE2-JIT leads straight-line literals / alternation / quantifiers on both.\n⁴ backtracking — **4.1 s where REAL takes 0.5 ms** on a `(a+)+b`-style input: the ReDoS-safety property,\nquantified, not an adjective.\n⁵ not one verdict: REAL leads class scans (**5–6×**) and dense-capture extraction (**3–6×**); the crate leads\nstraight-line literal / alternation (1.1–1.3×) and word-boundary; no-match is ≈ parity (1.6×). The per-line\nduel is in §E.\n⁶ Tier 1 (linear time): a single atom, or one wrapped in one capturing group — `[^x]*+`, `\\d++`,\n`(?\u003e\\w+)` — covers the dominant real-world shape. A compound/alternating body (`(?:ab)*+`, `(?\u003eab|a)`)\nis rejected as not supported yet, not silently accepted with wrong semantics — see `docs/divergences.dox`.\nExact multipliers, machines and methodology are in\n[`docs/BENCHMARKS.md`](https://github.com/RECHE23/real-regex/blob/main/docs/BENCHMARKS.md).\n\n**Every other engine that has lookarounds backtracks** (ReDoS-unsafe), and every linear-time\nengine drops them — **REAL is the only one with both**: bounded lookarounds *and* linear-time,\nReDoS-safe matching.\n\n## ReDoS, in numbers\n\nThe classic catastrophic-backtracking pattern `(a+)+b` over `\"a\"×N` (no `b`, so no match):\n\n| engine | input | time |\n| --- | --- | ---: |\n| **REAL** | N = 100 000 | **0.52 ms** — linear |\n| RE2 | N = 100 000 | 0.16 ms — linear |\n| `std::regex` | N = 26 | **4107 ms** (libstdc++ backtracks; libc++ *refuses* at \"complexity … exceeded\") |\n| Python `re` | n = 24 | **1398 ms** — and climbing exponentially |\n\nREAL and RE2 stay linear; the backtracking engines refuse or blow up at trivially small\ninputs. These figures are from [`docs/BENCHMARKS.md` §C](https://github.com/RECHE23/real-regex/blob/main/docs/BENCHMARKS.md); they depend on the\nplatform, pattern and input, so reproduce them locally with `make bench-engines` rather than\ntrusting a number here.\n\n## Quickstart\n\n**Python** — `pip install real-regex`, drop-in for the supported `re` subset:\n\n```python\nimport real as re                  # drop-in for the supported re subset\nre.search(r\"\\d+\", \"x42\")           # -\u003e a Match; findall / finditer / sub / split too\n```\n\n**C++** — header-only, C++20:\n\n```cmake\nfind_package(real CONFIG REQUIRED)\ntarget_link_libraries(app PRIVATE real::real)\n```\n\n```cpp\n#include \u003creal/real.hpp\u003e\nreal::regex re(\"[0-9]+\");\nre.search(\"x42\").matched();        // true\n```\n\nMore runnable programs — including the ReDoS demo — are in [`examples/`](https://github.com/RECHE23/real-regex/tree/main/examples).\n\n## Installation\n\n| Channel | Command |\n| --- | --- |\n| PyPI (Python + headers) | `pip install real-regex` |\n| Homebrew (macOS / Linux) | `brew install RECHE23/sci/real-regex` |\n| vcpkg | via the [`vcpkg-sci`](https://github.com/RECHE23/vcpkg-sci) registry → `\"dependencies\": [\"real-regex\"]` |\n| CMake FetchContent | `FetchContent_Declare(real GIT_REPOSITORY https://github.com/RECHE23/real-regex GIT_TAG v2026.7.41)` |\n| Vendored | copy `include/` and compile with `-std=c++20 -I include` |\n\nREAL is header-only, so \"installing\" just places the headers and the package metadata where a\nconsumer can find them. After `cmake --install \u003cbuild\u003e --prefix \u003cprefix\u003e`, there are three\nways to consume it from C++:\n\n```cmake\n# 1. CMake — find_package against the installed config package:\nfind_package(real CONFIG REQUIRED)\ntarget_link_libraries(app PRIVATE real::real)\n```\n\n```sh\n# 2. pkg-config — for Make / Meson / autotools (and the system packagers):\nc++ -std=c++20 $(pkg-config --cflags real) app.cpp -o app\n```\n\n```sh\n# 3. Direct copy — vendor include/ into your tree, no build system needed:\nc++ -std=c++20 -I/path/to/real/include app.cpp -o app\n```\n\n`real::real` is also available without installing, via `add_subdirectory` or `FetchContent`.\n\nREAL requires **C++20 or later**. Every header asserts it (`#include \u003creal/...\u003e`\nfails fast with a clear message under an older standard), and pkg-config has no\nfield to convey a language standard — so the consumer must pass `-std=c++20` (or\nnewer) itself, as shown above.\n\nThe header-only library builds and installs with nothing but a C++20 compiler and\nCMake. The [SciForge](https://github.com/RECHE23/sciforge) test harness is needed\n**only** to build the test suite (`BUILD_TESTING=ON`, the default for development\nand CI), the Python binding and the CI scripts — never the library. Packagers\nconfigure with `-DBUILD_TESTING=OFF` to install the library alone, with no\nSciForge dependency.\n\nThe Homebrew formula consumes the library via CMake `find_package(real)`,\n`pkg-config --cflags real`, or `-I\"$(brew --prefix real-regex)/include\"` — see the\n[tap README](https://github.com/RECHE23/homebrew-sci) for usage.\n\n## Documentation\n\n- **API reference \u0026 design** (Doxygen — \"How REAL Works\", the internals tour): \u003chttps://reche23.github.io/real-regex/\u003e\n- **Performance** — the measured baseline, with the machine and engine versions and the rust-crate duel:\n  [`docs/BENCHMARKS.md`](https://github.com/RECHE23/real-regex/blob/main/docs/BENCHMARKS.md)\n- **Compatibility** (`re` and `std::regex`) — the supported subset and every intentional divergence:\n  [`docs/COMPATIBILITY.md`](https://github.com/RECHE23/real-regex/blob/main/docs/COMPATIBILITY.md)\n- **Tests \u0026 conformance** — the differential harnesses and the coverage/gate policy:\n  [`docs/TESTS.md`](https://github.com/RECHE23/real-regex/blob/main/docs/TESTS.md)\n- **Python** — `pip install real-regex`, the `re` drop-in: [on PyPI](https://pypi.org/project/real-regex/).\n\n`make python-bench` compares throughput against Python's `re`, and `make bench-engines` against `std::regex`,\nPCRE2 and RE2 in one C++ process (match counts checked equal). Figures depend on the platform, pattern and\ninput — reproduce them locally rather than trusting a number here. The GitHub releases page is the changelog.\n\n## Supported syntax\n\n| Syntax | Meaning |\n|---|---|\n| `abc` | literal bytes (UTF-8 patterns match their UTF-8 bytes) |\n| `\\.` `\\*` `\\\\` … | escaped metacharacter, matched literally |\n| `.` | any codepoint except `\\n` |\n| `[abc]` `[a-z]` `[^abc]` `[é]` `[à-ÿ]` | character class, ASCII **and** non-ASCII code-point members / ranges (str mode); `[^…]` matches any code point outside the set |\n| `\\w \\W \\d \\D \\s \\S` | word / digit / space classes — Unicode in text mode (like `re`), ASCII in bytes mode or under `a` |\n| `\\n \\t \\r \\f \\v \\a \\0` `\\xHH` | control and hex escapes |\n| `x*` `x+` `x?` | quantifiers (greedy; append `?` for lazy) |\n| `x{n}` `x{n,}` `x{,m}` `x{n,m}` | counted repetition (greedy or lazy; counts capped at 1000) |\n| `x*+` `x++` `x?+` `x{n,m}+` | possessive quantifiers (no give-back), and `(?\u003ex)` atomic groups — over a single atom or one wrapped in one capturing group; linear time, beyond RE2/rust-regex |\n| `a\\|b` | alternation, leftmost branch preferred |\n| `(…)` `(?:…)` | capturing / non-capturing group |\n| `(?P\u003cname\u003e…)` `(?\u003cname\u003e…)` | named capturing group (Python and .NET styles) |\n| `^` `$` | line/text anchors (Python semantics: `$` also matches before a final `\\n`) |\n| `\\A` `\\Z` | strict text start / end |\n| `\\b` `\\B` | word boundary / non-boundary (Unicode word characters in text mode, ASCII in bytes mode or under `a`) |\n| `\\\u003c` `\\\u003e` | start / end of word (REAL extension, not in Python `re`) |\n| `(?imsxa)` prefix | global flags: `i` case-insensitive (Unicode fold in text mode), `m` multiline, `s` dotall, `x` verbose (ignore unescaped whitespace and `#` comments outside classes), `a` ASCII (`re.A`: keep `\\w \\W \\d \\D \\s \\S \\b \\B \\\u003c \\\u003e` and icase folding ASCII, even in text mode) — also `real::flags` on the constructor |\n\n**Bounded lookarounds** match in linear time — REAL's differentiator: lookahead `(?=…)`/`(?!…)` and\nlookbehind `(?\u003c=…)`/`(?\u003c!…)`, each length-bounded and capture-free (variable-width lookbehind such as\n`(?\u003c=a|bb)` is accepted, beyond `re`/PCRE's fixed-width limit). **Unicode property classes** `\\p{…}`\nmatch natively and linearly: General_Category, Script (`sc=`, short ISO codes), Script_Extensions (`scx=`),\nand 63 binary properties (`\\p{Alphabetic}`, `\\p{Emoji}`, …) — a superset of `re`, which has none of this.\nUnsupported syntax —\nbackreferences, conditional groups, a possessive/atomic construct over a compound body (`(?:ab)*+`,\n`(?\u003eab|a)`, not yet — see `docs/divergences.dox`) — is rejected with `real::regex_error`, never a silent\ndivergence.\n\nMatching is UTF-8 code-point-aware: classes and `.` accept non-ASCII (`[é]`, `[à-ÿ]`), `\\w \\d \\s \\b` and\n`IGNORECASE` are Unicode in text mode (ASCII under `flags::ascii` / `re.A`), and no match boundary splits a\ncharacter. The full Unicode model, the code-point-mode migration notes, and every intentional divergence\nfrom `re` (e.g. nullable-loop empty captures) are in\n[`docs/COMPATIBILITY.md`](https://github.com/RECHE23/real-regex/blob/main/docs/COMPATIBILITY.md).\n\n## C++ API\n\n```cpp\n#include \u003creal/real.hpp\u003e\n\nreal::regex rx(\"hello\");     // runtime pattern, storage sized exactly once\nrx.match(\"hello world\");     // anchored at the start   (Python re.match)\nrx.fullmatch(\"hello\");       // whole text              (Python re.fullmatch)\nrx.search(\"say hello\");      // leftmost match anywhere (Python re.search)\n```\n\n`match`/`fullmatch`/`search` return a `real::match_result`: `matched()`,\n`operator bool`, `start(g)`, `end(g)`, `m[g]` (a `std::string_view` into the\nsearched text, which must outlive the result), and the same accessors by group\nname (`m[\"year\"]`, `group_index`).\n\n```cpp\nfor (auto\u0026 m : rx.find_iter(text)) { … }      // lazy, Python finditer rules\nrx.find_all(text);                            // eager vector\u003cmatch_result\u003e\nrx.replace(text, \"$2:$1\");                    // $\u0026, $1…, ${name}, $$ — re.sub\nrx.replace(text, \"#\", 2);                     // count limit\nrx.split(text);                               // Python re.split, with groups\n```\n\nEmpty matches follow Python's rules: they are yielded (even right after a\nnon-empty match) and the scan then advances one whole codepoint.\n`find_iter`/`find_all` cannot be called on a temporary regex, and\n`match`/`search`/`split` cannot take a temporary `std::string`.\n\n### Drop-in for std::regex\n\nAlready using `\u003cregex\u003e`? `real::compat` is a drop-in for the `\u003cregex\u003e` surface on the `char` path —\nswap the include and alias the namespace, and your code keeps compiling:\n\n```cpp\n#include \u003creal/std/regex.hpp\u003e   // was: #include \u003cregex\u003e\nnamespace re = real::compat;    // then re::regex / re::smatch / re::regex_search / …\n```\n\nIt runs your pattern on REAL — linear-time, ReDoS-safe — wherever that is provably identical to\n`std::regex`, and falls back to `std::regex` everywhere else: **behave identically, never a silent\ndivergence**. See the [migration tour](https://reche23.github.io/real-regex/std_regex_dropin.html) and\nthe full [`docs/COMPATIBILITY.md`](https://github.com/RECHE23/real-regex/blob/main/docs/COMPATIBILITY.md).\n\n### Three memory modes\n\n```cpp\n// Static: pattern compiled at compile time into exactly-sized constexpr\n// arrays; an invalid pattern is a *compile error*.\nconstexpr real::static_regex\u003c\"(\\\\d{4})-(\\\\d{2})\"\u003e date;\nstatic_assert(date.search(\"on 2026-06-10\")[1] == \"2026\");  // constexpr match\n\n// Hybrid: compile-time pattern, runtime text — matching performs zero heap\n// allocations (state lives on the stack).\ndate.search(runtime_text);\n\n// Dynamic: everything at runtime; the program is sized exactly once at\n// compilation, match state is per-run scratch.\nreal::regex rx2(user_pattern, real::flags::icase);\n```\n\n### DFA over a rule set (opt-in)\n\n```cpp\n#include \u003creal/dfa.hpp\u003e   // opt-in: not pulled in by \u003creal/real.hpp\u003e\n\nconst std::array patterns {real::regex(\"\\\\s+\"), real::regex(\"[0-9]+\"),\n                           real::regex(\"[A-Za-z_][A-Za-z0-9_]*\")};\nreal::dfa d(std::span\u003cconst real::regex\u003e(patterns));   // built once, then immutable\nauto hit = d.match(\"foo\");   // -\u003e {rule_index = 2, length = 3}; std::nullopt if none\n```\n\n`real::dfa` fuses a set of patterns into one **capture-free, maximal-munch DFA**: a\nsingle left-to-right pass recognizes the winning rule (longest match; ties to the\nearliest pattern; empty excluded) instead of running each pattern in turn — linear-time\nand ReDoS-safe like the engine, built at run time and then immutable. It is the\naccelerated rule dispatch a lexer wants (SciLex's `dfa_modes` is built on it). A pattern\ncarrying a zero-width assertion no DFA can represent (`$`, `\\b`, multiline `^`/`$`)\nthrows `real::dfa_error`; lazy and greedy accept the same language, so feed it\nlongest-match-faithful rules.\n\n### Multi-pattern set (`real::regex_set`)\n\nFor **which-matched** multi-pattern queries (which patterns hit the text at least once —\nRE2::Set / rust `RegexSet` style), include `\u003creal/regex_set.hpp\u003e`:\n\n```cpp\n#include \u003creal/regex_set.hpp\u003e\nreal::regex_set set {\"error|warn\", \"[0-9]{4}-[0-9]{2}-[0-9]{2}\", \"absent\"};\n// or: span/array of string_view, or span/vector of string\nset.is_match(log_line);          // any-match (stops at first hit)\nauto bits = set.matches(log_line); // construction-order bitset\n```\n\nStage-1 is N independent `search` walks with per-pattern early-exit — **not**\n`real::dfa` (munch one-winner) and not yet a fused single-pass. Compile fails the\nwhole set if any pattern is invalid.\n\n## Python binding\n\nAn `re`-compatible module backed by the C++ engine (CPython Limited API, one\nabi3 extension, zero dependencies):\n\n```python\nimport real\n\nreal.search(r\"(?P\u003cy\u003e\\d{4})-(?P\u003cm\u003e\\d{2})\", \"on 2026-06-10\").groupdict()\nreal.compile(r\"\\w+\").findall(text)         # findall/finditer/split/sub/subn\nreal.sub(r\"\\s+\", \" \", text)                # templates: \\1, \\g\u003cname\u003e, callables\nreal.search(r\"(\\w+)=(\\w+)\", \"k=v\").expand(r\"\\2:\\1\")   # Match.expand -\u003e \"v:k\"\nreal.compile(rb\"[^;]+\").findall(raw)       # bytes patterns: raw-byte semantics\n```\n\n`str` matching is UTF-8 with character indices in `start/end/span`; `bytes`\npatterns get `re`'s exact raw-byte semantics. Unsupported `re` features raise\n`real.error` at compile time. Build with `make python-build \u0026\u0026 make python-test`.\n\n`pip install real-regex` installs one `cp310-abi3` wheel per platform\n(CPython 3.10+; the self-contained sdist compiles where no wheel matches).\n\n### Embedding the C++ library through the Python package\n\nThe wheel also ships the C++ headers, so a project can compile against REAL\nlocated through its Python install — the convention used by `petsc4py` and\n`slepc4py`:\n\n```bash\nc++ -std=c++20 $(python -c \"import real; print(real.get_include())\") app.cpp\n```\n\n`real.get_config()` returns the version, the include directory and the\nrequired C++ standard.\n\n**Releasing.** Run `make release`. It computes the next calendar version\n`YYYY.M.PATCH` — the patch resets each month, the first release of a month is\n`.0` (PEP 440 drops leading zeros, so `2026.6.1`, never `2026.06.001`) — bumps\nit in `pyproject.toml` and `bindings/python/real/__init__.py`, then commits, tags and\npushes. The tag drives `release.yml`, which checks the tag matches the version,\nbuilds abi3 wheels (`cibuildwheel`, Linux/macOS/Windows) and the sdist, and\npublishes to PyPI via Trusted Publishing (OIDC, no stored secret). The pushed\ntag is the single thing that triggers a publish.\n\n## Development\n\n```bash\nmake help        # list all targets\nmake test        # build and run the test suite\nmake coverage    # line coverage report (LLVM)\nmake sanitize    # tests under ASan + UBSan\nmake lint        # clang-tidy\nmake misra       # MISRA C++:2023-oriented analysis\nmake fuzz        # libFuzzer robustness fuzzing (clang)\nmake doc         # API reference (Doxygen)\nmake format      # Uncrustify, in place\nmake format-check  # Uncrustify, dry-run; exits non-zero on diff\n```\n\nThe API reference is published at \u003chttps://reche23.github.io/real-regex/\u003e.\n\nSelect the compiler with `make test CXX=g++-14`. Every behaviour is tested at\nruntime and in constexpr (`static_assert`) under Clang and GCC; an equivalence\nsuite checks the prefilter and fast paths never change results; a parity suite\nand a randomized differential fuzzer compare Python outputs against `re`.\n\n**Coverage bar.** REAL holds a high line-coverage bar (mid-90s on `include/`),\nchecked with `make coverage`. It deliberately does *not* adopt the\n100%-on-all-four-dimensions (lines, functions, regions, *and* branches) gate used\nby the SciLang-stack libraries built on top of it: as the oldest and most complex\nengine here, its dual runtime/constexpr execution and Pike-VM branch structure\nleave some regions and branches impractical to drive to 100% without contrived\ntests. That lower-but-still-high bar is a deliberate, documented exception, not an\noversight — REAL keeps its own gate (above) and its broad public CI.\n\nCI exercises:\n\n| Platform | Architecture | Compiler |\n|----------|--------------|----------|\n| Linux    | x86-64       | GCC, Clang |\n| Linux    | AArch64      | GCC |\n| macOS    | Apple Silicon (arm64) | Apple Clang |\n| Windows  | x86-64       | MSVC |\n\nIntelLLVM (`icpx`), x86-64 macOS and the BSDs share the Clang flag set and are\nsupported by the build configuration but not exercised in CI.\n\n## License\n\nMIT — Copyright (c) 2026 René Chenard\n\n## Author\n\nRené Chenard\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freche23%2Freal-regex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freche23%2Freal-regex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freche23%2Freal-regex/lists"}