编译器设计中的错误恢复策略
错误可能发生在不同的编译级别,因此错误处理对于代码的正确执行很重要。主要有五种错误恢复策略,分别是:
- 恐慌模式
- 相级恢复
- 错误产生
- 全局修正
- 符号表
恐慌模式:
大多数解析方法都使用此策略。在这种发现错误的方法中,解析器一次丢弃一个输入符号。这个过程一直持续到找到一组指定的同步令牌。同步标记是分隔符,例如分号或结尾。这些标记表示输入语句的结束。
因此,在恐慌模式恢复中,大量的输入会检查它是否有额外的错误。如果同一语句中的错误数量较少,则此策略是最佳选择。
例子:
C
int a, 5abcd, sum, $2;
C
int a,b
// AFTER RECOVERY:
int a,b;
// 在 int a, 5abcd , sum, $2之后; // 解析器一次丢弃一个输入符号。
优势:
- 它很容易使用。
- 程序永远不会陷入循环。
坏处:
- 这种技术可能会在进一步的阶段导致语义错误或运行时错误。
相级恢复:
在此策略中,在发现错误解析器时,将对剩余输入执行原始更正。它可以用一些字符串替换剩余输入的前缀。这实际上有助于解析器继续其工作。最初的更正可以是用分号替换逗号、省略分号或拟合缺少的分号。这种类型的原始更正由编译器开发人员决定。
例子:
C
int a,b
// AFTER RECOVERY:
int a,b;
优点:此方法用于修复编译器的许多错误。
缺点:在进行替换时,应防止程序陷入死循环。
错误产生:
它需要对可能遇到的常见错误有很好的了解,然后我们可以通过产生错误结构的错误产生来扩充相应语言的语法。如果在解析过程中使用了错误生成,我们可以生成适当的错误消息来指示输入中已识别的错误。这种方法维护起来非常不同,因为如果我们改变语法,那么就需要改变相应的产生式。
示例:假设输入字符串是 abcd。
语法:S-> A
A-> aA |巴|一个 | b
B-> 光盘
输入字符串不能通过上面的语法得到,所以我们需要添加Augmented Grammar。
语法:E->SB // 增强语法
S-> A
A-> aA|巴|一个 | b
B-> 光盘
现在,可以获取字符串abcd。
好处:
- 句法阶段错误通常通过错误产生来恢复。
缺点:
- 该方法很难维护,因为如果我们更改语法,则需要更改相应的产生式。
- 开发人员很难维护。
全局校正:
我们经常希望这样的编译器在处理不正确的输入字符串时只做很少的改动。给定不正确的输入字符串x 和语法 G ,算法本身可以找到相关字符串y 的解析树;这样,将 x 转换为 y 所需的令牌的插入、删除和更改次数尽可能少。全局校正方法增加了解析时的时间和空间要求。这只是一个理论概念。
优点:在处理不正确的输入字符串时几乎没有什么变化。
缺点:它只是一个理论概念,无法实现。
符号表:
在语义错误中,通过使用对应标识符的符号表来恢复错误,如果两个操作数的数据类型不兼容,编译器会自动进行类型转换。
优点:它允许基本的类型转换,我们通常在现实生活中进行计算。
缺点:只能进行隐式类型转换。