Skip to content
难度重点
建议时长45分钟

17.2.2 编译过程概述

编译过程是本章最核心的考点。记忆顺序不难,难的是把“这个错误归哪一阶段”判断清楚。

mermaid
flowchart LR
  A["字符流/源程序"] --> B["词法分析"]
  B --> C["Token 序列"]
  C --> D["语法分析"]
  D --> E["语法树/分析树"]
  E --> F["语义分析"]
  F --> G["中间代码"]
  G --> H["代码优化"]
  H --> I["目标代码"]
  S["符号表管理"] -.贯穿.-> B
  S -.贯穿.-> D
  S -.贯穿.-> F
  X["错误处理"] -.贯穿.-> B
  X -.贯穿.-> D
  X -.贯穿.-> F

词法分析:字符变单词

词法分析器从源程序字符流中识别关键字、标识符、常量、运算符、界符等,输出 Token 序列。它关心的是“单词是否合法”,常用正规式和有限自动机实现。

输入输出典型错误
字符流Token 序列非法字符、标识符拼写不合法、数字格式错误

语法分析:单词变结构

语法分析根据文法检查 Token 序列能否组成合法句子,并构造语法树或分析树。它关心的是“结构是否符合语法规则”。

输入输出典型错误
Token 序列语法树/分析树缺少分号、括号不匹配、ifendif 不匹配、表达式缺少操作数

常见方法包括自顶向下分析和自底向上分析,移进-归约属于自底向上思想。

语义分析:结构有了,含义还要合理

语义分析检查类型、作用域、参数匹配、运算对象是否合法等。语法正确不代表语义正确,例如 int a; a = "hello"; 结构上可能像赋值语句,但类型不匹配。

类型发现时机例子
静态语义错误编译期运算符与操作数类型不匹配、未声明变量、参数个数不符
动态语义错误运行期除数运行时为 0、数组下标越界、死循环

课程里提到的“无限循环、变量为零导致除零、数组越界”更接近运行期问题,不能简单归到词法或语法。

中间代码与优化

中间代码是介于源语言和目标机器代码之间的表示。它让编译器先脱离具体机器分析程序,再在后续阶段生成不同平台的目标代码。

中间表示特点
语法树保留表达式和语句结构
后缀表达式运算符在操作数之后,便于栈式处理
三地址码/四元式每条语句最多涉及三个地址,利于优化

代码优化在不改变程序语义的前提下改善时间或空间效率。优化不是“让错误程序变正确”,而是让正确程序更好地执行。

错误定位口诀

问题表现优先判断
单词本身不合法词法错误
单词都合法,但句子结构不合法语法错误
结构合法,但类型、作用域、参数等含义不合理语义错误
只有运行时具体值才暴露运行时错误/动态语义错误

小练习

题:a = b + ; 更可能属于哪类错误?

答:语法错误。标识符和运算符本身合法,但表达式结构缺少操作数。

自查

  1. 词法分析的输出为什么不是语法树?
  2. “括号不匹配”和“类型不匹配”分别属于什么层次?
  3. 为什么符号表管理要贯穿多个编译阶段?