编写 PEG 规则时需要注意它们是贪婪的。 可以消耗可变长度文本的规则总会尽可能消耗最多内容, 即使这会导致后续原本可能匹配的规则失败——不存在回溯。 例如,这条规则永远不会成功:
(forest (+ "tree" (* [blank])) "tree" (eol))
PEX (+ "tree" (* [blank])) 会消耗掉所有单词 ‘tree’ 的重复出现,
导致没有剩余内容匹配最后的 ‘tree’。
在这类场景中,可以通过使用谓词与守卫(即 not、if 与 guard 表达式)
约束行为以获得预期结果。例如:
(forest (+ "tree" (* [blank])) (not (eol)) "tree" (eol))
if 与 not 运算符接收一个解析表达式并将其解释为布尔值,
且不会移动点位置。guard 运算符中的内容会作为普通 Lisp 代码
(而非 PEX)求值,并应返回布尔值。nil 值会导致匹配失败。
另一个可能出乎意料的行为是,即使解析最终失败, 解析过程仍会尽可能移动点位置。这条规则:
(end-game "game" (eob))
在点之后包含文本 “game over” 的缓冲区中运行时,
会将点移动到 “game” 之后,然后停止解析并返回 nil。
成功的解析总会返回 t,或是解析栈中的内容。