编译原理通关笔记:从哈工大课堂到及格线速通

1. 编译原理速通指南:从哈工大课堂到及格线

编译原理这门课在计算机专业里一直是个"硬骨头",尤其是哈工大的编译原理课程,以内容深、实验多著称。作为一个过来人,我完全理解大家面对这门课时的焦虑——复杂的理论推导、抽象的概念体系,还有那让人头疼的八个大实验。

但别担心,这篇笔记就是来帮大家解决这个问题的。我把自己在哈工大课堂上学到的精华,加上备考时总结的实战技巧,全部浓缩在这份"及格版"笔记里。我们的目标很明确:用最短的时间掌握最核心的考点,顺利通过考试。

2. 核心概念精讲

2.1 编译过程全景图

编译的本质就是一个翻译过程,把高级语言(比如C、Java)转换成机器能懂的汇编或机器语言。这个过程可以类比人类翻译外文:

  • 词法分析:就像查字典,把句子拆成单词并标注词性
  • 语法分析:分析单词如何组成短语,画出语法树
  • 语义分析:检查句子是否通顺,收集变量和函数信息
  • 中间代码:把句子意思提炼成更抽象的表示
  • 代码优化:对翻译进行润色,让表达更高效
  • 目标代码:最终翻译成品

以C语言为例,完整的编译系统包含四个关键组件:

  1. 预处理器:处理#include和#define这些指令
  2. 编译器:核心部分,把预处理后的代码转成汇编
  3. 汇编器:把汇编转成机器码(还是逻辑地址)
  4. 链接器:把多个目标文件合并成可执行程序

2.2 文法与语言

文法就像是编程语言的"语法规则说明书"。它用数学方式定义了:

  • 终结符:最基本的符号(比如变量名、运算符)
  • 非终结符:语法成分(比如表达式、语句)
  • 产生式:符号之间的转换规则
  • 开始符号:最大的语法单位

文法的分类从0型到3型,限制越来越多。编程语言主要用2型文法(上下文无关文法),而词法分析多用3型文法(正则文法)。

举个实际例子:定义标识符的文法只需要4条规则:

  1. S → L | LT
  2. T → L | D | LT | DT
  3. L → a|b|...|z
  4. D → 0|1|...|9

这简单的几条规则就能描述所有可能的标识符,展现了文法"以有限定义无限"的强大能力。

3. 词法分析实战

3.1 正则表达式到DFA

词法分析的核心是把正则表达式转换成确定的有穷自动机(DFA)。这个转换分四步走:

  1. RE→NFA:按照优先级拆解正则式

    • 先处理括号内的内容
    • 然后是闭包(*)
    • 接着是连接(相邻)
    • 最后是或运算(|)
  2. NFA→DFA:用子集法消除不确定性

    • 计算ϵ-closure消除空转移
    • 对每个状态集计算Ia得到新状态
    • 直到没有新状态产生
  3. DFA最小化:用划分法合并等价状态

    • 先把状态分成终态和非终态
    • 检查每个子集是否可再分
    • 直到所有子集都不可分为止
  4. DFA实现:用二维表或switch-case实现

3.2 词法错误处理

当DFA卡住时,处理流程:

  1. 倒着检查已读入的字符
  2. 找到最近能匹配终态的子串
  3. 把这个子串作为一个token
  4. 从下一个字符重新开始分析
  5. 如果完全无法匹配,进入恐慌模式:
    • 持续丢弃字符直到能继续分析

4. 语法分析精要

4.1 自顶向下分析

LL(1)文法是最常用的自顶向下分析方法,关键是要计算三个集合:

FIRST集计算(某非终结符能推出的首终结符):

  1. 如果X是终结符,FIRST(X)={X}
  2. 对于产生式X→Y1Y2...Yn:
    • 把FIRST(Y1)加入FIRST(X)
    • 如果Y1能推出ϵ,继续加入FIRST(Y2)
    • 以此类推
    • 如果所有Yi都能推出ϵ,加入ϵ

