*** 本篇文章是个人对 Guido 有关 Packrat PEG 解析器文章的处理左递归部分的理解和总结。***
左递归
众所周知,PEG 解析器的一个缺陷就在于无法解析具有左递归的文法,而大多数情况下,CFG 使用左递归文法会让很多事情变得简单。下面的 PEG 文法列出了一个简单的左递归实例:
expr: expr '+' term | term
term: NAME
如果我们使用 PEG 解析器生成器生成对应的 Parser,那它大概率会有如下形式:
def expr(p):
# ...
if expr(p) and p.except('+') and term(p):
# ...
# ...
不难发现,这个函数将会不断递归调用下去,直至函数调用栈溢出。这就是所谓的 “左递归”,也是传统 PEG 解析器的问题。
面对左递归,生成式文法可以使用许多办法来处理左递归,然而实际上,解析式文法处理左递归也已经有很多学术上的方法。
Guido 的 Pegen 受到了 这位大佬 的启发,解决了左递归的问题。
memoize
pegen 的一个重要的实现是 memoize,实际上这来源于 Packrat 解析器。memoize 的核心是维护一个缓存(下文将其称为 memo),这个缓存记录了 Parser 的解析光标位置和对应的状态的返回值:
memo: pos -> (state, arg) -> return

文章探讨了PEG解析器处理左递归的挑战,指出传统的PEG解析器在遇到左递归文法时可能导致无限递归和栈溢出。Guido的Pegen解析器采用memoize技术,源自Packrat解析器,通过维护一个缓存来存储解析状态,从而有效地解决这个问题。缓存记录了解析位置和对应的状态返回值,避免了重复计算,确保了解析的效率和正确性。

被折叠的 条评论
为什么被折叠?



