【Compiler】-8 中间代码生成
中间代码
- 语法分析之后,编译的任务是由已识别为正确的源程序生成一组规格一致,便于计算机加工的指令形式。
一、 中间代码生成方法
语法制导翻译,属性文法制导翻译
二、中间代码
中间代码:不是机器语言便于生成机器语言,便于代码优化。
- 逆波兰式
- 树形表示
- 三元式
- 四元式(最常用)
翻译方法
语法制导翻译
- 在语法分析的基础上进行边分析边翻译。
注:
-
语法制导翻译时会根据文法产生式右部符号串的含义,进行翻译,翻译的结果是生成相应中间代码。
-
语法制导翻译的依据是语义子程序。
-
具体做法:为每个产生式配置一个语义子程序,当语法分析进行归约或推导时,调用语义子程序,完成一部分翻译任务。
语法制导翻译种类
- 自上而下语法制导翻译:对每个文法符号配以语义动作
- 自下而上语法制导翻译:我们主要讨论LR语法制导翻译。
语义子程序
语义子程序写在该产生式后面的花括号内。X→α{语义子程序1}
注:在一个产生式中同一个文法符号可能出现多次,但他们代表的是不同的语义值,要区分可以加上角标。
如:E->E^1^ +E^2^
语义值
为了描述语义动作,需要为每个文法符号赋予不同的语义值:类型、地址、代码值等。
代表了符号表入口地址,如变量名、变量类型、变量地址
语义栈
各个符号的语义值放在语义栈中
- 当产生式进行归约时,需对产生式右部符号的语义值进行综合,其结果作为左部符号的语义值保存到语义栈中。
下推栈包含3部分
- 状态栈、符号栈和语义栈
- 注:语义栈与状态栈和符号栈是同步变化的。
注:1)若把语义子程序改成产生某种中间代码的动作,就能在语法分析制导下,随着分析的进展逐步生成中间代码。
得到如下结果
举例
(1)第一步,将E->E+E归约并将语义相加
对应的表
- 如步骤7、8,由
E+E
归约为E,并且将top=9与top+2=7相加,求出16
中间代码形式
四元式形式
(操作符,操作数1,操作数2,结果)
- 变量采用符号表入口地址,因为语义分析中,需要变量的类型
三元式
(操作符,操作数1,操作数2)
后缀表示
(操作数1,操作数2,操作符)
如:abc*+,得出a+(b*c)
树形表示
赋值语句的翻译
- 仅含简单变量的表达式和赋值语句的翻译赋值语句的文法
举例
- T是临时产生的,用来保存结果
- A入栈,A是个变量,
布尔表达式翻译
布尔表达式作用
一、布尔表达式在程序设计语言中的作用
- 用作控制语句中的条件表达式;
- 用于逻辑赋值语句中布尔表达式演算。
布尔表达式组成
布尔表达式文法
逻辑演算中的翻译
语义子程序
由于布尔表达式演算与算术表达式计算非常类似,可以仿照算术表达式的翻译方法,为每个产生式写出语义子程序:
在语法栈中,和语义栈中进行计算,结果还是放到T中
举例
语法栈 | 语义栈 | 读头 | |
---|---|---|---|
x +y>zV |
x入栈 | ||
E | x | + y>zV |
+入栈,语义栈中用-表示 |
E+ | x- | y >zV |
y入栈 |
E+E | x-y | > zV |
遇到>,先进行算符运算,(+,x,y,T1) |
Ea | T1 | > zV |
>入栈 |
Ea> | T1- | z V |
z入栈 |
Ea>E | T1-z | V |
遇到V,先进行关系运算,(>,T1,z,T2) |
Eb | T2 | V |
|
控制语句中翻译
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 lthero!
评论