Minimal regex engine for fastC — Thompson NFA, no backreferences.
Part of the fastc-core launch set. The implementation ships
alongside the fastC v1.0 compiler — every fastC v1.0 program
already gets use regex::* for free. This repository is the
public home for the module's API and will become installable via
fastc add github.com/Skelf-Research/fastc-core-regex once stage
1.7's vendor-consumption flow completes the loop.
use regex::Regex; // opaque compiled pattern
use regex::Match; // struct Match { start: usize, end: usize }
use regex::RegexError; // compile-time syntax error
use regex::compile; // (pattern: Str) -> res(Regex, RegexError)
use regex::match_one; // (re: ref(Regex), text: Str) -> opt(Match)
use regex::match_all; // (re: ref(Regex), text: Str) -> Vec[Match]
use regex::replace; // (re: ref(Regex), text: Str, replacement: Str) -> Str
use regex::release; // (re: Regex) -> void
match_one returns the leftmost match or None. match_all
returns every non-overlapping match left-to-right. replace
substitutes every match with the replacement string.
release is explicit cleanup. A Drop impl lands in a later
v1.x slice once the language-level destructor story settles —
the surface above is the v1.0 floor.
| Construct | Meaning |
|---|---|
a, b, ... |
Literal characters |
. |
Any character except newline |
[a-z] |
Character class |
[^a-z] |
Negated character class |
^ |
Start anchor |
$ |
End anchor |
* |
Zero or more (greedy) |
+ |
One or more (greedy) |
? |
Zero or one (greedy) |
{n,m} |
Bounded repetition |
(...) |
Grouping |
| |
Alternation |
Anything outside this table is a syntax error from compile.
use regex::compile;
use regex::match_one;
use regex::match_all;
use regex::release;
use io::println;
use io::print_int;
use io::put_char;
fn main() -> i32 {
let re: Regex = compile(cstr("[a-z]+"))?;
let text: Str = cstr("the quick brown fox");
// Leftmost match.
let first: opt(Match) = match_one(ref(re), text);
if (is_some(first)) {
println(cstr("found a word"));
}
// Count every non-overlapping match.
let hits: Vec[Match] = match_all(ref(re), text);
print_int(len(hits));
put_char(10);
release(re);
return 0;
}
None required. regex is a pure data transform — it reads the
pattern and the input, allocates internal state for the NFA, and
returns matches. No syscalls, no ambient I/O, no Cap* token.
Thompson NFA matching is O(n * m) in the length of the input and
the size of the compiled pattern — linear in the input, with no
catastrophic backtracking. Backreferences (\1, \2, ...) blow
this guarantee up: matching with backrefs is NP-hard in the
general case and exponential in practice for adversarial inputs,
which is the same class of bug behind the well-known ReDoS
incidents in production regex libraries.
fastc-core-regex picks the linear-time floor and holds it. Code that genuinely needs backreferences — usually one-off scraping or migration scripts — can call PCRE through FFI and pay the performance variance explicitly.
v0.1.0 — preview. API is final; the package becomes a true
installable via fastc add once the consumption flow ships.
Until then, the same API is available in every fastC v1.0
program via the built-in prelude.
MIT