第1章 编译程序概论 1
1.1 什么是编译程序 1
1.2 编译过程和编译程序的结构 3
1.2.1 词法分析 3
1.2.2 语法分析 4
1.2.3 语义分析 5
1.2.4 中间代码生成 6
1.2.5 代码优化 6
1.2.6 目标代码生成 6
1.2.7 符号表管理和出错处理 7
1.2.8 编译阶段的组合和编译结构 9
1.3 实例:PL/0编译程序 10
1.3.1 PL/0语言简介 10
1.3.2 PL/0语言处理系统 11
习题 13
第2章 语言和文法 14
2.1 语言的基本概念 14
2.1.1 字母表和字 14
2.1.2 关于字的运算和字母表上的运算 14
2.1.3 语言 15
2.1.4 关于语言的运算 15
2.2 上下文无关文法 16
2.2.1 上下文无关文法的基本概念 16
2.2.2 归约与推导 17
2.2.3 上下文无关语言 18
2.2.4 句型、句子与分析树 20
2.2.5 归约、推导与分析树之间关系 20
2.2.6 文法的二义性 21
2.3 PL/0语言的语法 25
2.3.1 PL/0语言语法的上下文无关文法描述 25
2.3.2 PL/0语言语法的EBNF描述 26
习题 28
第3章 词法分析程序及其自动构造 31
3.1 词法分析概述 31
3.1.1 词法分析的任务 31
3.1.2 词法分析在编译程序中的组织 32
3.1.3 词法分析程序中如何识别单词 33
3.2 实例:PL/0编译程序中词法分析程序的设计和实现 33
3.3 词法分析程序自动构造原理 37
3.3.1 正规表达式与正规语言 37
3.3.2 有限自动机 40
3.3.3 词法分析程序构造的自动化 52
3.4 LEX:一个词法分析程序的生成工具 52
3.4.1 LEX描述文件中使用的正规表达式 53
3.4.2 LEX描述文件的格式 54
3.4.3 LEX的使用 56
3.4.4 与YACC的接口约定 56
3.4.5 用LEX构造PL/0词法分析程序 57
习题 57
第4章 自顶向下语法分析 60
4.1 自顶向下分析思想 60
4.2 LL(1)分析方法 63
4.2.1 First集合和Follow集合 63
4.2.2 LL(1)文法 66
4.2.3 LL(1)分析的实现 66
4.2.4 一些有用的文法变换 72
4.3 实例:PL/0编译程序中语法分析程序的设计和实现 76
4.3.1 PL/0语法分析程序的自顶向下预测分析思想 76
4.3.2 PL/0递归下降语法分析程序的设计 78
4.3.3 PL/0编译程序中的错误处理 80
习题 82
第5章 自底向上语法分析 85
5.1 自底向上分析思想 85
5.1.1 短语和直接短语 86
5.1.2 句柄 87
5.1.3 移进-归约分析 89
5.2 LR分析方法 92
5.2.1 LR分析基础 92
5.2.2 LR(0)分析 95
5.2.3 SLR(1)分析 100
5.2.4 LR(1)分析 102
5.2.5 LALR(1)分析 107
5.2.6 某些非LR文法的强制LR分析 109
5.3 LR分析中的错误处理 111
5.4 几类分析文法之间的关系 113
习题 113
第6章 语法制导的语义分析和中间代码生成 118
6.1 语法制导的语义处理基础 118
6.1.1 属性文法以及基于属性文法的语义处理 118
6.1.2 翻译模式以及基于翻译模式的语义处理 127
6.2 语法制导的语义分析 133
6.2.1 语义分析的主要工作 134
6.2.2 类型检查 134
6.3 语法制导的中间代码生成 137
6.3.1 常见的中间表示形式 137
6.3.2 生成抽象语法树 138
6.3.3 生成三地址码 139
6.4 YACC:一个语法分析/语义处理程序的生成工具 147
6.4.1 YACC描述文件 147
6.4.2 使用YACC的一个简单例子 151
6.4.3 用LEX和YACC实现PL/0编译程序 152
习题 152
第7章 符号表 158
7.1 名字的属性和说明 158
7.2 符号表的组织 159
7.2.1 符号表的总体组织 159
7.2.2 关键字域的组织 160
7.2.3 符号表的基本实现技术 160
7.3 分程序结构的符号表 161
7.4 PL/0编译程序中符号表的设计与实现 164
7.4.1 PL/0符号表的设计 164
7.4.2 作用域与可见性 166
7.4.3 符号表的操作 168
习题 169
第8章 目标程序运行时的存储组织 171
8.1 数据空间的使用和管理方法 171
8.1.1 静态存储分配 172
8.1.2 动态存储分配 172
8.2 栈式存储分配的实现 173
8.2.1 动态地分配和释放一个过程的数据空间 174
8.2.2 对非局部变量的引用 175
8.2.3 分程序共享过程的活动记录 179
8.3 参数传递 180
8.3.1 形实参对应的方法 181
8.3.2 传值的实现 181
8.3.3 传地址的实现 182
8.4 PL/0程序运行时的存储组织 183
8.4.1 PL/0程序运行栈中的过程活动记录 183
8.4.2 实现过程调用和返回的类P-code指令 185
习题 186
第9章 代码优化和代码生成 189
9.1 基本块和流图 191
9.1.1 基本块 191
9.1.2 控制流图 192
9.1.3 循环的判定 193
9.1.4 跟踪基本块内部变量使用信息 194
9.1.5 跟踪基本块之间变量使用信息 196
9.2 中间代码优化 200
9.2.1 局部优化 200
9.2.2 循环优化 202
9.2.3 全局优化 205
9.3 目标代码的生成和优化 207
9.3.1 设计代码生成程序的基本考虑 207
9.3.2 一个简单的代码生成算法 209
9.3.3 目标代码优化 211
9.4 PL/0编译程序中的目标代码生成 212
习题 214
第10章 编译器和相关工具实例——GCC/Binutils 217
10.1 开源编译器GCC 217
10.1.1 GCC介绍 218
10.1.2 GCC总体结构 219
10.1.3 GCC编译流程 220
10.1.4 GCC代码组织 221
10.2 开源工具Binutils 222
10.2.1 目标文件 222
10.2.2 汇编器和链接器 223
10.2.3 其他工具 224
10.3 编译器和工具使用实例 224
10.3.1 编译特定版本的编译器 224
10.3.2 查看目标文件 227
10.3.3 程序代码优化 229
习题 232
附录A PL/0编译程序文本 233
附录A-1 PL/0编译程序文本(Pascal) 233
附录A-2 PL/0编译程序文本(C) 250
附录B 用于生成某个PL/0编译程序的LEX描述文件和YACC描述文件 279
附录B-1 LEX描述文件pl0.l 279
附录B-2 YACC描述文件pl0.y 280
附录B-3 头文件define.h 292
参考文献 293