编译原理阶段
编译器分为9个阶段来将我们所编写的高级代码编译为计算机可执行的机器码
- 源程序
- 词法分析器
- 语法分析器
- 语义分析器
- 中间代码生成器
- 独立于机器的代码优化器
- 代码生成器
- 依赖于机器的代码优化器
- 目标机器代码
每一个阶段都对应着他相关的功能,最终将高级代码编译为计算机可识别的机器码
编译器与解释器有着一些量的区别,而引起质的变化:
解释器是不会生成目标代码,而是直接执行源程序所指定的运算、也就是说,它会直接执行三地址中间代码(后续会说的)
在92年之前的BASIC年代的解释器就是将高级语言程序翻译为一种中间语言程序、然后对中间语言程序进行解释执行,那时编译和解释在一个程序中、该程序被称为解释器
而在 92 年之后的Java年代中,编译器与解释的功能被分在两个程序中:
前一个被称为编译器,他会把源程序翻译为一种叫做字节码的中间语言程序
后一个被称为解释器,他对字节码程序进行解释执行
词法分析器
首先我们看一下这样一行代码
position = initial + rate * 60
这是一段将后面的表达式的值给到左边变量的赋值操作,这些变量都会在符号表中有对应的标记,比如 position 对应的是 1, initial 对应的是 2,rate 对应的是3
那么词法分析器就会将其转译为记号流:
<id,1> <=> <id,2> <+> <id,3> <*> <60>
现在我们获得到了一个记号流,我们将继续会对记号流进行下一步的操作
语法分析器
接着我们使用语法分析器对刚才得到的记号流转译为语法树:
现在我们获得到了一个语法树,我们将继续会对语法树进行下一步的操作
语义分析器
语义分析器将会对刚才得到的语法树进行一个类型检验转换
中间代码生成器
接下来我们会使用中间代码生成器将语法树进行一个改造,改造为三地址中间代码
三地址中间代码指的是最多三组表达式的代码块
t1 = inttofloat(60)
t2 = id3 * t1
t3 = id2 + t2
id1 = t3
代码优化器
接下来我们将会使用代码优化器对三地址中间代码进行代码优化
因为上面的 t3 没有进行运算,在最后一步直接赋值给 id1 ,所以我们省略此步即达到了优化的目的
t1 = id3 * 60
id1 = id2 + t1
代码生成器
我们接着将优化完成的三地址中间代码使用代码生成器转换为汇编代码
😪写汇编语言。。。我感觉我像在写SQL语句🥲
MOVF id3,R2 //将id3的值转移到R2计算器中
MULF #60.0,R2 // 将计算器与60进行相乘
MOVF id2,R1 // 将id2的值转移到R1计算器中
ADDF R2,R1 // 将计算器R1与R2进行相加
MOVF R1,id1 // 将 R1 的值移动到了id1中