扩展库 / xregex

xregex

文本处理

基于 BBRE 的正则表达式。复用编译结果和执行缓存,提供捕获、模板与回调替换、逐项拆分、多模式集合;与 C 共用 XRT 的内存和错误模型。

编译与便捷入口

import xregex

auto route = xregex.compile("^/users/(?<id>[0-9]+)$")
auto matcher = route.matcher()
if matcher.full("/users/42") then
    println(matcher.capture(route.captureIndex("id")).text)
end
接口合同
compile(pattern, flags=0, maxPatternBytes=1048576, maxCaptures=4096)返回不可变 Regex。预算须大于零,捕获数量包含完整匹配组 0。
compileSet(patterns, flags=0, maxPatternBytes=1048576, maxCaptures=4096)array<string> 输入,返回 RegexSet,允许空集合;预算按每个模式计算。
test(pattern, text, flags=0) / fullMatch(pattern, text, flags=0)一次性搜索或完整匹配,返回 bool;每次编译,没有隐式全局缓存。
valid(pattern) / escape(text)语法验证返回 bool;escape 返回正则字面量转义字符串,不是替换模板转义。

编译标志按位或组合:IGNORE_CASE=1、MULTILINE=2、DOT_ALL=4、UNGREEDY=8。 默认预算常量为 DEFAULT_MAX_PATTERN_BYTES、DEFAULT_MAX_CAPTURES;它们不是整个集合、输入、结果或 CPU 时间的统一预算。

匹配与捕获

所有位置和长度均按 UTF-8 字节计数,从零开始,区间为 [begin, endPos)。它们不是字符切片参数。

类型 / 成员合同
Regex.valid / pattern / flags / captureCount有效性、模式原文、标志和包含组 0 的捕获数量。
captureName(index) / captureIndex(name)有效未命名捕获返回空串;名称不存在返回 -1;下标越界报 IndexError。
test(text, start=0) / fullTest(text)返回 bool;前者搜索,后者覆盖完整输入。
find(text, start=0) / matchAt(text, start=0)返回 RegexMatch?;后者要求从指定位置匹配,未命中均为 null。
findAll(text, start=0)返回 array<RegexMatch>,未命中为空数组。
matcher()创建 RegexMatcher,保留表达式引用并复用执行缓存。
RegexMatcher.find / at / full / nextfind/at 参数为 text、start=0;full 接受 text;next 无参数。均返回 bool。空匹配按 UTF-8 标量推进。
RegexMatcher.valid / matched / capture(index=0)有效性、是否存在当前匹配、复制当前捕获;capture 要求有当前匹配。
RegexMatch.group / matched / begin / endPos / length / text捕获序号、参与状态、字节区间与独立字符串。未参与捕获与合法空捕获用 matched 区分。

XL matcher 在 find/at/full 时持有输入副本,next 不再复制全文。捕获结果可跨后续匹配和对象释放保留。 只需判断时使用 bool 接口,避免复制捕获。C 底层 matcher 借用输入,所有者必须保持输入有效。

替换与回调

Regex.replace(text, replacement, limit=-1) 支持 $0、$1、${name},$$ 表示字面量 $。 replaceFirst(text, replacement) 只替换一次。

import xregex
from xregex import RegexMatcher

auto digits = xregex.compile("[0-9]+")
println(digits.replaceWith("a1 b22", func(RegexMatcher current) as string
    return "[" + current.capture().text + "]"
end))   // a[1] b[22]

replaceWith(text, func(RegexMatcher) as string fn, limit=-1) 同步调用回调,其返回值原样写入,不再次解释为模板。 limit=-1 为全部,0 不调用回调,其他负值非法。回调异常保留原类型;可以嵌套独立匹配,但应只读取传入 matcher,不重新搜索或推进它。

逐项拆分

Regex.splitter(text, limit=-1, includeCaptures=false, skipEmpty=false) 返回 RegexSplitter; splitParts 使用相同参数,返回 array<RegexSplitPart>; split(text, limit=-1, skipEmpty=false) 返回普通字段 array<string>。

limit 限制分隔匹配次数,不是结果项数;0 不使用匹配,-1 不限次数。skipEmpty 对普通字段和捕获项都过滤空文本。 底层标志为 SPLIT_CAPTURES=1、SPLIT_SKIP_EMPTY=2。

