本书系统全面地介绍经典、广泛应用的高级程序设计语言编译程序的构造原理、实现技术、方法和工具。本书包含了现代编译程序设计的基础理论和技术,并在语义分析、代码优化,面向对象语言的编译及高级优化技术等方面反映了20世纪90年代后的一些重要研究成果,特别兼顾近年来编译原理及技术的发展和发生的一些重要变化,专辟“编译技术高级专题”予以介绍。本书的组织注重提炼精华、循序渐进、深入浅出,每章开头提炼了该章涉及的主要内容、要点和关键概念,全书精编、精选了近300道各种类型的习题和思考题,还提供了编译程序实现的具体实例,能够辅助读者更好地学习和掌握编译原理。
本书可以作为计算机学科类专业及相关专业本科和研究生编译原理的教科书,也可以作为软件技术人员的参考用书。
编译原理作为计算机学科的一门重要专业基础课,列入国际ACM教程和IEEE计算机学科的正式主干课程,并提高该课程内容的课时比重,这充分体现了其在计算机科学中的地位和作用。
编译程序是计算机系统软件的主要组成部分,是计算机科学中发展迅速、系统、成熟的一个分支,其基本原理和技术也适用于一般软件的设计和实现,而且在语言处理、软件工程、软件自动化、逆向软件工程、再造软件工程等诸多领域有着广泛的应用。
本书旨在介绍编译程序设计的基本原理、实现技术、方法和工具。本书的前驱版本系陈英教授主编,获得北京市2008年高校精品教材。在此基础上,规划、整合为“编译原理”课程的系列丛书,包括作为教材的本书及后续即将推出的《编译原理学习指导与习题解析》和《编译原理课程设计》。全书分为11章,第1章作为全书的开场白,介绍了编译程序有关的概念,编译过程、编译程序的结构与组织等要点。第2章作为后续各章的基础知识,也是学习编译原理应起码具备的理论基础,对形式语言与自动机理论作了基本的介绍。第3章以正则文法、正规式、有限自动机为工具,讨论了词法分析器的设计与实现。第4章和第5章对常规的语法分析方法,即自上而下和自下而上分析中的几种经典方法展开了较深入的讨论,并结合流行、实用、高效的LR分析方法,介绍了二义文法的分析应用,编译程序的出错处理。第3章和第5章还讨论了流行的词法分析和语法分析自动生成工具Lex及Flex,YACC及Bison的构造原理与应用,并以ANSI_C语言为例,给出了其Lex和YACC的描述。第6章涉及语义分析方法和属性翻译文法,中间语言,符号表及类型检查技术,流行的高级程序设计语言中典型语句的翻译。第7章介绍编译程序运行时环境的有关概念和存储组织与分配技术。第8章介绍中间代码级上的优化,展开讨论了优化的基本概念,优化涉及的控制流分析和数据流分析技术,以及中间代码上的局部优化和循环优化技术及实现。第9章简单介绍了代码生成的有关知识点及目标代码级可实施的窥孔优化技术。第10章以PL/0语言为源语言,提供了一个短小、精悍的编译程序实现的范例,以弥补编译程序从原理到工程实现的鸿沟。第11章反映了20世纪90年代后本领域的一些重要研究成果,如面向对象语言的翻译、GLR分析。另外,高性能体系结构的发展与技术对编译技术提出新的挑战。本章针对主流并行处理器体系结构及与之相关的编译优化技术进行简要介绍,如并行优化技术、存储层次及其优化技术等。
纵观本书的组织,注重循序渐进,深入浅出,每章开头提炼了该章涉及的主要内容提要和关键概念,全书精编、精选了近300道各种类型的习题和思考题,还提供了编译程序实现的具体实例,辅助读者更好地学习和掌握编译原理。
本书是作者多年教学实践和科研工作的汇集、提炼和整理,特别是北京理工大学“编译原理”课程组老师们奉献了他们教学实践的汇集和积累。本书完成的责任编著和辅助编著的直接承担者是: 陈英第1, 3, 4, 5, 6, 9和11章;王贵珍第2, 10, 4和11章;李侃第6, 7, 11和2章;计卫星第8, 9, 11, 1和5章;陈朔鹰第3, 7和8章。本书参考了国内外一些专著、论文和资料,参考、借鉴了一些专家学者的研究成果,对所有这些前辈和同行的引导和帮助表示衷心的感谢。另外,本书过去多个不同版本通过数届学生和读者的使用,亦得到了他们许多宝贵的反馈意见和建议。 本书完成过程中,得到了清华大学出版社的鼎力协助,尤其是编审谢琛高效的工作和非常专业的指导,作者在此一并深为致谢。
鉴于作者水平有限,本书稿虽经审慎校阅,仍难免存在疏误,敬请读者不吝赐教。
编 者2009年1月于北京
第1章 编译引论 /1
1.1 程序设计语言与编译程序 /1
1.1.1 编译程序鸟瞰 /1
1.1.2 源程序的执行 /2
1.2 编译程序的表示与分类 /2
1.2.1 T型图 /2
1.2.2 编译程序的分类 /3
1.3 编译程序的结构与编译过程 /4
1.3.1 编译程序的结构与编译过程 /4
1.3.2 编译程序结构的公共功能与编译程序的
组织 /9
1.4 语言开发环境中的伙伴程序 /10
1.5 编译程序结构的实例模型 /11
1.5.1 一遍编译程序结构 /11
1.5.2 PRIME机上AHPL语言的两遍编译
程序 /11
1.5.3 PDP-11计算机上C语言的三遍编译
程序 /11
1.5.4 Tiger编译程序结构 /12
1.5.5 GCC编译程序结构框架 /13
1.6 编译程序的构造与实现 /14
1.6.1 如何构造一个编译程序 /14
1.6.2 编译程序的生成方式 /15
1.6.3 编译程序的构造工具 /15
习题1 /16第2章 形式语言与自动机理论基础 /18
2.1 文法和语言 /18
2.1.1 语言的语法和语义 /18
2.1.2 文法和语言的定义 /19
2.1.3 文法的表示方法 /25
2.1.4 语法分析树与二义性 /26
2.1.5 文法和语言的类型 /29
2.2 有限自动机 /30
2.2.1 确定的有限自动机 /31
2.2.2 非确定的有限自动机 /33
2.2.3 确定的有限自动机与非确定的有限自动机的等价 /35
2.2.4 确定的有限自动机的化简 /38
2.3 正规式与有限自动机 /42
2.3.1 有限自动机与正则文法 /42
2.3.2 正规式与正规集 /43
2.3.3 正规式与有限自动机 /44
习题2 /52第3章 词法分析 /58
3.1 词法分析与词法分析程序 /58
3.2 词法分析程序设计与实现 /59
3.2.1 词法分析程序的输入与输出 /59
3.2.2 源程序的输入与预处理 /60
3.2.3 单词的识别 /61
3.2.4 词法分析程序与语法分析程序
的接口 /62
3.2.5 词法分析器的设计与实现 /62
3.3 词法分析程序的自动生成 /68
3.3.1 词法分析自动实现思想与自动生成
器--Lex/Flex /68
3.3.2 Lex运行与应用过程 /68
3.3.3 Lex语言 /69
3.3.4 词法分析器产生器的实现 /73
3.3.5 Lex应用 /74
习题3 /78第4章 语法分析--自上而下分析 /79
4.1 语法分析综述 /79
4.1.1 语法分析程序的功能 /79
4.1.2 语法分析方法 /80
4.2 不确定的自上而下语法分析 /81
4.2.1 一般自上而下分析 /81
4.2.2 不确定性的原因与解决方法 /82
4.2.3 消除回溯 /85
4.3 递归下降分析法与递归下降分析器 /86
4.3.1 递归下降分析器的实现 /86
4.3.2 递归下降分析器设计工具--状态转
换图 /87
4.4 LL(1)分析法与LL(1)分析器 /89
4.4.1 LL(1)分析器的逻辑结构与动态
实现 /89
4.4.2 LL(1)分析表的构造 /91
4.4.3 关于LL(1)文法 /94
习题4 /95第5章 语法分析--自下而上分析 /99
5.1 基于“移进-归约”的自下而上分析 /99
5.1.1 “移进-归约”分析 /99
5.1.2 规范归约与句柄 /101
5.2 算符优先分析法与算符优先分析器 /103
5.2.1 直观的算符优先分析法 /103
5.2.2 算符优先文法和算符优先分析表的
构造 /106
5.2.3 算符优先分析法实现的理论探讨 /109
5.2.4 优先函数表的构造 /112
5.3 LR分析 /114
5.3.1 LR分析法与LR文法 /114
5.3.2 LR(0)分析及LR(0)分析表的
构造 /119
5.3.3 SLR(1)分析及SLR(1)分析表的
构造 /128
5.3.4 LR(1)分析及LR(1)分析表的
构造 /130
5.3.5 LALR(1)分析及LALR(1)分析表的
构造 /135
5.4 LR分析对二义文法的应用 /138
5.5 LR分析的错误处理与恢复 /140
5.6 语法分析程序自动生成器 /142
5.6.1 YACC综述与应用 /143
5.6.2 YACC语言 /144
5.6.3 YACC处理二义文法 /145
5.6.4 YACC的错误恢复 /147
5.6.5 YACC应用 /148
习题5 /158第6章 语义分析与中间代码生成 /163
6.1 语法制导翻译 /163
6.1.1 语法制导定义 /164
6.1.2 综合属性 /165
6.1.3 继承属性 /166
6.1.4 依赖图 /166
6.1.5 语法树的构造 /168
6.1.6 S_属性定义与自下而上计算 /168
6.1.7 L_属性定义与翻译模式 /169
6.2 符号表 /172
6.2.1 符号表的组织 /173
6.2.2 分程序结构的符号表 /174
6.3 类型检查 /177
6.3.1 类型体制 /177
6.3.2 一个简单的类型检查程序 /179
6.4 中间语言 /183
6.4.1 逆波兰表示法 /183
6.4.2 N-元式表示法 /184
6.4.3 图表示法 /186
6.5 中间代码生成 /186
6.5.1 说明类语句的翻译 /186
6.5.2 赋值语句与表达式的翻译 /189
6.5.3 控制流语句的翻译 /190
6.5.4 数组说明和数组元素引用的翻译 /196
6.5.5 过程、函数说明和调用的翻译 /198
习题6 /199第7章 运行环境 /203
7.1 程序运行时的存储组织与分配 /203
7.1.1 关于存储组织 /203
7.1.2 过程的活动记录 /204
7.1.3 存储分配策略 /205
7.2 静态运行时环境与存储分配 /206
7.3 基于栈的运行时环境的动态存储分配 /208
7.3.1 简单的栈式存储分配的实现 /208
7.3.2 嵌套过程语言的栈式存储分配的
实现 /210
7.4 基于堆的运行时环境的动态存储分配 /212
7.4.1 基于堆的运行时环境的动态存储分配的
实现 /212
7.4.2 关于悬空引用 /214
习题7 /216第8章 代码优化 /221
8.1 代码优化概述 /221
8.1.1 代码优化的概念 /221
8.1.2 优化技术分类 /222
8.1.3 优化编译程序的组织 /227
8.2 局部优化 /227
8.2.1 基本块的定义与划分 /227
8.2.2 程序的控制流图 /228
8.2.3 基本块的DAG表示及应用 /229
8.3 控制流分析与循环查找 /236
8.4 数据流分析 /239
8.4.1 程序中的点与通路 /239
8.4.2 到达-定值数据流方程及其方程
求解 /239
8.4.3 引用-定值链(ud链) /242
8.4.4 活跃变量与数据流方程 /242
8.4.5 定值-引用链(du链)与du链数据流
方程 /243
8.4.6 可用表达式数据流方程 /244
8.5 循环优化 /244
8.5.1 代码外提 /245
8.5.2 强度削弱 /247
8.5.3 变换循环控制变量(删除归纳
变量) /247
习题8 /249第9章 代码生成 /253
9.1 代码生成器设计中的要点 /253
9.1.1 代码生成器的输入与输出 /253
9.1.2 指令的选择 /254
9.1.3 寄存器分配 /255
9.1.4 存储管理 /256
9.2 简单代码生成器的构造 /256
9.3 目标代码的窥孔优化 /258
9.3.1 冗余指令序列 /259
9.3.2 控制流优化 /260
9.3.3 代数化简 /261
9.3.4 窥孔优化实例 /261
习题9 /264第10章 编译程序实现范例 /265
10.1 PL/0语言描述 /265
10.2 PL/0编译程序的结构 /266
10.3 PL/0编译程序的词法分析 /268
10.4 PL/0编译程序的语法分析 /270
10.5 PL/0编译程序的目标代码结构和代码
生成 /274
10.6 PL/0编译程序的语法错误处理 /276
10.7 PL/0编译程序的目标代码解释执行时的
存储分配 /279
10.8 PL/0编译程序文本 /281
习题10 /301第11章 编译技术高级专题 /303
11.1 面向对象语言的翻译 /303
11.1.1 面向对象程序设计语言的概念 /303
11.1.2 面向对象语言的翻译 /305
11.1.3 面向对象语言中的动态存储 /308
11.2 高性能计算机体系结构及发展趋势 /309
11.2.1 支持指令级并行的处理器简介 /310
11.2.2 支持线程级并行的处理器简介 /313
11.2.3 高性能体系结构对编译器的
挑战 /316
11.3 关于并行优化技术 /316
11.3.1 指令相关与指令并行化 /316
11.3.2 循环展开与优化 /319
11.3.3 VLIW指令调度 /322
11.4 存储层次及其优化技术 /323
11.4.1 存储层次与Cache组织结构 /323
11.4.2 Cache预取 /324
11.4.3 循环交换 /325
11.4.4 循环分块 /327
11.5 关于GLR分析法 /329
习题11 /335
参考文献 /337