FOLLOW集计算(某非终结符后可能出现的终结符):

  1. 把$加入开始符号的FOLLOW
  2. 对于产生式A→αBβ:
    • 把FIRST(β)-{ϵ}加入FOLLOW(B)
    • 如果β能推出ϵ,把FOLLOW(A)加入FOLLOW(B)

SELECT集计算(决定使用哪个产生式):

  • 对于A→α:
    • 如果α不能推出ϵ:SELECT=FIRST(α)
    • 否则:SELECT=(FIRST(α)-{ϵ})∪FOLLOW(A)

4.2 自底向上分析

LR分析是更强大的自底向上方法,主要步骤:

  1. 构造LR(0)自动机

    • 从增广文法S'→S开始
    • 计算项目集闭包
    • 根据转移符号生成新状态
    • 直到没有新状态产生
  2. 构造分析表

    • 移入项:对应ACTION表的s
    • 规约项:对应ACTION表的r
    • 非终结符转移:对应GOTO表
  3. 冲突处理

    • SLR:用FOLLOW集解决冲突
    • LR(1):加入展望符更精确判断
    • LALR:合并LR(1)的同心状态

实际考试中,SLR就够用了。重点掌握如何用FOLLOW集解决移进-规约冲突:只有当下一个输入符号在规约产生式左部的FOLLOW集中时,才选择规约。

5. 语法制导翻译

5.1 属性文法

SDD(语法制导定义)分两类属性:

  • 综合属性:自底向上计算,子节点决定父节点
  • 继承属性:自顶向下传递,依赖父节点或兄弟

S-SDD只有综合属性,计算简单:

  1. 建立依赖图
  2. 按拓扑序计算属性
  3. 通常在规约时完成计算

5.2 翻译方案实现

对于LR文法,S-SDD的实现:

  1. 把语义动作放在产生式末尾
  2. 在分析栈中开辟空间存储属性
  3. 规约时执行对应的语义动作

L-SDD适合LL文法,实现方法:

  1. 继承属性动作放在对应符号前
  2. 综合属性动作放在产生式末尾
  3. 递归下降分析时按顺序执行动作

考试中最常考的是中间代码生成,特别是四元式。记住几个规律:

  • 赋值操作:结果在第四分量
  • 二元运算:两个操作数在2、3分量
  • 数组访问:下标作为目标数
  • 函数调用:参数在2、3分量

6. 备考策略与高频考点

根据哈工大近年考题,这些内容出现频率最高:

  1. 词法分析(25%分值):

    • 正则式到DFA的转换
    • DFA最小化
    • 词法错误恢复策略
  2. 语法分析(35%分值):

    • FIRST/FOLLOW/SELECT计算
    • LL(1)分析表构造
    • SLR冲突解决
    • LR(0)项目集计算
  3. 语法制导翻译(20%分值):

    • 属性计算顺序
    • S-SDD实现
    • 四元式生成
  4. 综合应用题(20%分值):

    • 给一个小语言定义词法和语法
    • 设计属性文法
    • 生成中间代码

备考建议:

  • 先掌握算法步骤,再理解原理
  • 多画状态转换图和语法树
  • 重点练习FIRST/FOLLOW计算
  • 熟悉常见的错误恢复策略
  • 考前做3-5套往年真题

我在复习时发现,很多同学卡在LR分析表的构造上。其实只要记住这个口诀:"移进看ACTION,跳转看GOTO,规约看FOLLOW",就能解决大部分问题。考试时如果时间紧张,至少要写出LR(0)的自动机,SLR的分析表部分空着也没关系,步骤分能拿大半。

最后提醒,哈工大的实验虽然多,但考试还是以理论为主。把这份笔记里的核心概念和解题方法吃透,及格绝对没问题。我当时考前三天开始看这份笔记,最后拿了78分,相信你们会考得更好!