Pattern matching
Regex at full PCRE2 power is the entry point; six pattern languages carry it to lists, numbers, time, tables, matrices and graphs. The lanes rate the text engine.
4 Strong · 5 Solid · 3 Partial · 0 Emerging
Measured against: PCRE2 · RE2 · Oniguruma · Folders: base/regex(opens in a new tab) · For programmers: this area's reference

Rethought from first principles
What Softanza kept from what works, and what it rethought, as the library wrote it down in its design documents and narrations.
The Softanza wayPattern matching is one way of thinking for every kind of data. The regex is its entry point; Softanza carries the same idea to lists, numbers, time, tables, matrices and graphs, and lets you build a pattern in words or call it by its name.
Kept from the best practice
- PCRE2 runs every match: proven, Unicode-aware, and written in the regex syntax programmers already know, with Unicode mode always switched on. source(opens in a new tab)
- Simple matches are not reinvented: a classic pattern string, named groups and captures work as written; Softanza only adds clearer names around them. source(opens in a new tab)
Rethought
- Listex, Matrex, Tablex and Graphex apply one pattern grammar to lists, matrices, tables and graphs, replacing the verbose conditional code structured data usually needs. source(opens in a new tab)
- Numbrex and Timex describe a number's properties (prime, perfect, palindrome) or a timeline's events and durations, so you state what you mean, not how to test it. source(opens in a new tab)
- stzRegexMaker builds a pattern from readable steps, with conditional (wrxm) and look-around (arxm) makers, because cryptic notation is error-prone and documents nothing. source(opens in a new tab)
- Ready-made patterns are called by name — pat(:email), pat(:IPv6) — and can explain themselves with Explain(), because a raw pattern carries no sign of its intent. source(opens in a new tab)
- Four scope verbs — Match, MatchLine, MatchWord, MatchSegment — replace the dotall, multiline and word-boundary flags, because a flag set elsewhere hides what the pattern means. source(opens in a new tab)
- Match() asks whether the whole text fits the pattern; MatchFirst() asks whether it occurs anywhere — two different questions get two different verbs. source(opens in a new tab)
Under the hood it is PCRE2 10.47, statically linked, Unicode always on, with an unusually rich Haro layer (100+ methods, four fluent builder classes, a reactive match-to-code engine). On features it is at PCRE2 parity, with lookaround, backreferences, recursion and conditionals that RE2 and Rust refuse. Where it trails the modern engines is the safety-and-throughput story: no JIT, no linear-time matcher, and the ReDoS knob is not reachable from Haro, although the code for both is already compiled into the binary.
What a crafter does with it, and what stands out
- Feature-complete PCRE2: lookaround, backrefs, recursion, conditionals that RE2 and Rust deliberately refuse
- The clearest match-semantics API in its class: Match() anchors, MatchFirst() searches, partial as-you-type
- Four fluent builder classes with no native peer
- A reactive RegexUter match-to-code engine
What is owed
- Wire the linear-time DFA matcher (pcre2_dfa_match is already in the binary)
- Surface the ReDoS limits on the Haro stzRegex class
- Named-group substitution ${name} in replace
- Fix the broken Explain fallback (missing stzRegexAnalyzer) and the builder stubs
The Softanza way, run
What Softanza does differently in this area, shown by code taken from its narrations and guards, and run for this page.
A list is matched by its shape, the way a regex matches text: a number then a string, one to three numbers then a string, anything but a number.
# a number, then a string
? Lx("[@N, @S]").Match([42, "hello"])
# one to three numbers, then a string
? Lx("[@N1-3, @S]").Match([1, 2, "end"])
# anything but a number
? Lx("[@!N]").Match(["string"])
? Lx("[@!N]").Match([42])1 1 1 0
run on 2026-10-15 13:37 inside the library at commit 4a184e6f0; taken from base/doc/narrations/stzlistex-pattern-matching-for-lists.md(opens in a new tab)
A ready-made pattern is called by name, matched against a whole value, and explains itself in plain words.
rx(pat(:xlsConditionalExpression)) {
? Match("B2<>C3")
? Pattern() + NL
? Explain() + NL
}1 ^.*(?:=|<|>|<>).*$ Matches an Excel conditional expression
run on 2026-10-15 13:37 inside the library at commit 4a184e6f0; taken from base/test/regexmaker/02_match.ring(opens in a new tab)
A conditional pattern is declared like an if/else, international or local phone format, and the maker writes the regex.
wrxm() {
IfStartsWith("+")
ThenMatch("\+1\d{10}") # International format
ElseMatch("\d{10}") # Local format
? Pattern()
}(?(?=^\+)\+1\d{10}|\d{10})run on 2026-10-15 13:37 inside the library at commit 4a184e6f0; taken from base/test/regexmaker/34_validate_phone_numbers.ring(opens in a new tab)
A number is matched by what it is: 17 fits the pattern for primes, 18 does not.
Nx = new stzNumbrex("{@Property(Prime)}")
? Nx.Match(17)
? Nx.Match(18)1 0
run on 2026-10-15 13:37 inside the library at commit 4a184e6f0; taken from base/test/numbrex/02_basic_property_matching.ring(opens in a new tab)
The articles of this area (10)
- Mastering Regular Expressions with Softanza: A Modern Approach to Pattern Matching 2025
- Simplifying Regular Expressions with the Enhanced stzRegexData Library 2025
- The Softanza RegexMaker: Making Regex Human-Friendly 2025
- Softanza Regexuter: Regex as Computational Reactive Medium 2025
- Softanza Listex: Bringing Pattern Matching to Lists 2025
- stzNumbrex: A Pattern Language for Numbers 2025
- stzTimex: A Pattern Language for Time in Softanza 2025
- stzNumbrex: A Pattern Language for Numbers in Softanza 2025
- stzMatrex: Declarative Pattern Matching for Matrices in Softanza 2025
- stzTablex: Declarative Pattern Matching for Tables in Softanza 2025
The lanes, one by one
Lanes and their notes are quoted as they were read at the source, on Read from the source on 2026-09-16.

