我在我的PEG解析器中添加了零个或多个和一个或多个修饰符,这很简单,因为 PEG 中的回溯很少。早期的迭代永远不会重新考虑,所以一个简单的while
循环就足够了。
然而,在其他情况下,零个或多个和一个或多个修饰符确实需要回溯。例如,采用以下正则表达式:
(aa|aaa)+
这个表达式应该能够贪婪地匹配一个由 7 组成的字符串a
:有几种方法可以将 2 和 3 相加得到 7。但要做到这一点,重新考虑早期的迭代是必要的。例如,如果表达式a
第一次匹配 3 a
,第二次匹配 3,则只剩下一个a
,无法匹配。但是,回溯最后三个a
并匹配两个a
,然后匹配五个a
。然后最后两个a
也可以匹配(即3 + 2 + 2 = 7)。
幸运的是,正则表达式在匹配字符串后退出搜索。但是EBNF解析器呢?如果语法不明确,解析器将使用回溯查找所有可能的语法树!如果我们有生产
( "aa" | "aaa" )*
和一个由 7 组成的字符串a
,一个完全回溯的解析器将返回用 2 和 3 来表达 7 的所有可能方式。这只是针对 7a
的:匹配一个稍长的字符串,并且N叉树的可能性会增长另一个层次。考虑N = 6:
S : ( T )*
;
T : A
| B
| C
| D
| E
| F
;
恐怖的组合爆炸!
然而,真的会是这样吗?EBNF中对零个或多个修饰符和一个或多个修饰符没有限制吗?按照描述实现它们比while()
PEG 解析器的普通循环要多得多,所以我不得不怀疑......