我正在阅读Ullman 等人的文本编译器:原理、技术和工具。我在预测解析中遇到了恐慌模式恢复的概念。文本中提到了一些应该遵循的启发式方法。但他们在本文后面给出的例子仅说明了要点(1)
和(5)
启发式方法。
恐慌模式错误恢复基于跳过输入上的符号直到出现所选同步标记集中的标记的想法。其有效性取决于同步集的选择。应该选择这些集合,以便解析器从实践中可能发生的错误中快速恢复。
一些启发式方法如下:
作为起点,我们可以将所有符号
FOLLOW(A)
放入 nonterminal 的同步集中A
。如果我们跳过标记,直到FOLLOW(A)
看到一个元素并从堆栈中弹出A
,则解析可能会继续。
FOLLOW(A)
仅用作 的同步集是不够的A
。例如,如果分号终止语句,如C
,则开始语句的关键字可能不会出现在FOLLOW
非终结生成表达式的集合中。因此,赋值后缺少分号可能会导致下一条语句开始的关键字被跳过。通常,语言中的结构存在层次结构。例如,表达式出现在语句中,语句出现在块中,等等。我们可以将开始较高结构的符号添加到较低结构的同步集中。例如,我们可以将开始语句的关键字添加到非终结符生成表达式的同步集中。如果我们将符号 in 添加
FIRST(A)
到 nonterminal 的同步集中A
,则可以根据输入中A
是否出现符号 in来恢复解析FIRST(A)
。如果非终结符可以生成空字符串,则
\epsilon
可以将产生式推导用作默认值。这样做可能会推迟一些错误检测,但不会导致遗漏错误。这种方法减少了在错误恢复期间必须考虑的非终结符的数量。如果堆栈顶部的终端无法匹配,一个简单的想法是弹出终端,发出一条消息说终端已插入,然后继续解析。实际上,这种方法将一个令牌的同步集包含在所有其他令牌中。
一般来说,我无法理解点中所述启发式的含义(4)
。
谁能给我一个(或多个)点(2), (3) , (4)
可能有用的例子。虽然我可以理解除 之外的所有点的含义(4)
,但由于本书没有说明点 (2)、(3) 和 (4),因此举个例子可以帮助我更好地理解这件事。