moonregex

    Regular expressions for MoonBit.

    regex
    re
    ecma262
    unicode
    moonbit
    Download zip
    Version
    0.1.1
    License
    Apache-2.0
    Last updated
    2 hours ago
    Downloads
    30

    #moonregex

    Regular expressions for MoonBit — Python's re interface, the regex superset behind it, and the ECMA-262 grammar that JSON Schema and OpenAPI mean.

    The showcase runs this library in the browser: src/examples/browser compiles to docs/assets/moonregex_web.js with python scripts/build_web.py, and the page feeds your pattern, flags and text through it. Nothing there is re-implemented in JavaScript.

    let year = @moonregex.search("\\d{4}", "copyright 2026").unwrap()
    year.content() // "2026"
    year.start() // 10
    @moonregex.sub("\\s+", " ", "a b c") // "a b c"

    A pattern is read by one of three grammars, lowered into a single syntax tree, and run by one engine, so the same pattern behaves the same way on every backend.

    Python (the default)re as Python 3.15 documents it, plus everything the regex package adds
    Ecma262ECMA-262 §22.2, the grammar JSON Schema and OpenAPI patterns are written in
    Lexmatchthe grammar the core library's @string.Regex and the lexer speak

    #Install

    moon add moonbitstack/moonregex

    #The names it uses

    The module functions are the re ones, with three renames — one concept, one name, and the name says where the match has to fall:

    Pythonmoonregexwhere the match must be
    re.searchsearchanywhere, leftmost first
    re.matchprefixat the position the scan starts
    re.fullmatchfullthe whole region
    re.sub with a functionsub_with—
    re.subn with a functionsubn_with—

    match is not used because in most languages it means what Python calls search, and Python itself has soft-deprecated it in favour of prefixmatch. Reading an ECMA-262 pattern next to a Python one, a name that means two things is worse than a name nobody has seen before. Pattern::search, Pattern::prefix and Pattern::full are the same three.

    let p = @moonregex.compile("[a-z]+")
    p.search(" hello ") // Some(_) — at 2
    p.prefix(" hello ") // None — the scan starts at 0
    p.full("hello") // Some(_)

    #The interface

    Module functions compile on every call. compile once, then use the Pattern methods, when a pattern is used more than once.

    FunctionReturns
    compile(pattern, flags~, dialect~, lists?, partial~)Pattern
    search / prefix / fullMatch?
    findallArray[String?]
    finditerArray[Match]
    splitArray[String?]
    sub / subn / subf / subfnString or (String, Int)
    sub_with / subn_withString or (String, Int)
    escape(string, dialect~, special_only~, literal_spaces~)String

    Pattern answers pattern, flags, dialect, groups, groupindex, named_lists, partial, dump, and the same matching methods without the compile options. Match answers group, groups, groupdict, start, end, span, captures, starts, ends, spans, capturesdict, allcaptures, allspans, expand, expandf, pos, endpos, lastindex, lastgroup, re, string, content, before, after, fuzzy_counts, fuzzy_changes, marks and partial.

    A group is addressed by number or by name — trait GroupKey is implemented by Int and by String, so m.group(1) and m.group("year") both work.

    #Groups, and the one place a list cannot answer

    findall collects the whole match when the pattern has no groups, the single group when it has one — and refuses when it has two or more, because Python answers a tuple there and a statically typed list cannot. Pass group to say which one, or walk finditer for matches that carry them all.

    @moonregex.findall("(\\w+)=(\\d+)", "a=1") // raises Ambiguous
    @moonregex.findall("(\\w+)=(\\d+)", "a=1", group=Num(n=1)) // ["a"]

    #Flags

    Flags is a record, not a bitmask: Flags::new(ignorecase=true) sets one switch and leaves the rest, and @moonregex.flags is all of them off.

    ignorecase, multiline, dotall, verbose, ascii, unicode, unicode_sets, fullcase, bestmatch, enhancematch, posix, reverse, word, and version (V0 / V1).

    The common ones also have their inline spelling — (?i), (?m), (?s), (?x), (?a) and the scoped (?i:…) — which needs no flag argument at all.

    #Escape

    escape follows the grammar it is told to follow, because the three do not agree on what is special:

    Dialectescape("a.b")rule
    Pythona\.bre.escape: the characters that can mean something take a backslash
    Ecma262\x61\.bRegExp.escape: punctuation is spelled in hex, and a leading alphanumeric too
    Lexmatcha\.bthe @string.Regex metacharacters, with \u{…} for the invisible ones

    #The three grammars

    // Python: named group, `\A`, backreference — the default.
    @moonregex.findall("(?P<w>\\w+)\\s+\\1", "go go no")

    // ECMA-262: what a JSON Schema `pattern` means.
    @moonregex.compile("^[a-z]+$", dialect=@moonregex.ecma262)

    // lexmatch: a pattern already written for the core library.
    @moonregex.compile("[[:digit:]]+", dialect=@moonregex.lexmatch_dialect)

    Choose by where the pattern comes from. A pattern a person wrote for text processing is Python; a pattern from a schema, a form, or a JavaScript codebase is Ecma262; a pattern from a MoonBit lexer is Lexmatch.

    The dialects differ where the standards differ: \A and \Z exist only in Python, $ sits before a trailing newline only in Python, \w is ASCII in ECMA-262, and [[:alpha:]] is a class escape only in the superset. Each of those is settled while reading the pattern, not while matching it.

    #Standing next to the core engine

    The core library ships a regular-expression engine of its own, reached through @string.Regex and the lexmatch grammar. This library uses it where it can and runs the rest itself.

    • A pattern that says nothing the core engine cannot say lowers onto it. Pattern::lower answers the @string.Regex for it, or None. Backreferences, lookaround, conditionals, recursion, atomic groups, fuzzy matching, \X, Unicode word boundaries and Python's $ answer None — those run here.
    • The combinators are the same five, with the same meaning: Pattern::string, +, |, repeat, capture. A pattern assembled in code and a pattern written as text are the same kind of value.
    • A match carries both views: content, before and after as core spells them, next to group, span and the rest.

    let year = @moonregex.Pattern::string("\\d{4}").capture("year")
    let dash = @moonregex.Pattern::string("-")
    let month = @moonregex.Pattern::string("\\d{2}").capture("month")
    let date = year + dash + month

    let m = date.prefix("2026-10").unwrap()
    m.group("month") // Some("10")

    // `lower` hands the pattern to the core engine when it fits.
    match date.lower() {
    Some(core) => core.execute("2026-10") is Some(_) // true
    None => false
    }

    #Step limits

    A backtracking engine can be talked into taking a very long time. Every call carries a step ceiling — ten million by default, the number PCRE2 uses — and raises Exceeded(limit~, got~) rather than hanging. limit~ raises or lowers it per call.

    #Partial matching

    With partial=true, a pattern that has matched everything it can but could go on matching if the text continued answers a match with Match::partial set — what a streaming parser needs to know that it should wait for more input.

    #What it does not do

    Not implementedWhy
    re.LOCALEMoonBit has no locale; re itself only offers it for bytes and advises against it
    re.DEBUGthe library does not print; Pattern::dump returns the tree as text instead
    re.purgethere is no global pattern cache to clear
    ECMA's g, y, dthey are ways of calling, not properties of a pattern: g is findall/finditer/count=0, y is prefix(pos=), d is what span has always answered
    Match.detach_string, Match.regsstrings are immutable here, and spans covers regs

    #Where it differs from the references

    Everything else follows the reference implementations case by case, checked against generated vectors. These are the places where a decision was taken instead:

    CaseHereThe reference
    matchnot offered; prefix is the same thingre.match, soft-deprecated in 3.15
    Runaway patternsExceeded after ten million stepsno limit
    \N without a nameany character but a newlinere refuses it; regex reads a literal N under V0
    \v, \Vthe vertical tab under V0, the vertical-space class under V1re always means the tab
    \e, \Q…\E, \Kacceptedre refuses them
    (?<name>…)accepted in the Python dialect toore wants (?P<name>…)
    [[:alpha:]]a class escape in every dialectre reads it as a set of characters
    Refusal offsetswhere reading stoppedPython's convention differs per error
    A group repeated over an empty tailkeeps the captures of the empty turn ((a*)* leaves group 1 at the end)ECMA-262 clears them
    Astral charactersoffsets count code pointsECMA-262 counts UTF-16 code units
    Property namesUnicode loose matching in every dialectECMA-262 is case- and space-sensitive
    A name used twiceallowed in the ECMA dialect anywherere refuses it; ECMA-262 only across alternatives
    v-mode nested classes[[a-z]--[aeiou]] is not read as a class expressionECMA-262 reads them

    #Licence

    Apache-2.0. See LICENSE.

    Dialect

    Which grammar a pattern is written in.

    The interface is the same whichever is chosen; the grammar is a parameter because the callers need different ones. JSON Schema's pattern and OpenAPI's pattern are defined as ECMA-262 §22.2 and are unforgiving about it, while everyone else writes Python's.

    Flags

    The flags type, re-exported so a caller needs only this package.

    Refused

    The error the grammar and engine raise when a pattern cannot be read or a group the pattern does not have is asked for.

    Version

    Which regex-module behaviour set a Python pattern is read under.

    V0 is re as everyone writes it; V1 opens the set algebra (--, &&, ~~, nested sets) and the rest of what (?V1) unlocks. Only the Python dialect has versions — ECMA-262 gates the same algebra behind its v flag.

    GroupKey

    pub(open) trait GroupKey {
    fn to_group(Self) -> Group
    }

    What can name a group. Two implementations do the work: a number and a name, so m.group(1) and m.group("year") are the same method.

    The trait is open: a caller with its own key — a slot number in a table of its own, say — implements it and the methods take it without a change here.
    impl GroupKey for Int
    impl GroupKey for String

    Group

    pub(all) enum Group {
    Whole
    Num(n~ : Int)
    Name(n~ : String)
    }

    Which group a value names: Whole for the whole match, Num for a numbered parenthesis, Name for a named one.

    This is the shape the methods work in. Callers do not have to build it — GroupKey is implemented by Int, by String and by this type, so m.group(1), m.group("year") and m.group(Whole) are one call.
    impl GroupKey for Group

    Group::to_group

    #deprecated("`Group::to_group` is deprecated, use `GroupKey::to_group` instead.")
    fn Group::to_group(self : Group) -> Group

    Match

    pub(all) struct Match {
    // private fields
    }

    One match: where it sits in the text, and every group's span.

    A span is a code-point range, so start and end read the way Python's do — characters, not UTF-16 units — and group slices the original text back out by those offsets.

    Match::after

    fn Match::after(self : Match) -> StringView

    The text after the match — core's MatchResult::after.

    Match::before

    fn Match::before(self : Match) -> StringView

    The text before the match — core's MatchResult::before.

    Match::captures

    fn[K : GroupKey] Match::captures(self : Match, group : K) -> Array[(Int, Int)] raise
    Refused

    Every capture of group, as code-point spans; an empty list when the group took no part — Python's Match.captures. Our engine records the last span a group held, so this returns the one span a non-repeated group captured.

    Match::capturesdict

    fn Match::capturesdict(self : Match) -> Map[String, Array[(Int, Int)]]

    Named groups to their captured spans — Python's Match.capturesdict.

    Match::content

    fn Match::content(self : Match) -> StringView

    The matched text — core's MatchResult::content, and Python's group(0).

    Match::end

    fn[K : GroupKey] Match::end(self : Match, group : K) -> Int raise
    Refused

    Code-point offset just past where the whole match ends.

    Match::endpos

    fn Match::endpos(self : Match) -> Int

    The endpos the search was bounded by — Python's Match.endpos.

    Match::expand

    fn Match::expand(self : Match, template : String) -> String raise
    Refused

    Expand the Python replacement language in template against this match — Python's Match.expand.

    Match::fuzzy_changes

    fn Match::fuzzy_changes(self : Match) -> (Array[(Int, Int)], Array[(Int, Int)], Array[(Int, Int)])

    The individual edits of a fuzzy match, as (substitutions, insertions,deletions) each a list of (string_offset, pattern_offset); three empty lists when the pattern was not fuzzy — Python's Match.fuzzy_changes.

    Match::fuzzy_counts

    fn Match::fuzzy_counts(self : Match) -> (Int, Int, Int)

    The edit counts of a fuzzy match, as (substitutions, insertions,deletions); all zero when the pattern was not fuzzy — Python's Match.fuzzy_counts.

    Match::group

    fn[K : GroupKey] Match::group(self : Match, group : K, default? : String?) -> String? raise
    Refused

    The substring the group captured, or default (preset None) if it took no part — Python's Match.group.

    Match::groupdict

    fn Match::groupdict(self : Match, default? : String?) -> Map[String, String]

    Named groups to their captured strings, default filling those that took no part — Python's Match.groupdict.

    Match::groups

    fn Match::groups(self : Match, default? : String?) -> Array[String?]

    All capturing groups (1..n) as strings, None for those that did not take part — Python's Match.groups.

    Match::item

    #alias("_[_]")
    fn[K : GroupKey] Match::item(self : Match, key : K) -> String? raise
    Refused

    m[1] and m["year"] — indexing is group.

    Match::lastgroup

    fn Match::lastgroup(self : Match) -> String?

    The name of the group lastindex points at, or None — Python's Match.lastgroup.

    Match::lastindex

    fn Match::lastindex(self : Match) -> Int?

    The number of the highest group that took part, or None — Python's Match.lastindex.

    Match::marks

    fn Match::marks(self : Match) -> Array[String]

    The names of the marks (*MARK:name) set during the match, in the order they were set — an empty list when none were.

    Match::partial

    fn Match::partial(self : Match) -> Bool

    Whether this match is a partial match — regex.Match.partial. True when the pattern was compiled with partial=true.

    Match::pattern

    fn Match::pattern(self : Match) -> Pattern

    The Pattern that produced this match.

    Match::pos

    fn Match::pos(self : Match) -> Int

    The pos the search started at — Python's Match.pos.

    Match::re

    fn Match::re(self : Match) -> Pattern

    The Pattern that produced this match — Python's Match.re.

    Match::slices

    fn[K : GroupKey] Match::slices(self : Match, group : K) -> Array[String] raise
    Refused

    The substrings the group captured, or an empty list when it took no part — Python's Match.slices.

    Match::span

    fn[K : GroupKey] Match::span(self : Match, group : K) -> (Int, Int) raise
    Refused

    The (start, end) span of a group.

    Match::start

    fn[K : GroupKey] Match::start(self : Match, group : K) -> Int raise
    Refused

    Code-point offset where the whole match begins.

    Match::string

    fn Match::string(self : Match) -> String

    The subject text.

    Pattern

    pub(all) struct Pattern {
    // private fields
    }

    A compiled pattern: the tree it came from, the flat program it became, and the source, so it can answer what Python's re answers of a Pattern — its string, its flags, how many groups, and what they are named.
    impl Add for Pattern
    impl BitOr for Pattern

    Pattern::add

    #deprecated("`Pattern::add` is deprecated, use `Add::add` instead.")
    fn Pattern::add(self : Pattern, other : Pattern) -> Pattern

    Pattern::capture

    fn Pattern::capture(self : Pattern, name : String) -> Pattern raise
    Refused

    This pattern wrapped in a named capture group, as Regex::capture in core.

    The group is numbered after the ones the pattern already has, and groupindex gains name.

    Pattern::dialect

    The dialect the pattern was read under.

    Pattern::dump

    fn Pattern::dump(self : Pattern) -> String

    The syntax tree re-printed, as Python's Pattern.dump would.

    Pattern::findall

    fn Pattern::findall(self : Pattern, text : String, group? : Group, overlapped? : Bool, pos? : Int, endpos? : Int, limit? : Int) -> Array[String?] raise
    Refused

    All non-overlapping matches, as findall at the module level.

    Pattern::finditer

    fn Pattern::finditer(self : Pattern, text : String, pos? : Int, endpos? : Int, overlapped? : Bool, limit? : Int) -> Array[Match] raise
    Refused

    All matches as Match objects, as finditer at the module level.

    Pattern::flags

    The effective flags.

    Pattern::full

    fn Pattern::full(self : Pattern, text : String, pos? : Int, endpos? : Int, limit? : Int) -> Match? raise
    Refused

    Match the whole region pos..endpos.

    Pattern::groupindex

    fn Pattern::groupindex(self : Pattern) -> Map[String, Array[Int]]

    Group name to slot, as Python's Pattern.groupindex.

    Pattern::groups

    fn Pattern::groups(self : Pattern) -> Int

    How many capturing groups the pattern has, group 0 not counted — Python's Pattern.groups.

    Pattern::lor

    #deprecated("`Pattern::lor` is deprecated, use `BitOr::lor` instead.")
    fn Pattern::lor(self : Pattern, other : Pattern) -> Pattern

    Pattern::lower

    The pattern as a core @string.Regex, when the core engine can run it.

    The core engine speaks one grammar, so this answers only for the patterns that fit inside it: literals, classes, ., ^, $, \b, \B, groups, alternation, quantifiers up to 256. Anything else — backreferences, lookaround, conditionals, recursion, atomic groups, fuzzy matching, \X, Unicode word boundaries, Python's $ — answers None, and the pattern runs on this library's own engine instead.

    The result is an ordinary @string.Regex: it can be handed to core's execute, find, split, replace_by, or to the lexer.

    Pattern::partial

    fn Pattern::partial(self : Pattern) -> Bool

    Whether the pattern was compiled for partial matching.

    Pattern::pattern

    fn Pattern::pattern(self : Pattern) -> String

    The pattern's source text.

    Pattern::prefix

    fn Pattern::prefix(self : Pattern, text : String, pos? : Int, limit? : Int) -> Match? raise
    Refused

    Match only at pos.

    Pattern::repeat

    fn Pattern::repeat(self : Pattern, min? : Int, max? : Int, greedy? : Bool) -> Pattern raise
    Refused

    This pattern repeated, as Regex::repeat in core: min to max times, greedily unless greedy is off.

    Pattern::scanner

    fn Pattern::scanner(self : Pattern, text : String) -> Scanner

    Bind a Pattern to a text so its methods can scan that text incrementally.

    Pattern::search

    fn Pattern::search(self : Pattern, text : String, pos? : Int, endpos? : Int, limit? : Int) -> Match? raise
    Refused

    Scan text for the leftmost match.

    Pattern::split

    fn Pattern::split(self : Pattern, text : String, maxsplit? : Int, pos? : Int, endpos? : Int, limit? : Int) -> Array[String?] raise
    Refused

    Split text on the pattern, as split at the module level.

    Pattern::string

    fn Pattern::string(text : StringView) -> Pattern

    A pattern that matches text literally, as @string.Regex::string does.

    Nothing in text is read as syntax — the caller does not have to escape it first.

    Pattern::sub

    fn Pattern::sub(self : Pattern, text : String, repl : String, count? : Int, pos? : Int, endpos? : Int, limit? : Int) -> String raise
    Refused

    Replace matches with repl, as sub at the module level.

    Pattern::sub_with

    fn Pattern::sub_with(self : Pattern, text : String, f : (Match) -> String raise
    Refused
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int) -> String raise
    Refused

    Replace matches with f(match), as sub_with at the module level.

    Pattern::subf

    fn Pattern::subf(self : Pattern, text : String, repl : String, count? : Int, pos? : Int, endpos? : Int, limit? : Int) -> String raise
    Refused

    Replace matches with repl, as regex.subf — repl is a format template whose fields name groups ({}, {0}, {name}, {0[0]}), with an optional :spec.

    Pattern::subfn

    fn Pattern::subfn(self : Pattern, text : String, repl : String, count? : Int, pos? : Int, endpos? : Int, limit? : Int) -> (String, Int) raise
    Refused

    Replace matches with repl, returning the new text and the count, as regex.subfn.

    Pattern::subn

    fn Pattern::subn(self : Pattern, text : String, repl : String, count? : Int, pos? : Int, endpos? : Int, limit? : Int) -> (String, Int) raise
    Refused

    Replace matches with repl, returning the new text and the count, as subn at the module level.

    Pattern::subn_with

    fn Pattern::subn_with(self : Pattern, text : String, f : (Match) -> String raise
    Refused
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int) -> (String, Int) raise
    Refused

    Replace matches with f(match), as subn_with at the module level.

    Scanner

    pub struct Scanner {
    // private fields
    }

    A Scanner walks a fixed text from left to right, each call picking up where the last left off — Python's regex.Scanner, and the loop re's finditer runs internally. Build one with Pattern::scanner.

    Scanner::findall

    fn Scanner::findall(self : Scanner, group? : Group, overlapped? : Bool) -> Array[String?] raise
    Refused

    Every remaining match from the current position, as group strings, advancing to the end of the text — Python's Scanner.findall.

    Scanner::finditer

    fn Scanner::finditer(self : Scanner, overlapped? : Bool) -> Array[Match] raise
    Refused

    Every remaining match from the current position, as Match objects, advancing to the end of the text — Python's Scanner.finditer.

    Scanner::full

    A full match of the region from the current position, advancing past it; None otherwise — Python's Scanner.full.

    Scanner::prefix

    A match anchored at the current position, advancing past it; None if the pattern does not match there — Python's Scanner.match.

    Scanner::search

    The next match from the current position, advancing past it; None once the text is exhausted — Python's Scanner.search.

    Scanner::split

    fn Scanner::split(self : Scanner, maxsplit? : Int) -> Array[String?] raise
    Refused

    Split the remaining text on the pattern, advancing to the end — Python's Scanner.split.

    Scanner::sub

    fn Scanner::sub(self : Scanner, repl : String, count? : Int) -> String raise
    Refused

    Replace every remaining match with repl, returning the new text — Python's Scanner.sub.

    Scanner::subn

    fn Scanner::subn(self : Scanner, repl : String, count? : Int) -> (String, Int) raise
    Refused

    Replace every remaining match with repl, returning the new text and advancing to the end — Python's Scanner.subn / Scanner.sub.

    ascii

    ascii — Python's re.ASCII.

    bestmatch

    bestmatch — regex.BESTMATCH.

    compile

    fn compile(pattern : StringView, flags? :
    Flags
    , dialect? :
    Dialect
    , lists? : Map[String, Array[String]], partial? : Bool) -> Pattern raise
    Refused

    Compile pattern into a Pattern.

    flags and dialect set the grammar; lists feeds \L<name> named lists; partial turns on partial matching. A pattern the grammar refuses is refused here, with where reading stopped.

    default_version

    The version the engine reads a Python pattern under when none is asked for.

    dialect

    The preset dialect: Python's re.

    dotall

    dotall — Python's re.DOTALL.

    ecma262

    The ECMA-262 RegExp dialect — JSON Schema and OpenAPI "string" patterns.

    enhancematch

    enhancematch — regex.ENHANCEMATCH.

    escape

    fn escape(pattern : StringView, dialect? :
    Dialect
    , special_only? : Bool, literal_spaces? : Bool) -> String

    Escape pattern so the result matches it literally, under dialect.

    The three grammars do not agree on what needs escaping, so the same string comes back spelled three ways:

    • Python — Python's re.escape: the characters that can mean something to the grammar are backslashed, everything else is left alone. With special_only off every non-alphanumeric is escaped; literal_spaces stops spaces from being escaped.
    • Ecma262 — RegExp.escape of ECMA-262: punctuation that is not a syntax character becomes \x.., syntax characters are backslashed, and a leading alphanumeric is spelled \x.. too so the result can never read as a quantifier's neighbour.
    • Lexmatch — the @string.Regex grammar: its metacharacters are backslashed and control characters are spelled in the escapes that grammar knows (\n, \t, \u{..}), never \x...

    findall

    fn findall(pattern : StringView, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , group? : Group, overlapped? : Bool, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> Array[String?] raise
    Refused

    All non-overlapping matches, as Python's re.findall.

    With no group named and the pattern holding one or none, the matches (or the single group) are returned. With two or more groups and no group given, the call is ambiguous and refused — pass group to say which to collect, or use finditer to walk Match objects that carry them all.

    finditer

    fn finditer(pattern : StringView, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , overlapped? : Bool, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> Array[Match] raise
    Refused

    All matches as Match objects, as Python's re.finditer.

    flags

    The preset flags, for callers who want to tweak one and keep the rest.

    full

    fn full(pattern : StringView, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> Match? raise
    Refused

    Match the whole region pos..endpos (Python's re.fullmatch).

    fullcase

    fullcase — Python's re.FULLCASE.

    ignorecase

    ignorecase — Python's re.IGNORECASE.

    lexmatch_dialect

    The MoonBit lexmatch dialect — @string.Regex and the lexer.

    multiline

    multiline — Python's re.MULTILINE.

    posix

    posix — regex.POSIX.

    prefix

    fn prefix(pattern : StringView, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , pos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> Match? raise
    Refused

    Match only at pos (Python's re.match): fail unless the pattern matches where the scan begins, not somewhere later in the text.

    python

    The Python re dialect — the default, and the one most callers want.

    reverse

    reverse — regex.REVERSE.
    fn search(pattern : StringView, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> Match? raise
    Refused

    Scan text for the leftmost match, as Python's re.search.

    split

    fn split(pattern : StringView, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , maxsplit? : Int, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> Array[String?] raise
    Refused

    Split text on the pattern, as Python's re.split.

    sub

    fn sub(pattern : StringView, repl : String, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> String raise
    Refused

    Replace matches with repl, as Python's re.sub.

    sub_with

    fn sub_with(pattern : StringView, f : (Match) -> String raise
    Refused
    , text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> String raise
    Refused

    Replace matches with the result of f(match), as Python's re.sub with a callable replacement.

    subf

    fn subf(pattern : StringView, repl : String, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> String raise
    Refused

    Replace matches with repl, as regex.subf — repl is a format template whose fields name groups ({}, {0}, {name}, {0[0]}).

    subfn

    fn subfn(pattern : StringView, repl : String, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> (String, Int) raise
    Refused

    Replace matches with repl, returning the new text and the count, as regex.subfn.

    subn

    fn subn(pattern : StringView, repl : String, text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> (String, Int) raise
    Refused

    Replace matches with repl, returning the new text and how many matches were replaced, as Python's re.subn.

    subn_with

    fn subn_with(pattern : StringView, f : (Match) -> String raise
    Refused
    , text : String, flags? :
    Flags
    , dialect? :
    Dialect
    , count? : Int, pos? : Int, endpos? : Int, limit? : Int, lists? : Map[String, Array[String]], partial? : Bool) -> (String, Int) raise
    Refused

    Replace matches with f(match), returning the new text and the count, as Python's re.subn with a callable replacement.

    unicode

    unicode — Python's re.UNICODE.

    verbose

    verbose — Python's re.VERBOSE.

    version

    let version : String

    The library version, as regex.__version__ reports it.

    version0

    version0 — regex.VERSION0.

    version0_value

    The V0 behaviour set, as a Version value — regex.VERSION0's target.

    version1

    version1 — regex.VERSION1.

    version1_value

    The V1 behaviour set, as a Version value — regex.VERSION1's target.

    version_info

    let version_info : (Int, Int, Int)

    The library version split into (major, minor, patch), as regex.__version_info__ reports it.

    word

    word — regex.WORD.

    Powered by MoonBit

    Site sourceReport issueModulesSkillsBuild queueStatistics

    © 2026 mooncakes.io