中间代码:
中间代码是源程序的一种内部表示
复杂性介于源程序和目标机语言之间
中间代码的作用:
1、使编译程序逻辑结构更加简单明确
2、利于与目标机无关的优化
3、利于不同目标机上实现一种语言
中间代码形式:
1、逆波兰式(或称为后缀式)
2、图表示法(DAG和抽象树)
3、三地址表示(四元式、三元式、间接三元式)
1、举例逆波兰式:
a+b*(c+d/e)
(a+(b*(c+(d/e)))) 按计算顺序加上括号
(a(b(c(de)/)+)*)+ 把运算符放到括号外面
abcde/+*+ 去掉括号
2、图表示法
抽象语法树(abstract syntax code,AST)是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构,这所以说是抽象的,是因为抽象语法树并不会表示出真实语法出现的每一个细节,比如说,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现。抽象语法树并不依赖于源语言的语法,也就是说语法分析阶段所采用的上下文无文文法,因为在写文法时,经常会对文法进行等价的转换(消除左递归,回溯,二义性等),这样会给文法分析引入一些多余的成分,对后续阶段造成不利影响,甚至会使合个阶段变得混乱。因些,很多编译器经常要独立地构造语法分析树,为前端,后端建立一个清晰的接口。
3、三地址表示
三元式是把表达式及语句表示成一组三元式,每个三元式由运算符op,运算对象arg1,运算对象2arg2组成,形如(op,arg1,arg2)
举例: a:=b*c+b*d
(1) (* b,c)
(2) (* b,d)
(3) (+ (1),(2))
(4) (:= (3),a)
说明:运算符合第一个运算对象中间没有逗号,运算对象之间有逗号,:=表示赋值,就是把后面的赋值给前面的,(1)(2)这种叫序列号,出题的时候如果说当前序列号是100,那你的答案应该从100开始,不是1,下面四元式也是一样
三元式画成树如图:
(图为网络搜索)
从下往上画,最下面是最开始运算的运算对象,上一层是运算符,再上一层是运算符,一直到算完
四元式是较为普遍的中间代码形式,和三元式比多了一个result,形如(op,arg1,arg2,result),op和arg1之间有逗号,如果有arg是缺省的话用-占位
举例: a:=b*c+b*d
(1) (*,b,c,t1)
(2) (*,b,d,t2)
(3) (+,t1,t2,t3)
(4)(:=,t3,-,a)
解释:t1是bc的积的,t2是bd的积,t3是t1,t2的和,a是t3赋值给a,那个-就是占位的,因为赋值语句只有一个arg对象
四元式可以写成简单赋值语句,如下:
t1:=b*c
t2:=b*d
t3:=t1+t2
a:=t3