4.5 KiB
4.5 KiB
NGRA Regex 源生成手写样本
这个文件用于记录源生成器实现前需要手写的正则匹配样本。
流程:
- 选一个表达式。
- 手写理想匹配代码。
- 生成优化后 IR。
- 对照手写代码和 IR 段。
- 标注每段 IR 应该生成的代码形状。
- 抽取生成器规则。
选样原则:
- 表达式必须是典型正则写法。
- 全部样本合起来应覆盖计划支持的大部分 regex 语法。
- 样本不以表达式结构优化为目标,避免依赖公共前缀提取、分支树重排等 AST 优化。
TRY/CONDITION前缀化改写属于 IR 执行形态整理,不算表达式优化。
记录模板
Regex:
覆盖形态:
期望代码形状:
Optimized IR:
IR -> Code 规则:
备注:
第一批:基础线性匹配与转义
| Regex | 覆盖形态 | 手写重点 |
|---|---|---|
abc |
单个 MATCH_SEQ |
最小长度检查、序列匹配、活动指针推进 |
a[abc]d |
MATCH_SEQ + MATCH_SET + MATCH_SEQ |
set 后端展开前的调用边界 |
[abc] |
单个 MATCH_SET |
字符集单字符匹配 |
[.] |
set 中的字面点号 | 确认 [.] 和 . 语义分离 |
. |
任意字符匹配 | MATCH_SET "." 的特殊后端语义 |
\. |
转义字面点号 | 确认 \. 进入 seq 系 IR |
a\*b |
转义操作符字面量 | tokenizer 已消解转义语义 |
第二批:计数
| Regex | 覆盖形态 | 手写重点 |
|---|---|---|
a* |
COUNT_SEQ,MIN:0 MAX:-1 |
贪婪计数、允许空匹配 |
a+ |
COUNT_SEQ,MIN:1 MAX:-1 |
至少一次的计数 |
a? |
COUNT_SEQ,MIN:0 MAX:1 |
可选单元 |
a{3,5} |
固定下限 + 可选上限 | 下限展开与剩余计数 |
[abc]* |
COUNT_SET |
字符集循环 |
.{11,13} |
任意字符计数 | set 语义在后端展开 |
第三批:ALT 与前缀化
| Regex | 覆盖形态 | 手写重点 |
|---|---|---|
| `a | b` | 最小 ALT |
| `ab | cd | ef` |
| `a | bc | def` |
| `(ab | [cd] | .)x` |
第四批:复杂计数块
| Regex | 覆盖形态 | 手写重点 |
|---|---|---|
(ab){2,3} |
COUNT complex body |
complex body 调用域、计数退出 |
| `(123(4 | 5)67){3,4}114514` | complex count + ALT + 后缀 |
第五批:FIND 与 .*
| Regex | 覆盖形态 | 手写重点 |
|---|---|---|
.*abc |
最远/最近搜索前缀 | FIND_SEQ 或 FIND_COMPLEX 到后续锚点 |
abc.* |
后缀任意吞吐 | 尾部 .* 的快速成功策略 |
[.]* |
字面点号计数 | 不应被当成原装 .* 优化 |
第六批:字符集语义
| Regex | 覆盖形态 | 手写重点 |
|---|---|---|
[123abc] |
离散字符集 | set 后端展开为离散匹配 |
[1-9] |
连续字符集 | set 后端展开为范围匹配 |
\w |
转义字符集 | escape-set 后端语义 |
\w+ |
转义字符集计数 | set 计数循环 |
第七批:捕获组
| Regex | 覆盖形态 | 手写重点 |
|---|---|---|
(abc) |
普通捕获组 | 默认序号 group |
(?<name>abc) |
简单命名组 | group 起止范围、PACK |
(?<name>.*)234 |
group 内 .* + 后续锚点 |
FIND_COMPLEX FURTHEST -1 与后续 MATCH_SEQ |
(?<name>.*)a |
group 内 .* + 单字符锚点 |
最远搜索回退到后缀匹配 |
| `(?abcd | a(bc)c)` | group 内 ALT |
| `a*.[abc]*(?abcd | a(bc)c)(?.*)234` | 综合样本 |
当前优先级
第一阶段只要求源生成器能稳定处理:
MATCH_SEQMATCH_SETCOUNT_SEQCOUNT_SET- 简单
ALT PACKFIND_SEQFIND_COMPLEX COUNT:-1
低优先级:
- 逐 region 最短长度断言。
- 复杂字符集完全内联。
- 公共前缀提取和代码树生成。
- 对所有正则语义做完整兼容。
手写代码关注点
每个样本的手写代码都应尽量确认这些点:
- 活动指针如何推进。
- 失败时是否需要恢复活动指针。
- region result 和 single-line result 是否必须分配。
Observe_Line是否只读取目标行结果。Observe_Region是否只读取目标 region 结果。PACK使用哪一个成功结果作为捕获区间。- 最小长度检查是否值得在当前样本中生成。