前置知识: 计算机基础

编译原理进阶

00:00
8 min Advanced 2026/6/14

编译原理进阶:LL/LR分析、语法制导翻译、中间代码优化与代码生成

1. 词法分析

1.1 正则表达式到 NFA

Thompson 构造法:

  • 空串 :两个状态, 转移
  • 单字符 :两个状态, 转移
  • :新起始状态, 到两个子 NFA
  • 连接 终态 起始
  • 闭包 :新起始和终态, 循环

1.2 NFA 到 DFA

子集构造法:

1.3 DFA 最小化

Hopcroft 算法:

  1. 初始划分
  2. 对每个块,按转移目标进一步分割
  3. 重复直到稳定

2. 语法分析

2.1 LL 分析(自顶向下)

LL(1) 条件

对于文法

  1. ,则

FIRST 集计算

FOLLOW 集计算

LL(1) 分析表构造

对每个产生式

  • 对每个
  • :对每个

2.2 LR 分析(自底向上)

LR 分析器结构

输入 ──→ ┌──────────┐ ──→ 动作
          │  栈      │
          │ 状态+符号 │
          └──────────┘

动作类型

  • Shift :移进,压入状态
  • Reduce :归约,弹出 个状态,压入
  • Accept:接受
  • Error:报错

2.3 SLR 分析

使用 FOLLOW 集确定归约动作:

对项目 ,仅在 时添加

SLR 的不足:FOLLOW 集可能过大,导致归约-归约冲突。

2.4 LALR 分析

合并同心项目集(核心相同的项目集)。

LALR 表大小与 SLR 相同,但分析能力更强。

大多数实用解析器生成器(Yacc、Bison)使用 LALR(1)。

2.5 LR 分析器对比

类型状态数分析能力冲突
SLR最少最弱最多
LALR中等较少
LR(1)最多最强最少

3. 语法制导翻译

3.1 语法制导定义(SDD)

为文法的每个产生式关联语义规则

3.2 综合属性与继承属性

综合属性:在分析树中,由子节点属性计算父节点属性(自底向上)。

继承属性:由父节点或兄弟节点属性计算(自顶向下)。

3.3 S 属性文法

仅使用综合属性的 SDD,可在 LR 分析中自底向上计算。

3.4 L 属性文法

每个继承属性 仅依赖于:

  1. 的继承属性
  2. 左侧兄弟的属性

L 属性文法可在 LL 或 LR 分析中单遍计算。

4. 中间代码生成

4.1 中间表示形式

三地址码

t1 = a + b
t2 = t1 * c
x = t2

静态单赋值(SSA)

每个变量只被赋值一次,使用 函数合并控制流:

if condition:
    x1 = a + b
else:
    x2 = a - b
x3 = φ(x1, x2)

四元式:(op, arg1, arg2, result)

三元式:(op, arg1, arg2),通过位置引用结果

4.2 类型检查

类型表达式

  • 基本类型:integer, real, boolean
  • 构造类型:array(n, T), pointer(T), record(fields)
  • 函数类型:

类型等价

  • 名字等价:类型名相同
  • 结构等价:类型结构相同

5. 代码优化

5.1 基本块优化

常量折叠

x = 3 + 5  →  x = 8

常量传播

x = 5
y = x + 1  →  y = 6

死代码消除

x = 5
x = 10     →  删除 x = 5

代数化简

x = y + 0  →  x = y
x = y * 1  →  x = y

5.2 循环优化

循环不变代码外提

// 优化前
for (i = 0; i < n; i++) {
    t = a * b;  // 循环不变
    c[i] = t + d[i];
}

// 优化后
t = a * b;
for (i = 0; i < n; i++) {
    c[i] = t + d[i];
}

强度削弱

// 优化前
for (i = 0; i < n; i++) {
    a[i*4] = 0;
}

// 优化后
t = 0;
for (i = 0; i < n; i++) {
    a[t] = 0;
    t = t + 4;  // 乘法 → 加法
}

归纳变量删除

当存在基本归纳变量和派生归纳变量时,可删除其中一个。

5.3 全局优化

数据流分析

分析方向信息
到达定义前向变量在哪里被定义
活跃变量后向变量未来是否使用
可用表达式前向表达式是否已计算
常量传播前向变量是否为常量

数据流方程(以活跃变量为例):

5.4 优化级别

级别优化内容
局部优化基本
全局优化过程
过程优化过程

6. 代码生成

6.1 寄存器分配

着色算法

  1. 构建干涉:同时活跃的变量之间有
  2. 颜色着色( 为可用寄存器数)
  3. 无法着色时溢出(spill)到内存

活跃区间变量定义到最后一次使用的范围

6.2 指令选择

重写:将中间代码匹配目标机器指令模式。

动态规划每个表达式选择代价最小指令序列。

6.3 指令调度

列表算法

  1. 构建数据依赖图
  2. 计算每个操作优先级关键路径
  3. 优先级到低调度到可用时钟周期

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式