编译原理第一章学习笔记
第1章 编译程序的基本概念
1.1什么是编译程序
java中反编译命令:javap
汇编语言本质上是一种助记符
编译程序和解释程序两大不同:
- 编译程序有目标程序而解释程序没有
- 比如在C语言中,.exe就是目标程序
- 前者效率高而后者交互性好
1.2 编译程序的逻辑结构
编译程序分为五个阶段
-
词法分析
- 结果是一个token序列
-
语义分析
- 结果是一个语义树
-
语法分析
- 结果是一个语法树/中间代码
- 中间代码形式与源语言和目标语言没有关系
-
——————————————————以此为界,上面是前端,下面是后端
-
优化处理
-
目标代码生成
在编译过程中,编译程序不断地和符号表管理程序和错误处理程序打交道
1.3编译程序的实现机制
遍:编译程序对源程序或等价程序扫描的遍数
在整个编译过程中,看似扫描了五遍,其实只有两遍,分别是对前端和后端进行的扫描
即第一遍:词法分析、语法分析、语义分析。
第二遍:代码优化和中间代码生成
每遍中的各阶段的工作是穿插进行的,例如下图:
其中,语法分析器处于核心地位,每当语法分析器需要一个完整的语法单位时,便向词法分析器请求一个Token。当接收到所需要的token之后,便调用语义分析器生成中间代码。
1.4 编译程序的生成方法
涉及三个语言:源语言、目标语言 和 编译程序的实现语言
编译程序的生成方法:
- 用:利用已有的编译器
- 写:自己动手写一个
- 半用半写:重写现有编译器的后端
自动生成编译程序:
- 词法分析程序生成器LEX
- 语法分析程序生成器YACC
- 编译程序生成器
输入:词法规则、语法规则和语义解释
1.5 编译过程实例分析
对如下C语言程序进行编译:
int a,b;
b = a + 2*5;
1.词法分析:识别单词并分类
词法分析的结果是以token的形式传给语法分析
2.语法分析:组词成句并进行语法错误检查
生成结果是一棵语法树
分支语句由变量和表达式组成:
- 变量
- 赋值语句(expression)
- 赋值语句可以分成项(item)/项之间的加减
- 项可以分成因式(factor)/因式的乘除
- 因式则可以是具体的常数/变量
3.语义分析:分析各种语法成分
语义分析需要构建两个东西——标识符的语义辞典(符号表)&语句的语义树(中间语言)
符号表分为:
- 名字
- 类型,比如整型int
- 种类,比如变量,常量,函数的名字等等,这里是值value
- 地址,是一个指针
接下来是语义树,和语法树很类似,但是是完全不同的,前者是描述语义信息,而后者描述的确实构成。
当然了,还可以采用四元式的形式:
- 第一位是运算的符号
- 第二位是参与运算的第一个元素
- 第三位是参与运算的第二个元素
- 如果是单元运算,这一位可以用下划线代替
- 第四位是存放运算结果的位置
4.优化:提高目标程序质量
为了提高运算速度,这里可以进行的优化是将2*5直接运算出来,不需要特意为它生成一条中间代码。
下图是对b=a+2*5优化之后的结果:
5.目标代码生成
这里采用汇编指令作为目标代码,对步骤四中的中间代码对应生成三条汇编指令:
LD R,10 ;将10加载到寄存器中
ADD R,a ;将a与寄存器相加
ST R,b ;将寄存器中的值存储(store)到b中