← 前一天目录后一天 →

每日科普 · 2026-10-30 周五

考研 408 × 求职面试

知识点 · 编译原理 · 基础

编译各阶段的错误检测与错误恢复

编译器的错误检测贯穿各阶段,不同阶段能发现不同问题。1. 词法分析:检查非法字符、非法记号等,如出现@、数字开头的标识符;恢复常采用跳过字符、删除或插入记号,让扫描继续。2. 语法分析:检查记号序列是否符合文法,如括号不匹配、缺少分号;常用恐慌模式,跳到同步记号如分号,也可用短语层次恢复或错误产生式恢复。3. 语义分析:检查类型不匹配、变量未声明、作用域和参数个数等问题;可做类型转换、插入默认声明或标记错误后继续。4. 中间代码生成与优化、目标代码生成也会检查类型一致性、控制流和资源限制等。关键理解是:错误恢复的目标不是立刻终止,而是把错误局部化、继续编译,以便一次报告更多错误;错误处理通常由符号表、错误处理例程和各阶段协同完成。

每日一题 · 编译原理

编译各阶段的错误检测与错误恢复

下列“错误—最可能检测阶段—恢复策略”对应正确的是( ) A. 非法字符@—语法分析—恐慌模式 B. 括号不匹配—词法分析—跳过字符 C. 变量未声明—语义分析—插入声明并继续 D. 缺少分号—语义分析—类型转换

解析

选C。词法分析负责识别记号,非法字符@应在词法阶段发现;括号和缺少分号属于语法结构,应在语法分析发现并用恐慌模式等恢复;变量未声明是符号表与作用域问题,属于语义分析,可插入声明或标记后继续。D把语法错误误归语义阶段。因此C正确。

面试小贴士 · 编译原理

编译各阶段的错误检测与错误恢复

面试常问“各阶段能发现什么错误、怎么恢复”。按词法、语法、语义、代码生成顺序举例,强调局部恢复和继续发现更多错误。易错点:误认为错误只在语法阶段、把语义错误当语法错误、把恢复理解为立即停止。

代码实现 · C++

代码示例

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main() {
    vector<string> tok = {"int","x","=","@",";","y","=","x","+"};
    vector<string> declared = {"x"};
    // 词法阶段:发现非法字符并跳过
    for (auto &s : tok)
        if (s == "@") cout << "词法错误:@非法,跳过恢复" << endl;
    // 语法阶段:检查括号配对,用恐慌模式恢复
    int bal = 0;
    for (auto &s : tok) { if (s=="(") bal++; if (s==")") bal--; }
    if (bal != 0) cout << "语法错误:括号不匹配,跳到分号恢复" << endl;
    // 语义阶段:检查未声明变量,假定声明后继续
    for (auto &s : tok)
        if (s == "y" && find(declared.begin(), declared.end(), s) == declared.end())
            cout << "语义错误:y未声明,插入声明并继续" << endl;
    cout << "局部恢复后继续分析,可报告更多错误" << endl;
    return 0;
}
← 前一天目录后一天 →