RegexSplitter 的 valid 表示句柄有效,next() 返回 RegexSplitPart?,结束后为 null。 RegexSplitPart 包含 text、capture、matched、isCapture;capture=-1 为普通字段。XL splitter 持有输入副本,C splitter 借用输入。 这是逐项输出接口,不是接收分块网络输入的增量解析器。

多模式集合

成员合同
RegexSet.valid / count / regex(index)有效性、模式数量、取得带有独立引用的 Regex。
test(text, start=0) / matches(text, start=0) / first(text, start=0)返回 bool、命中索引数组、最小命中索引;未命中为 false、[]、-1。
matcher() as RegexSetMatcher复用集合执行缓存,search(text, start=0) 返回是否命中。
RegexSetMatcher.valid / count / first有效性、命中数量、最小命中模式索引。
index(index) / matched(pattern) / indices()读取第 index 项、查询指定模式、复制索引数组;非法模式索引 matched 返回 false,index 越界抛 IndexError。

结果按模式索引升序,不按文本出现顺序。集合经公开 xvalue API 读取 array<string>,完成编译后不再借用数组。

错误与资源

普通未命中不是异常。非法语法、标志、非正预算和 limit 为 ValueError;字节位置/下标越界为 IndexError; 原生资源超限为 RangeError;分配失败为 MemoryError。valid 只对非法语法返回 false,不吞掉内存或资源故障。

errorOffset(error value) 读取语法字节位置,errorPatternIndex(error value) 读取集合编译失败的模式索引; 没有对应信息或传 null 返回 -1。查询明确的 catch 错误对象,允许跨后续调用保存。

import xregex

try
    xregex.compileSet(["ok", "("])
catch ValueError problem
    println(xregex.errorPatternIndex(problem))   // 1
    println(xregex.errorOffset(problem))
end

Regex/RegexSet 不可变;不同 matcher 可独立运行。同一可变 matcher、splitter 或 set matcher 必须串行访问。 Regex、RegexMatcher、RegexSplitter、RegexSet、RegexSetMatcher 的 nativeHandle() 都返回底层借用指针,不能重复接管或由 C 擅自释放。

C API 与双语范例

公共头为 extlibs/xregex/include/xregex.h。xrtRegexConfigInit、xrtRegexSplitConfigInit 初始化配置; xrtRegexCompile、xrtRegexMatcher*、xrtRegexReplaceTo/ReplaceFuncTo、xrtRegexSplitter*、xrtRegexSet* 提供相同核心能力。 执行结果为 XREGEX_ERROR / XREGEX_NONE / XREGEX_MATCH 三态。

C 输入和捕获 xstrview 为借用;核心拥有型 str 使用 xrtFree,包装返回的 xbuffer* 使用 xrtBufferDestroy。 xrtRegexSetRegex 返回集合内借用表达式,独立保留需 xrtRegexRef;XL set.regex 已处理引用。

包使用 ERROR_FORMAT、IO_BUFFER、STRING_SPLIT、UNICODE、VALUE_CONTAINER。裁剪产物使用包内正则实现; 完整 C 环境已提供 XRT 正则时,不重复编译相同实现。所有原生编译单元必须采用一致的模块选择。

XL 教学:examples/extlibs/xregex.xl;对照:examples/extlibs/xregex_basic.xl 与 extlibs/xregex/examples/basic.c。共同预期为 examples/extlibs/xregex_basic.expected.txt。 发行包内 README 提供完整参数与运行命令。

验证范围

2026-09-27 限定基线覆盖 Windows C/XL、JIT/AOT、49 个实际生成的绑定原型、输入及捕获寿命、空匹配推进、 错误对象保留、回调异常与重入、逐点分配失败和双语黄金输出。门禁为 tools/check_extlib_xregex.ps1。

独立 Linux C 使用 ASan/UBSan 和泄漏检查,并核对 LP64 原型,门禁为 tools/check_extlib_xregex.sh。 不表示 Linux xlang JIT/AOT、32 位/ARM、同一可变对象并发或完整性能基准已验收。源码和构建变化后须重新验证。