Skip to content

定义Definition

解析表达式文法 PEG

Parsing expression grammar · PEG

以有序选择、序列和不消费前看定义确定前缀识别结果的文法。

形式陈述 ​

解析表达式文法(PEG)用确定的识别过程定义语言。它包含有限终结符、有限非终结符、每个非终结符唯一对应的解析表达式,以及一个开始表达式。基础表达式为

e::=ε∣a∣A∣e1e2∣e1/e2∣e∗∣!e.

其中 e1/e2 是有序选择,!e 是不消费输入的否定前看。给定固定输入 w 和位置 i,识别结果要么为失败 ⊥,要么为下一位置 j≥i。以下操作语义固定了它们的含义:

  • ε 成功返回 i;字符 a 只在当前位置确为 a 时返回 i+1
  • A 按其唯一规则识别
  • e1e2 先在 i 识别 e1,成功到 j 后在 j 识别 e2;任一失败则整个序列失败
  • e1/e2 先在 i 试 e1;成功便返回其结果,只有失败才回到原位置 i 试 e2
  • e∗ 反复识别 e,第一次失败时成功停在本轮起点;不把已成功的重复次数主动退回以帮助后续表达式
  • !e 在 i 试 e:若 e 失败则成功返回 i,若成功则失败;两种情况都不消费输入

这些规则定义的是前缀识别。若要求整串接受,可令开始表达式为 e!.,其中点表示任意单字符;!. 仅在输入结束时成功。

本页限制到良构PEG:排除可在不消费输入的情况下循环调用自身的左递归,并要求重复体每次成功都消费至少一个字符。否则递归执行可能发散,不能把“未返回”当成正常失败。

直觉

CFG的备选规则表示“存在任意一条生成途径”;PEG的斜杠则是一条决定次序的指令。第一项一旦成功,选择已经完成,即使外层随后失败,也不会回头要求这次选择换用更长的第二项。

这给文法作者明确的消歧方式,也把顺序变成语言定义的一部分。短备选放在前面可能遮住长备选;这不是解析器偶然选错,而是它忠实执行了有序选择。

例子与边界

括号的位置改变回退边界 ​

比较以下两个开始表达式,并都要求输入结束:

P=("a"/"ab")"c",Q=("ab"/"a")"c".

在 abc 上,P 的第一项 "a" 成功到位置1,所以选择不再尝试 "ab"。随后 "c" 遇见位置1的 b 而失败,整个 P 拒绝。Q 则先匹配 ab 到位置2,再匹配 c,整串成功。

再看

R=("a""c")/("ab""c").

R 的左备选是完整的 "a" "c";它在 b 处失败,外层选择因此回到位置0并尝试右备选,最终接受。于是

(e1/e2)e3不总等价于(e1e3)/(e2e3).

这里不是只改变了实现效率,而是真正改变了哪些输入被接受。生成式文法中熟悉的代数改写,搬到PEG前必须核对回退边界。

关键字边界与不消费前看 ​

想识别关键字 if,却不把标识符 iffy 的前缀误认成关键字,可定义

Keyword←"if" !Letter.

在 if( 上,前两字符成功,当前位置是 (,Letter失败,否定前看成功但不吃掉括号。在 iffy 上,前两字符之后还是字母 f,否定前看失败,Keyword整体失败;外围的标识符备选可以从原起点重新识别全部 iffy。

!e 是关于解析成功与否的判断,不是自动生成补语言的字符类。它永不消费;要在“不以某模式开头”的条件下消费一个字符,需另外接点或其他消费表达式。

贪婪重复不会为了后缀退让 ​

表达式 "a"* "a" 在非空全a串上失败:星号先消费所有a,末尾那个a再无输入可读。若希望至少一个a,应写 "a" "a"*。这与某些带回溯的正则表达式引擎会减少重复次数的行为不同。

(ε)* 的重复体每次成功却不前进;A←A "a"/"a" 又在消费之前再次调用A。两者都超出本页良构条件。支持左递归的PEG实现需要额外的种子增长等算法及其复杂度分析,不能仅加一个缓存就宣称问题消失。

推论与应用

对会终止的PEG识别,输入和表达式决定唯一结果。这并不说明它识别的是某个CFG的“唯一正确树”,而是文法已经通过优先选择规定了一个结果。若原任务需要保留自然语言的多种解析,Earley或GLR的森林更符合目标。

直接递归执行仍可能指数重复。Packrat利用结果唯一性,把每个规则在每个位置的结果缓存起来;良构、无外部可变状态及每表项工作有界等条件满足时,得到固定文法下的线性时间。

单元支线任务及解答 ​

判断 P,Q,R 在 ac、abc、abbc 上是否整串接受,并解释有序选择。解答为:ac 三者都接受;abc 只有 Q,R 接受;abbc 三者都拒绝。最后一个串中,即便匹配了 ab,下一字符仍是 b,后面的 c 无法匹配。

验收要记录每次选择的起点及成功后的位置,特别是 P 在 abc 上不能改用第二分支,而 R 可以。这一差异就是有序选择作用范围的具体证据。

参考资料
关系图谱7 个相邻概念 · 4 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系