编译器设计 - 错误恢复

  • 简述

    解析器应该能够检测并报告程序中的任何错误。预计当遇到错误时,解析器应该能够处理它并继续解析输入的其余部分。大多数情况下,解析器会检查错误,但在编译过程的各个阶段可能会遇到错误。一个程序在不同阶段可能会出现以下类型的错误:
    • Lexical: 某些标识符的名称输入错误
    • Syntactical: 缺少分号或不平衡的括号
    • Semantical: 不兼容的赋值
    • Logical: 代码不可达,无限循环
    有四种常见的错误恢复策略可以在解析器中实现以处理代码中的错误。

    恐慌模式

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

    语句模式

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

    错误产生

    编译器设计者知道代码中可能出现的一些常见错误。此外,设计人员可以创建要使用的增强语法,作为在遇到这些错误时生成错误结构的产品。

    全局修正

    解析器将手头的程序作为一个整体来考虑,并试图找出程序打算做什么,并试图找出最接近的匹配项,这是没有错误的。当输入错误的输入(语句)X 时,它会为一些最接近的无错误语句 Y 创建解析树。这可能允许解析器对源代码进行最小的更改,但由于复杂性(时间和空间)这一战略,尚未在实践中实施。

    抽象语法树

    解析树表示不容易被编译器解析,因为它们包含的细节比实际需要的要多。以下面的解析树为例:
    解析树
    如果仔细观察,我们会发现大多数叶节点都是其父节点的单个子节点。在将其馈送到下一阶段之前,可以消除此信息。通过隐藏额外的信息,我们可以获得如下所示的树:
    抽象语法树
    抽象树可以表示为:
    抽象语法树表示
    AST 是编译器中的重要数据结构,其中不必要的信息最少。AST 比解析树更紧凑,并且可以很容易地被编译器使用。