错误恢复

框架中的_parse函数(位于syntax/src/parser_ll.rs)已经实现了一部分,然而尚未实现错误恢复的功能,遇到错误时会直接unimplemented!(),这是大家需要完成的实验任务。

在lecture4中,我们介绍了应急恢复和短语层恢复的方法。这里,我们使用一种介于二者之间的错误恢复方法:与应急恢复的方法类似,当分析非终结符AA时,若当前输入符号aBegin(A)a \notin Begin(A),则先报错,然后跳过输入符号串中的一些符号,直至遇到Begin(A)End(A)Begin(A) \bigcup End(A)中的符号:

  • 若遇到的是Begin(A)Begin(A)中的符号,可恢复分析A,即可以选择一个左端为AA的产生式来分析它

  • 若遇到的是End(A)End(A)中的符号,则A分析失败,返回StackItem::_Fail,继续分析AA后面的符号

这个处理方法与应急恢复方法的不同之处在于:

  • 我们用集合Begin(A)={sPS[As]非空}Begin(A) = \{s | PS[A, s]非空\}(其中,PSPS为预测分析表)来代替First(A)First(A)。由于First(A)Begin(A)First(A) \in Begin(A),我们能少跳过一些符号

  • 我们用集合End(A)=Follow(A)FEnd(A) = Follow(A) \bigcup F(其中,F为_parse函数传入的最后一个参数)来代替Follow(A)Follow(A)。由于FF集合包含了AA各父节点的FollowFollow集合,我们能少跳过一些符号,同时由于结束符(_Eof)必然属于文法开始符号的FollowFollow集合,本算法无需额外考虑因读到文件尾而陷入死循环的问题。

另外,当匹配终结符失败时,只报错,但不消耗此匹配失败的终结符,而是将它保留在剩余输入串中。这个逻辑已经在_parse函数中实现。

Last updated