编译器设计 - 错误恢复



解析器应该能够检测并报告程序中的任何错误。当遇到错误时,预期解析器能够处理它并继续解析其余的输入。大多数情况下,期望解析器检查错误,但错误可能会在编译过程的各个阶段遇到。程序在各个阶段可能出现以下几种错误:

  • 词法错误:某些标识符的名称输入错误

  • 语法错误:缺少分号或括号不平衡

  • 语义错误:不兼容的值赋值

  • 逻辑错误:代码不可达,无限循环

解析器中可以实现四种常见的错误恢复策略来处理代码中的错误。

恐慌模式

当解析器在语句中的任何位置遇到错误时,它会忽略语句的其余部分,而不处理从错误输入到分隔符(例如分号)的输入。这是最简单的错误恢复方法,并且它还可以防止解析器陷入无限循环。

语句模式

当解析器遇到错误时,它会尝试采取纠正措施,以便语句的其余输入允许解析器继续解析。例如,插入缺少的分号,用分号替换逗号等。解析器设计者在这里必须小心,因为一个错误的更正可能会导致无限循环。

错误产生式

编译器设计者知道代码中可能发生一些常见的错误。此外,设计者可以创建增强的语法以用作产生式,当遇到这些错误时,这些产生式会生成错误的结构。

全局校正

解析器将程序作为一个整体来考虑,并试图弄清楚程序的意图,并试图找到一个最接近的无错误匹配。当输入错误的输入(语句)X时,它会为某个最接近的无错误语句Y创建解析树。这可以允许解析器对源代码进行最小更改,但是由于此策略的复杂性(时间和空间),它尚未在实践中实现。

抽象语法树

解析树表示不容易被编译器解析,因为它们包含比实际需要的更多细节。以下面的解析树为例

Parse Tree

如果仔细观察,我们会发现大多数叶子节点都是其父节点的单个子节点。此信息可以在将其馈送到下一阶段之前消除。通过隐藏额外信息,我们可以获得如下所示的树

Abstract Syntax Tree

抽象树可以表示为

Abstract Syntax Tree Representation

AST 是编译器中重要的数据结构,其中包含最少的冗余信息。AST 比解析树更紧凑,并且可以很容易地被编译器使用。

广告