错误处理目标
语法错误检测到后,分析器应:
- 清晰报告错误位置和类型
- 从错误中恢复,继续分析后续输入
- 避免级联错误(大量虚假错误)
四种错误恢复策略
紧急恢复(Panic Mode)
最简单的方法。
从错误点开始丢弃输入符号,直到遇到同步符号(如 ;、}、end 等)。
- 优点:简单,避免死循环
- 缺点:可能跳过大量有效代码
短语级恢复(Phrase-Level Recovery)
对输入串做局部修正:插入、删除、替换一个符号。
例如:遇到 A = B + ; C,检测到缺少操作数,可插入一个假符号继续分析。
产生式扩展(Error Productions)
扩充文法,加入常见的错误模式作为产生式。
示例:在标准文法中加入 作为错误产生式(处理一元负号写为二元的情况)。
- 优点:可捕获特定类型的错误并给出精确提示
- 缺点:扩大的文法可能引入新的冲突或二义性
全局纠正(Global Correction)
理论上,找到与错误输入最接近的合法句子(最小编辑距离)。
- 优点:理论上最优
- 缺点:实现过于复杂,实际中很少使用
错误处理选择
| 策略 | 实现复杂度 | 错误定位精度 | 实际应用 |
|---|---|---|---|
| 紧急恢复 | 低 | 低 | 广泛使用 |
| 短语级恢复 | 中 | 中 | 常见 |
| 产生式扩展 | 高 | 高 | 特定场景 |
| 全局纠正 | 极高 | 最高 | 极少使用 |
LR 分析器的错误恢复
LR 分析器检测到错误时(表中为空/出错),通过修改栈和输入实现恢复。
紧急恢复(LR 版本)
- 弹出状态栈中的状态,直到栈顶状态有 对应某非终结符
- 丢弃输入符号,直到遇到 中的符号
- 将 压入栈,继续分析
错误恢复例程(e1-e4)
常见的 LR 错误恢复例程:
| 例程 | 检测场景 | 恢复动作 |
|---|---|---|
| e1 | 缺运算对象(如 A = + B) | 插入假标识符 |
| e2 | 括号不配对 | 插入/删除括号 |
| e3 | 缺运算符(如 A B) | 插入假运算符 |
| e4 | 缺 ) | 插入假右括号 |