第 4 章 · 05 实现基础语法:字符类、量词、锚点 本节摘要:前四节讲了理论与核心算法,这一节动手实现正则的基础语法:字符类( )、量词( )、锚点( )、通配符( )。我们要把这些「语法糖」映射到前几节建立的 NFA 基本构造上——比如 就是「26 个单字符的选择」, 等价于 。理解这种「语法糖 ↔ 基本构造」的映射,你就能支持丰富的正则语法,而引擎内核仍是 Thompson 构造。 内容来源:基于正则语法与引擎实现整理的导读。 学习目标 阅读完本节,你应当能够: 把字符类 、 、 映射为选择构造(扩展到字符集转移)。 把量词 (一个或多个)、 (零或一)、 映射为闭包构造的变体。 实现锚点 (行首)、 (行尾)为「零宽断言」——不消耗字符,只检查位置。
本节摘要:前四节讲了理论与核心算法,这一节动手实现正则的基础语法:字符类(
[a-z])、量词(* + ? {m,n})、锚点(^ $)、通配符(.)。我们要把这些「语法糖」映射到前几节建立的 NFA 基本构造上——比如[a-z]就是「26 个单字符的选择」,a+等价于aa*。理解这种「语法糖 ↔ 基本构造」的映射,你就能支持丰富的正则语法,而引擎内核仍是 Thompson 构造。
内容来源:基于正则语法与引擎实现整理的导读。
阅读完本节,你应当能够:
[a-z]、[abc]、[^abc] 映射为选择构造(扩展到字符集转移)。+(一个或多个)、?(零或一)、{m,n} 映射为闭包构造的变体。^(行首)、$(行尾)为「零宽断言」——不消耗字符,只检查位置。. 为「任意字符」的转移。正则有几十种语法元素,看上去复杂。但本节的核心洞察是:绝大多数语法都是「糖」,内核仍是 Thompson 构造的四种基本模板(字符/连接/选择/闭包)。把语法糖翻译成基本构造,引擎内核不用改,只需扩展解析器。
这种「语法层丰富、内核层简洁」的设计,是优秀引擎的标志——也是第 9 章编译器「AST 优化」的预演(很多语法糖在 AST 层就被化简成基本构造了)。
[...][abc] 等价于 a|b|c (选择) [a-z] 等价于 a|b|c|...|z (选择, 扩展为范围) [^abc] 等价于 "非 a 且非 b 且非 c" (补集, 需特殊转移)
实现:把字符类展开成一个「字符集转移」——NFA 的转移不标单个字符,而标一个字符集(或补集)。
a* 零个或多个 ← 闭包(基本构造) a+ 一个或多个 等价于 aa* (连接 + 闭包) a? 零个或一个 等价于 (a|ε) (选择, 含空) a{m} 恰好 m 个 等价于 aaa...a (m 次连接) a{m,n} m 到 n 个 等价于 aa...a a? a? ... (m 次连接 + (n-m) 个可选)
所有量词都能化简为「连接 + 闭包 + 选择」的组合。解析时把它们展开成这些基本构造即可。
.. 匹配除换行外的任意字符。实现:标为「任意字符集」的转移(除 \n)。
^ 与 $^ 行首 不消耗字符, 只在"位置是行首"时允许通过 $ 行尾 不消耗字符, 只在"位置是行尾"时允许通过
锚点是「零宽断言」——不读字符,只检查位置。实现:特殊转移,匹配「位置」而非「字符」。这扩展了纯自动机模型(纯自动机只认字符),但实现简单:在匹配循环里特殊处理。
[、]、{、}、^、$、. 等。[A-Z][a-z]+ 匹配单词、^error 匹配行首 error、.* 匹配任意行。+ ? {m,n})化简为连接+闭包+选择。^ $)是零宽断言,不消耗字符只检查位置,需特殊转移。[abc] [a-z](展开为选择)。+ ? {m,n}(展开为连接+闭包)。.(任意字符转移)。^ $(零宽,需匹配循环特殊处理)。[A-Z]\w*、^From:、https?:// 等真实模式。下一节讲分组、选择与捕获组——以及为什么捕获组让引擎倒退回回溯。