feat: add multi-engine regex flavour support
This commit is contained in:
@@ -1,75 +1,87 @@
|
||||
# Flavour support
|
||||
|
||||
| Flavour | Syntax | Execution | Replacement | Captures | Trace | Analysis | Generated cases | Native offsets |
|
||||
| ---------------------- | ------------------------------------------------------------ | --------------------------------------------------------- | ---------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------- | -------------- |
|
||||
| ECMAScript | regexpp 4.12.2; explanations partial/feature-matrix tested | Current browser `RegExp`; conformance tested | Bounded ECMAScript `GetSubstitution` | Named/numbered; final repeated capture; no history | Unavailable | Experimental static heuristics + bounded native probes | Bounded normalized-AST sampling; actual-engine verified | UTF-16 |
|
||||
| PCRE2 10.47 | Application lexical provider partial; compiler authoritative | Pinned 8-bit WASM; bounded/killable/conformance tested | Native bounded `pcre2_substitute()` loop | Native named/numbered records; no capture history | Bounded reported automatic callouts; derived movement labels | Unavailable; ECMAScript heuristics are never applied | Unavailable; structural syntax provider is partial | UTF-8 bytes |
|
||||
| Python `re` | Application lexical provider partial; compiler authoritative | CPython 3.14.2 in self-hosted Pyodide 314.0.3 | Native bounded `re` expansion | Native named/numbered spans; no capture history | Unavailable | Unavailable; ECMAScript heuristics are never applied | Unavailable; structural syntax provider is partial | Code points |
|
||||
| Java `java.util.regex` | Application lexical provider partial; compiler authoritative | TeaVM 0.15.0 class library; bounded/killable; not OpenJDK | TeaVM single-digit `$n`; no `${name}` | Native numbered ranges; lexical names; no history | Unavailable | Unavailable; ECMAScript heuristics are never applied | Unavailable; structural syntax provider is partial | UTF-16 |
|
||||
| PCRE | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable |
|
||||
| Go `regexp` | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Planned bytes |
|
||||
| Rust `regex` | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Unavailable | Planned bytes |
|
||||
| .NET | Unavailable | Unavailable | Unavailable | Planned capture history | Unavailable | Unavailable | Unavailable | Planned UTF-16 |
|
||||
Version 0.4.0 exposes twelve executable profiles. “Partial lexical provider”
|
||||
means that Regex Tools recognizes common structure and replacement tokens for
|
||||
explanation only; the named runtime compiler and replacement operation remain
|
||||
authoritative.
|
||||
|
||||
ECMAScript tests cover its complete exposed flag matrix, internal indices,
|
||||
zero-length iteration, captures, lookbehind, backreferences, Unicode properties
|
||||
and bounded replacement.
|
||||
| Profile | Syntax and execution identity | Replacement | Captures and native offsets |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| JavaScript (ECMAScript) | regexpp 4.12.2 with ECMAScript 2025 syntax; current browser `RegExp` executes | Bounded ECMAScript `GetSubstitution` | Named/numbered, final repeated capture; UTF-16 |
|
||||
| PCRE2 | Partial provider; official standalone PCRE2 10.47 8-bit WASM executes in mandatory UTF/UCP mode | Native bounded `pcre2_substitute()` loop | Native named/numbered records, no history; UTF-8 bytes |
|
||||
| PHP | Partial provider; actual PHP 8.5.8 `preg_*` in `@php-wasm/web-8-5` 3.1.46, reporting PCRE2 10.44 | Fixed bounded PHP-token expansion; load-time `preg_replace()` parity | Native named/numbered records, no history; UTF-8 bytes |
|
||||
| Perl | Partial provider; actual Perl 5.28.1 through legacy WebPerl 0.09-beta | Fixed bounded literal/`$$`/`$n`/`${name}` expansion; arbitrary Perl expressions unavailable | Native numbered spans plus bounded name annotations, no history; Unicode code points |
|
||||
| Python | Partial provider; CPython 3.14.2 `re` in Pyodide 314.0.3 | Native bounded `re` expansion | Native named/numbered spans, no history; Unicode code points |
|
||||
| Ruby | Partial provider; CRuby 4.0.0 `Regexp` in ruby.wasm 2.9.3-2.9.4 | Native `gsub`/`sub` iteration plus bounded CRuby 4.0.0-compatible expansion | Native named/numbered spans, no history; Unicode code points |
|
||||
| Java | Partial provider; TeaVM 0.15.0 `java.util.regex`, not OpenJDK | TeaVM single-digit `$n`; no `${name}` | Native numbered ranges plus lexical names, no history; UTF-16 |
|
||||
| C++ | Partial provider; Emscripten 6.0.4 libc++ `std::wregex`; modified ECMAScript grammar by default | Fixed bounded formatter; load-time libc++ `match.format` parity | Numbered captures only, no history; 32-bit `wchar_t` code points |
|
||||
| Go | Partial provider; Go 1.26.5 standard-library `regexp` with RE2 syntax | Fixed bounded expansion; load-time `regexp.ExpandString` parity | Native named/numbered records, no history; UTF-8 bytes |
|
||||
| Rust | Partial provider; Rust `regex` crate 1.13.1, built with rustc 1.97.1 | Fixed bounded expansion; load-time `Captures::expand` parity | Native named/numbered records, no history; UTF-8 bytes |
|
||||
| .NET | Partial provider; .NET 10.0.10 `System.Text.RegularExpressions`, invariant culture | Fixed streaming .NET-token expansion with load-time native `Match.Result` parity | Named/numbered final records, no capture history in this adapter; UTF-16 |
|
||||
| Scala/JVM compatibility | Partial provider; explicitly shares TeaVM 0.15.0 `java.util.regex`; no Scala runtime | Same TeaVM single-digit `$n` subset; no `${name}` | Same ranges as the TeaVM Java adapter; UTF-16 |
|
||||
|
||||
PCRE2 tests cover `g`, `i`, `m`, `s`, `x`, `U`, `J`, mandatory UTF/UCP,
|
||||
branch-reset groups, recursion, `\K`, duplicate names, native substitution,
|
||||
astral byte/UTF-16 ranges, zero-length iteration, compile errors, match limits
|
||||
and result/output truncation. Trace tests cover reported automatic callouts,
|
||||
bounded mark copying, native stop at the complete-event cap, compile ranges,
|
||||
worker loading and browser rendering.
|
||||
## Flags and options
|
||||
|
||||
Python tests cover application-level `g`, CPython flags `a`, `i`, `m`, `s` and
|
||||
`x`, Python-only named-group/replacement syntax, native `re` substitution,
|
||||
astral code-point/UTF-16 normalization, zero-length iteration, compile errors,
|
||||
result limits, runtime identity and worker recovery.
|
||||
- JavaScript exposes `g`, `i`, `m`, `s`, `u`, `v`, `y` and `d`; `u` and `v`
|
||||
are mutually exclusive.
|
||||
- Standalone PCRE2 exposes application iteration `g` plus `i`, `m`, `s`, `x`,
|
||||
`U` and `J`, with match-step, depth and heap limits. UTF/UCP is mandatory.
|
||||
- PHP exposes application iteration `g` plus the reviewed `preg` modifiers
|
||||
`i`, `m`, `s`, `x`, `u`, `U`, `A`, `D`, `J`, `n` and `r`. PHP's `u` is not
|
||||
conflated with standalone PCRE2's mandatory UTF/UCP configuration.
|
||||
- Legacy Perl exposes `g`, `i`, `m`, `s`, `x`, `n` and one of `a`, `d`, `l` or
|
||||
`u`. The two-character `/aa` mode is not exposed.
|
||||
- Python exposes application iteration `g` plus `a`, `i`, `m`, `s` and `x`.
|
||||
- Ruby exposes application iteration `g` plus `i`, `m` and `x`; Ruby `m`
|
||||
includes dot-all behavior.
|
||||
- Java and Scala compatibility expose application iteration `g` plus TeaVM
|
||||
`Pattern` flags `i`, `d`, `m`, `s`, `u`, `x` and the documented `U`
|
||||
compatibility request.
|
||||
- C++ exposes application iteration `g` plus `i`, `n`, `o` and `c`, and a
|
||||
required grammar option: `ECMAScript`, `basic`, `extended`, `awk`, `grep` or
|
||||
`egrep`.
|
||||
- Go exposes application iteration `g` plus `i`, `m`, `s` and `U`.
|
||||
- Rust exposes application iteration `g` plus `i`, `m`, `s`, `U`, `u`, `x` and
|
||||
`R`; Unicode is enabled by default.
|
||||
- .NET exposes application iteration `g` plus `i`, `m`, `s`, `n`, `x`, `r`,
|
||||
`c` and `b`. Execution is always culture invariant; `c` makes that fixed
|
||||
compatibility choice explicit.
|
||||
|
||||
Java tests cover application-level `g`, TeaVM `Pattern` flags, Java named-group
|
||||
syntax, TeaVM's native single-digit `$n` `Matcher` replacement, explicit
|
||||
rejection of unsupported `${name}`, astral UTF-16 ranges, zero-length
|
||||
iteration, compile errors, result limits, module identity and worker recovery.
|
||||
The runtime and UI explicitly report that TeaVM 0.15.0 is not OpenJDK and does
|
||||
not implement OpenJDK `Pattern.UNICODE_CHARACTER_CLASS`; `U` is a compatibility
|
||||
request rather than an exact implementation of that flag.
|
||||
## Verified boundaries
|
||||
|
||||
ECMAScript static findings and generated-input timing observations are
|
||||
advisory. They describe only the selected ECMAScript 2025 pattern, browser
|
||||
runtime and bounded inputs; they are not proofs of safety or general
|
||||
complexity.
|
||||
Every adapter has focused identity, request and result-contract tests.
|
||||
Conformance and browser suites exercise compilation errors, bounded matching,
|
||||
zero-length iteration, range normalization, replacement and worker recovery
|
||||
across the profile set. Pack verifiers additionally check self-hosted assets,
|
||||
metadata, closed-file-set checksums and applicable licences/notices.
|
||||
|
||||
ECMAScript generated-case version 1 uses only a complete accepted normalized
|
||||
AST, an explicit deterministic seed and bounded sampling strategies. Every
|
||||
retained positive or negative label is confirmed by the actual selected
|
||||
browser engine. PCRE2, Python and Java generation are unavailable because
|
||||
their current lexical providers are intentionally partial; ECMAScript behavior
|
||||
is never relabelled as another flavour.
|
||||
TeaVM supplies an Apache Harmony-derived class library. It is not OpenJDK and
|
||||
does not implement OpenJDK `Pattern.UNICODE_CHARACTER_CLASS`; `U` means the
|
||||
documented TeaVM compatibility behavior in both the Java and Scala profiles.
|
||||
The Scala profile also does not implement `scala.util.matching.Regex` wrapper
|
||||
or extractor APIs.
|
||||
|
||||
The PCRE2, Python and Java explanation providers deliberately do not invent
|
||||
full structural coverage. PCRE2 branch-reset numbering is omitted from the
|
||||
syntax tree, while actual capture numbers, names and ranges still come from the
|
||||
selected runtime result.
|
||||
The Perl target is intentionally legacy. Its unmodified WebPerl loader contains
|
||||
one `eval(code)` site in an optional Perl-to-JavaScript interoperability import.
|
||||
The fixed Regex Tools bridge does not load that facility, accepts pattern and
|
||||
replacement values only as JSON data, uses `no re 'eval'`, rejects `(?{...})`
|
||||
and `(??{...})`, and passes the documented CSP smoke without broad
|
||||
`'unsafe-eval'`.
|
||||
|
||||
ECMAScript and PCRE2 support exact-request comparison for syntax acceptance,
|
||||
engine compilation, matches, captures and engine-native replacement. Results
|
||||
align by normalized UTF-16 ranges while retaining each native offset model.
|
||||
Timeout, cancellation, rejection and truncation are never presented as
|
||||
equivalent results.
|
||||
## Feature scope
|
||||
|
||||
Pattern formatting is available only for an exact accepted ECMAScript regexpp
|
||||
snapshot. It canonicalizes literal slashes and raw control/line-separator
|
||||
representations, then requires paired actual-engine and applicable exact-test
|
||||
validation before apply. PCRE2, Python and Java formatting is unavailable
|
||||
because those providers are deliberately partial; their syntax is never
|
||||
treated as ECMAScript.
|
||||
Static findings, bounded growth probes, benchmarks, generated cases and
|
||||
formatting are ECMAScript-only. Generated-case version 1 requires the complete
|
||||
accepted regexpp AST and verifies every retained label through the actual
|
||||
browser engine. No partial provider is passed through that generator or
|
||||
formatter.
|
||||
|
||||
Subject minimization accepts only the verified ECMAScript and PCRE2 paths.
|
||||
Python and Java selections are disabled rather than being minimized through a
|
||||
different flavour. Semantic comparison is likewise an explicit
|
||||
ECMAScript/PCRE2 operation; it is not a generic four-way equivalence checker.
|
||||
Automatic-callout tracing and reviewed C17 code generation are standalone
|
||||
PCRE2-only. The PHP profile does not reuse the standalone PCRE2 10.47 trace or
|
||||
code-generation path because its authoritative engine is PHP `preg` with
|
||||
PCRE2 10.44.
|
||||
|
||||
PCRE2 is the only current code-generation target. The reviewed C17 generator is
|
||||
pinned to the PCRE2 10.47 8-bit API; other language generators remain
|
||||
unavailable until they pass equivalent escaping and named-toolchain gates.
|
||||
Exact-request semantic comparison and subject minimization support only their
|
||||
reviewed ECMAScript/standalone-PCRE2 paths. Other selections are disabled
|
||||
rather than routed through another profile. Results never claim generic
|
||||
twelve-way equivalence.
|
||||
|
||||
Reference in New Issue
Block a user