Module regex/index
Regular expression engine with an NFA-based virtual machine.
The public surface of the whole package is the four names this module
exports: Regex, RegexMatch, RegexMatchIter and RegexError. The sibling modules
(parser, node, compiler, vm, flags, unicode) are internals —
they export only what their siblings consume, and nothing in them is
covered by the stability promise.
Example
{ Regex } :: import("std/regex");
re := Regex.new_with_flags(`(\w+)@(\w+)`, `i`).unwrap();
match(
re.find(`mail Ada@Example`),
.Some(m) => println(m.group(usize(1)).unwrap()),
.None => println(`no match`)
);
Stability
unstable. The Rust-shaped names landed only in v0.2.28 (#517 — test →
is_match, exec → find, match_all → find_all, and the flag string
split out into new_with_flags), and three shapes are still wrong rather
than merely young:
splitinterleaves capture groups into its result and emits the literal string"undefined"for a group that did not participate — JavaScript's shape, described at the method and filed asissues/stddoc-str-regex-split-emits-the-literal-string-undefined.md.- The
ganduflags are accepted and ignored (issues/stddoc-str-regex-g-and-u-flags-are-silently-ignored.md), sonew_with_flags(p, "g")reads as if it changedreplaceand does not. ifolds ASCII only, so anipattern does not matchÉwithé.
Each fix changes behaviour, so none of them is additive, and the module
cannot freeze before they are decided. What IS settled: Regex /
RegexMatch / RegexMatchIter / RegexError as the whole public surface,
byte offsets everywhere, Result rather than exceptions from new, no
separate captures (a RegexMatch always carries its groups), and the
Pattern impl that lets a compiled regex be passed to any String search
method.
Types
Compiled regular expression backed by an NFA program.
Fields
| Name | Type | Description |
|---|---|---|
_program | NfaProgram | |
_flags | RegexFlags | |
_pattern | String | |
_n_groups | usize | |
_group_names | ArrayList(GroupNameEntry) |
Trait Implementations
impl(Regex, ...)
new_with_flags : (Regex) fn(pattern : String, flags_str : String) -> Result(Regex, RegexError)Compile pattern with the JavaScript-style flag string flags_str
(any of g, i, m, s, u, y; an empty string for none). Reach
for new(pattern) when there are no flags — which is most of the time.
Returns .Err(RegexError) for every malformed pattern or flag string —
the variants are matchable, so a caller can report the exact fault and
the byte offset it was found at.
Capture groups are not capped: the VM allocates 2 * (n_groups + 1)
capture slots per NFA thread, bounded only by memory. Only the
syntax is limited — \1–\9 backreferences and $1–$9
replacement references are single-digit, so groups past 9 are reachable
by name ((?<x>…) / \k<x> / ${x}) or by RegexMatch.group(i).
Parameters
| Name | Type | Notes |
|---|---|---|
pattern | String | |
flags_str | String |
Returns: Result(Regex, RegexError)
source : (Regex) fn(self : Regex) -> Stringnew : (Regex) fn(pattern : String) -> Result(Regex, RegexError)Compile pattern with no flags — Rust's Regex::new, and the
constructor to reach for. new_with_flags is the two-argument form.
This name used to take the flag string as a second parameter, so every
flagless call had to spell Regex.new(p, "") and a sibling compile(p)
existed to avoid it. One name per shape, with the common shape getting
the short name, removes both.
Parameters
| Name | Type | Notes |
|---|---|---|
pattern | String |
Returns: Result(Regex, RegexError)
escape : (Regex) fn(s : String) -> StringQuote s so every character the pattern grammar treats specially
(\ ^ $ . | ? * + ( ) [ ] { }) matches literally: each is preceded by
a backslash. Bytes that are already ordinary (alphanumerics, spaces,
other punctuation) and non-ASCII UTF-8 sequences pass through
untouched, so Regex.new(Regex.escape(s)).unwrap().is_match(s) and
round-tripping a user string through a larger pattern are both safe.
Parameters
| Name | Type | Notes |
|---|---|---|
s | String |
Returns: String
_extract_substring : (Regex) fn(self : Regex, bytes : ArrayList(u8), start : usize, end_pos : usize) -> Stringimpl(Regex, ...)
_build_match : (Regex) fn(self : Regex, slots : ArrayList(usize), input : String) -> RegexMatchimpl(Regex, ...)
_find_from : (Regex) fn(self : Regex, input : String, from_byte : usize) -> Option(RegexMatch)The scan behind exec, generalized to a nonzero start offset — what the
Pattern impl needs for index_in(haystack, from). Sticky: one
anchored attempt at from_byte. Otherwise every rune boundary from
from_byte on, with the same literal-prefix jump exec uses.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String | |
from_byte | usize |
Returns: Option(RegexMatch)
find : (Regex) fn(self : Regex, input : String) -> Option(RegexMatch)The first match in input, or .None — Rust's Regex::find.
Rust splits this into find (the span only) and captures (the span
plus its groups) because the first is cheaper. Yo's RegexMatch always
carries its groups — group(i), name(n) — so there is nothing for a
second method to add, and the two collapse into this one.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String |
Returns: Option(RegexMatch)
find_all : (Regex) fn(self : Regex, input : String) -> ArrayList(RegexMatch)Every non-overlapping match, collected — Rust's find_iter().collect().
find_iter is the lazy form and is what a for loop should use.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String |
Returns: ArrayList(RegexMatch)
impl(Regex, ...)
find_iter : (Regex) fn(self : Regex, input : String) -> RegexMatchIterLazy variant of find_all: returns a RegexMatchIter (an
Iterator) yielding the same non-overlapping matches one at a time.
Works with for m in re.find_iter(s) and with manual next() loops;
see the type's doc for the advance rules.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String |
Returns: RegexMatchIter
impl(Regex, ...)
is_match : (Regex) fn(self : Regex, input : String) -> boolTrue when input contains a match — Rust's Regex::is_match.
There is no search() -> Option(usize) companion any more: it returned
the first match's byte offset, which is find(input)'s
RegexMatch.index(), so it was a strictly-less-informative duplicate
carrying a JavaScript name.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String |
Returns: bool
impl(Regex, ...)
_apply_replacement : (Regex) fn(self : Regex, replacement : String, m : RegexMatch) -> Stringimpl(Regex, ...)
replace : (Regex) fn(self : Regex, input : String, replacement : String) -> Stringinput with the FIRST match replaced — Rust's Regex::replace.
FIRST, not all. This is deliberate and it is the one asymmetry in the
whole replace family: String.replace(re, rep) — the same regex reached
through the Pattern trait — replaces EVERY match (D10), because that is
what str::replace means, while Regex::replace / Regex::replace_all
is the split Rust's regex crate draws. So
re.replace(`aaa`, `X`) // "Xaa" — this method
`aaa`.replace(re, `X`) // "XXX" — String.replace, D10
re.replace_all(`aaa`, `X`) // "XXX" — say it explicitly
Returns input unchanged when nothing matches. replacement is
interpreted: $& is the whole match, $1–$9 are groups, ${name} is
a named group, $` and $' are the text before and after the match,
and $$ is a literal $. Use replace_with when the replacement has to
be computed, or when the text must be inserted verbatim.
The g flag does NOT change this — the engine ignores g entirely; the
method name is the only thing that decides one-or-all.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String | |
replacement | String |
Returns: String
replace_all : (Regex) fn(self : Regex, input : String, replacement : String) -> Stringinput with EVERY non-overlapping match replaced — Rust's
Regex::replace_all, and the method to reach for when "replace" means
all of them (replace here does the first only).
Matches come from find_all, so they are the same non-overlapping,
left-to-right set, and a zero-width-matching pattern advances the way
find_all advances rather than looping. replacement gets the same $
interpretation as replace. Returns input unchanged when nothing
matches.
Builds the whole result in one pass over input, so it is O(input +
output) rather than one string allocation per match.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String | |
replacement | String |
Returns: String
replace_with : (Regex) fn(self : Regex, input : String, f : Impl : (Fn(RegexMatch) -> String)) -> Stringreplace with the replacement COMPUTED per match: f receives the
RegexMatch (so group(i)/named_group(...) are available) and
returns the text to splice in. The callback IS the interpretation
layer — its output is inserted verbatim, with no $1 reference
processing.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String | |
f | Impl : (Fn(RegexMatch) -> String) |
Returns: String
replace_all_with : (Regex) fn(self : Regex, input : String, f : Impl : (Fn(RegexMatch) -> String)) -> Stringreplace_all with the replacement computed per match by f — same
non-overlapping-match walk as replace_all, same verbatim insertion
rule as replace_with.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String | |
f | Impl : (Fn(RegexMatch) -> String) |
Returns: String
split : (Regex) fn(self : Regex, input : String) -> ArrayList(String)input cut at every non-overlapping match, JavaScript-style — and
JavaScript-style is a real divergence from Rust worth reading twice.
Two things follow String.prototype.split(regexp) rather than Rust's
Regex::split:
- Capture groups are INTERLEAVED into the result. After each piece,
the text of every group the pattern declared is pushed too, so
Regex.new("(-)").unwrap().split("a-b-c")is["a", "-", "b", "-", "c"], not["a", "b", "c"]. A pattern with no groups behaves as you would expect. - A group that did not participate contributes the literal string
"undefined", JavaScript'sundefinedrendered as text. SoRegex.new(",(x)?").unwrap().split("a,b")is["a", "undefined", "b"]. That is a magic string in a typed API and it is filed asissues/stddoc-str-regex-split-emits-the-literal-string-undefined.md; anArrayList(Option(String))or simply omitting non-participating groups would both be better, and both are breaking.
A pattern that never matches yields [input] — one piece, never an empty
list. This is also the body behind String.split(re), so the Pattern
dispatch inherits both behaviours.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
input | String |
impl(Regex, Pattern(...))
is_prefix_of : (Regex) fn(self : Regex, haystack : String, position : usize) -> boolis_suffix_of : (Regex) fn(self : Regex, haystack : String, end_position : usize) -> boolindex_in : (Regex) fn(self : Regex, haystack : String, from_index : usize) -> Option(usize)is_contained_in : (Regex) fn(self : Regex, haystack : String, from_index : usize) -> boollast_index_in : (Regex) fn(self : Regex, haystack : String, from_index : usize) -> Option(usize)length_in : (Regex) fn(self : Regex, haystack : String, at : usize) -> usizeNumber of BYTES the match STARTING EXACTLY at byte offset at occupies
— 0 when no match starts there. replace, replace_all, split_once
and strip_prefix cut the haystack by it; a zero-width pattern (empty
string, empty-matching regex) legitimately answers 0.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
haystack | String | |
at | usize |
Returns: usize
split_of : (Regex) fn(self : Regex, haystack : String) -> ArrayList(String)Every piece of haystack between occurrences of this pattern, in order.
The only Pattern method with no offset argument — it always covers the
whole haystack — and the only one an implementation may give a shape of
its own: String / str treat an EMPTY pattern as "split into runes"
(see String.split), which no offset-based method can express.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Regex | |
haystack | String |
A single regex match result.
Fields
| Name | Type | Description |
|---|---|---|
_value | String | |
_index | usize | |
_end | usize | |
_input | String | |
_groups | ArrayList(Option(String)) | |
_group_spans | ArrayList(Option(Range(usize))) | |
_group_names | ArrayList(GroupNameEntry) |
Methods
new : (RegexMatch) fn(value : String, index : usize, end : usize, input : String, groups : ArrayList(Option(String)), group_spans : ArrayList(Option(Range(usize))), group_names : ArrayList(GroupNameEntry)) -> RegexMatchCompile pattern with no flags — Rust's Regex::new, and the
constructor to reach for. new_with_flags is the two-argument form.
This name used to take the flag string as a second parameter, so every
flagless call had to spell Regex.new(p, "") and a sibling compile(p)
existed to avoid it. One name per shape, with the common shape getting
the short name, removes both.
Parameters
| Name | Type | Notes |
|---|---|---|
value | String | |
index | usize | |
end | usize | |
input | String | |
groups | ArrayList(Option(String)) | |
group_spans | ArrayList(Option(Range(usize))) | |
group_names | ArrayList(GroupNameEntry) |
Returns: RegexMatch
value : (RegexMatch) fn(self : RegexMatch) -> StringThe matched text itself — the same bytes as
input().substring(index(), end()), captured at match time.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch |
Returns: String
index : (RegexMatch) fn(self : RegexMatch) -> usizeStart position of the match as a byte offset into the input.
Basis change (D4, 2026-08-26): this used to be a character
(rune) index; it is now a byte index, matching String's
byte-indexed API. The offset is always on a UTF-8 character
boundary (a valid pattern cannot match at a continuation byte), so
it can be fed directly to String.substring / index_of on the
input. Use input().substring(usize(0), m.index()).chars().count() if
a rune count is really needed.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch |
Returns: usize
end : (RegexMatch) fn(self : RegexMatch) -> usizeEnd position of the match as a byte offset into the input
(exclusive — the offset of the first byte AFTER the match). Always
on a UTF-8 character boundary, for the same reason as index().
span() is index() .. end().
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch |
Returns: usize
span : (RegexMatch) fn(self : RegexMatch) -> Range(usize)The whole match as a byte range index() .. end() into the input.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch |
Returns: Range(usize)
input : (RegexMatch) fn(self : RegexMatch) -> StringThe whole string the match was found in, not just the matched part. The
match holds a reference to it, so the offsets index() / end() /
span() / group_span() stay meaningful for as long as the match does.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch |
Returns: String
group : (RegexMatch) fn(self : RegexMatch, idx : usize) -> Option(String)The text of capture group idx, 1-based, with 0 meaning the whole
match — the same numbering $1 and \1 use in patterns.
.None means EITHER that the group did not participate in this match (an
unmatched (x)?, or an alternative that was not taken) OR that idx is
past group_count(). The two are not distinguishable here; compare idx
against group_count() first if that matters.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch | |
idx | usize |
group_span : (RegexMatch) fn(self : RegexMatch, idx : usize) -> Option(Range(usize))Capture group's byte range into the input (1-based, mirroring
group(); group 0 is the full match's span()), or .None when
the group did not participate in the match or the index is out of
range. A participating group's range satisfies
input().substring(r.start, r.end) == group(idx).unwrap().
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch | |
idx | usize |
named_group : (RegexMatch) fn(self : RegexMatch, name : String) -> Option(String)The text of the group declared as (?<name>...), or .None when no
group has that name OR the named group did not participate — the same
conflation as group.
O(number of named groups): the name table is scanned linearly on every call, so a loop over many names over a long input is quadratic. Names are compared for exact equality, case-sensitively.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch | |
name | String |
group_count : (RegexMatch) fn(self : RegexMatch) -> usizeHow many capture groups the PATTERN declared, not counting group 0 and
not counting how many actually participated. So a non-participating group
is still counted, and group(i) is a legal call for every
1 <= i <= group_count().
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatch |
Returns: usize
Lazy iterator over a regex's non-overlapping matches — what
Regex.find_iter returns. Yields exactly what find_all collects,
one match at a time: next() runs the VM from the end of the previous
match (an empty match advances one UTF-8 character, mirroring
find_all's infinite-loop guard), so a large input can be scanned
without materializing every match. Single-pass: once next() returns
.None the iterator is exhausted (it does not rewind).
Fields
| Name | Type | Description |
|---|---|---|
_regex | Regex | |
_vm | NfaVm | |
_input | String | |
_byte_pos | usize | |
_has_prefix | bool |
Trait Implementations
impl(generic(I : Type), where(I <: Iterator), I : (Iterator))
impl(generic(I : Type), where(I <: Iterator), I : (Iterator))
map : fn(generic(A, B, F) self : I : (Iterator), f : F : (Fn(A) -> B)) -> IterMap(I : (Iterator), B, F : (Fn(A) -> B))filter : fn(generic(A, F) self : I : (Iterator), f : F : (Fn(A) -> bool)) -> IterFilter(I : (Iterator), F : (Fn(A) -> bool))Parameters
| Name | Type | Notes |
|---|---|---|
self | I : (Iterator) | |
f | F : (Fn(A) -> bool) |
Returns: IterFilter(I : (Iterator), F : (Fn(A) -> bool))
take : fn(generic(A) self : I : (Iterator), n : usize) -> IterTake(I : (Iterator))skip : fn(generic(A) self : I : (Iterator), n : usize) -> IterSkip(I : (Iterator))enumerate : fn(generic(A) self : I : (Iterator)) -> IterEnumerate(I : (Iterator))zip : fn(generic(A, J, B) self : I : (Iterator), other : J : (Iterator)) -> IterZip(I : (Iterator), J : (Iterator))fold : fn(generic(A, Acc, F) self : I : (Iterator), init : Acc, f : F : (Fn(Acc, A) -> Acc)) -> Accfor_each : fn(generic(A, F) self : I : (Iterator), f : F : (Fn(A) -> unit)) -> unitcount : fn(generic(A) self : I : (Iterator)) -> usizeany : fn(generic(A, F) self : I : (Iterator), pred : F : (Fn(A) -> bool)) -> boolall : fn(generic(A, F) self : I : (Iterator), pred : F : (Fn(A) -> bool)) -> boolfind : fn(generic(A, F) self : I : (Iterator), pred : F : (Fn(A) -> bool)) -> Option(A)The first match in input, or .None — Rust's Regex::find.
Rust splits this into find (the span only) and captures (the span
plus its groups) because the first is cheaper. Yo's RegexMatch always
carries its groups — group(i), name(n) — so there is nothing for a
second method to add, and the two collapse into this one.
Parameters
| Name | Type | Notes |
|---|---|---|
self | I : (Iterator) | |
pred | F : (Fn(A) -> bool) |
Returns: Option(A)
position : fn(generic(A, F) self : I : (Iterator), pred : F : (Fn(A) -> bool)) -> Option(usize)last : fn(generic(A) self : I : (Iterator)) -> Option(A)nth : fn(generic(A) self : I : (Iterator), n : usize) -> Option(A)sum : fn(generic(A) self : I : (Iterator)) -> A : ((Output : Type, + : fn(lhs : Self, rhs : A) -> Output) + Default)min : fn(generic(A) self : I : (Iterator)) -> Option(A : ((< : fn(lhs : Self : ((== : fn(lhs : Self, rhs : A) -> bool, != : fn(lhs : Self, rhs : A) -> bool)), rhs : A) -> bool, <= : fn(lhs : Self, rhs : A) -> bool, > : fn(lhs : Self, rhs : A) -> bool, >= : fn(lhs : Self, rhs : A) -> bool, cmp : fn(lhs : Self, rhs : A) -> Ordering)))Parameters
| Name | Type | Notes |
|---|---|---|
self | I : (Iterator) |
Returns: Option(A : ((< : fn(lhs : Self : ((== : fn(lhs : Self, rhs : A) -> bool, != : fn(lhs : Self, rhs : A) -> bool)), rhs : A) -> bool, <= : fn(lhs : Self, rhs : A) -> bool, > : fn(lhs : Self, rhs : A) -> bool, >= : fn(lhs : Self, rhs : A) -> bool, cmp : fn(lhs : Self, rhs : A) -> Ordering)))
max : fn(generic(A) self : I : (Iterator)) -> Option(A : ((< : fn(lhs : Self : ((== : fn(lhs : Self, rhs : A) -> bool, != : fn(lhs : Self, rhs : A) -> bool)), rhs : A) -> bool, <= : fn(lhs : Self, rhs : A) -> bool, > : fn(lhs : Self, rhs : A) -> bool, >= : fn(lhs : Self, rhs : A) -> bool, cmp : fn(lhs : Self, rhs : A) -> Ordering)))Parameters
| Name | Type | Notes |
|---|---|---|
self | I : (Iterator) |
Returns: Option(A : ((< : fn(lhs : Self : ((== : fn(lhs : Self, rhs : A) -> bool, != : fn(lhs : Self, rhs : A) -> bool)), rhs : A) -> bool, <= : fn(lhs : Self, rhs : A) -> bool, > : fn(lhs : Self, rhs : A) -> bool, >= : fn(lhs : Self, rhs : A) -> bool, cmp : fn(lhs : Self, rhs : A) -> Ordering)))
chain : fn(generic(A, J) self : I : (Iterator), other : J : (Iterator)) -> IterChain(I : (Iterator), J : (Iterator))take_while : fn(generic(A, F) self : I : (Iterator), f : F : (Fn(A) -> bool)) -> IterTakeWhile(I : (Iterator), F : (Fn(A) -> bool))Parameters
| Name | Type | Notes |
|---|---|---|
self | I : (Iterator) | |
f | F : (Fn(A) -> bool) |
Returns: IterTakeWhile(I : (Iterator), F : (Fn(A) -> bool))
skip_while : fn(generic(A, F) self : I : (Iterator), f : F : (Fn(A) -> bool)) -> IterSkipWhile(I : (Iterator), F : (Fn(A) -> bool))Parameters
| Name | Type | Notes |
|---|---|---|
self | I : (Iterator) | |
f | F : (Fn(A) -> bool) |
Returns: IterSkipWhile(I : (Iterator), F : (Fn(A) -> bool))
filter_map : fn(generic(A, B, F) self : I : (Iterator), f : F : (Fn(A) -> Option(B))) -> IterFilterMap(I : (Iterator), B, F : (Fn(A) -> Option(B)))Parameters
| Name | Type | Notes |
|---|---|---|
self | I : (Iterator) | |
f | F : (Fn(A) -> Option(B)) |
Returns: IterFilterMap(I : (Iterator), B, F : (Fn(A) -> Option(B)))
peekable : fn(generic(A) self : I : (Iterator)) -> IterPeekable(I : (Iterator), A)collect : fn(self : I : (Iterator), C : Type) -> C : (FromIterator)impl(RegexMatchIter, Iterator(...))
Item : RegexMatchnext : (RegexMatchIter) fn(self : RegexMatchIter) -> Option(RegexMatch)Advance the iterator and return the next value, or None when exhausted.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexMatchIter |
Returns: Option(RegexMatch)
Everything Regex.new can reject, split by what the user has to fix.
Variants
| Variant | Fields | Description |
|---|---|---|
UnexpectedEnd | pos: usize | The pattern ended where an expression was expected, e.g. |
TrailingBackslash | pos: usize | The pattern ends with a |
UnterminatedCharClass | pos: usize | A |
UnterminatedGroup | pos: usize | A |
UnmatchedCloseParen | pos: usize | A |
InvalidQuantifier | pos: usize | A |
QuantifierOutOfOrder | min: usize, max: usize, pos: usize | A |
InvalidBackreference | group: usize, pos: usize |
|
InvalidNamedBackreference | pos: usize |
|
UnknownGroupName | name: String, pos: usize |
|
InvalidUnicodeProperty | pos: usize |
|
UnknownUnicodeProperty | name: String, pos: usize |
|
InvalidFlag | flag: u8 | A flag character outside |
DuplicateFlag | flag: u8 | The same flag character given more than once. |
Trait Implementations
impl(generic(T : Type), where(T <: ToString), T : (ToString))
impl(generic(T : Type), where(T <: ToString), T : (ToString), Format)
format : fn(self : Self, spec : str) -> StringRender self under spec. An unrecognised spec degrades to the plain
to_string() rendering rather than failing.
Parameters
| Name | Type | Notes |
|---|---|---|
self | Self | |
spec | str |
Returns: String
Methods
to_string : (RegexError) fn(self : RegexError) -> Stringsource : (RegexError) fn(self : RegexError) -> Option(dyn( + ToString))The pattern text this Regex was compiled from, exactly as given —
Rust's Regex::as_str. Useful in error messages and logs; it is the
SOURCE, not a canonical form, so it round-trips through Regex.new but
says nothing about the compiled program.
Parameters
| Name | Type | Notes |
|---|---|---|
self | RegexError |