编译原理(十四)——中间代码生成(2)

一、表达式的中间代码生成

基于LL(1)方法

原始不带有语义动作的LL(1)文法:
在这里插入图片描述
简单表达式带有语义动作的LL(1)文法:在这里插入图片描述
GenCode安排在一个运算符的右分量后面,因为这个时候涉及到这个运算符的所有操作数都已经进入语义栈Gem中,可以进行该运算符的计算,生成对应的四元式。

简单表达式的LL(1)分析表

在这里插入图片描述

表达式的中间代码生成过程分析举例

在这里插入图片描述

语义栈看上去压入的是x,但是实际上压入的是x的语义信息。
首先对应输入流的第一个字符x,文法从E开始推导,(这里的语义栈是从左往右写的),使用E->T Es生成然后T继续使用T->P Ts,继续向下生长子树,继续执行P->id #Push(id)#,(注意写的顺序,id在分析栈的顶部),这个时候可以把id(也就是x)和输入流中的x进行匹配,将id匹配掉,执行push,剩下的不是句柄,继续进行。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
执行加减乘除的操作的时候生成对应的四元式。最后的计算结果存储在语义栈Gem的栈顶。
⚠️符号表是在什么时候被创建的?实际上是在语义动作中实现符号表的创建、检查和删除。
⚠️如果是有回溯的自底向上语法如何插入语义动作?首先确定正确的可执行路经,然后在确定好的路径上添加想要执行的语义动作。

例题:

将下列表达式翻译成四元式序列:X*2+A*(i+1)/(j+1),其中i和j为整型变量,其它为实型变量。
(将给定的表达式翻译成四元式,根据计算过程,一般给的是程序)

(float,2,_,t1)//首先将常数赋值给中间变量t1,整型变量变成float
(multf,X,t1,t2)//执行+前面的部分
(addi,i,1,t3)//首先执行i+1的部分
(float,t3,_,t4)//因为i和j是整型变量,在这里进行实型变量运算,所以需要将其转换成float计算
(multf,A,t4,t5)//执行A*(i+1)
(addi,j,1,t6)
(float,t6,_,t7)
(divf,t5,t7,t8)
(addf,t2,t8,t9)

二、变量的中间代码生成

  1. 标识符变量——直接压入Gem
  2. 指针变量——将栈顶的元素取出,然后将其地址压入Gem
  3. 域选择变量——类似结构体structure中的某个分量,eg:student.ID
  4. 下标变量(数组)——需要两步寻址
    在这里插入图片描述
    首先检查域名和标识符的正确性;给中间变量开辟一个空间;找到当前访问的是structure中的哪个部分,确定其具体的偏移;Gen([],sem(s-2),x,t)生成当前要访问的域选择变量的地址。[]表示地址生成运算,sem(s-2)代表当前structure的起始地址,x代表偏移,t存储计算地址得到的结果。将用来计算地址的两个变量弹出Gem,然后将得到的地址结果压入Gem。
typedef struct node{
   int data1;//占一个空间
   float data2;//占2个空间
}Node;

对应的地址:如果层数是l,偏移是Off1
data1——Off1
data2——Off1+1

在这里插入图片描述
在取出E的值之前首先要判断一下V是否是数组类型的变量;计算V[E]的所在地址
[(用E减下界)*单位元数大小]+初始地址

#Addnext中要执行的动作:
1. (-,sem(s-1),sem(s-2).low,t1)
2. (*,t1,si,t2)
3. ([ ],sem(s-2),t2,t3)
4. pop(2); push(t3)

在这里插入图片描述
上面的过程详细分析:
在这里插入图片描述
看起来第一步好像没有什么用途,但是并不是所有语言的数组下界都是从0开始的,所以还是有意义的。

对应的一般情况

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

例题:

在这里插入图片描述
上面的答案没有涉及到数组下界的那个四元式

首先进行a[][]中下标的计算:
(+,5,i,t1)
(-,t1,0,t2)//和第一维下标相减,使用的是定义的A[i][j]中的i
(*,t2,30,t3)
//这里数组a的类型是rt,而rt中每个元素占3个单位
//第一维a[i]指向的是一个10个元素的序列,所以size/per = 30
([],a,t3,t4)
(-,6,0,t5)和第二维下标相减,使用的是定义的A[i][j]中的j
(*,t5,3,t6)
([],t4,t6,t7)
([],t7,1,t8)//访问域变量标识符,int占1个字节,所以这里的偏移量是1
(float,m,_,t9)//m是整型,与浮点型进行计算,向上转型成float,然后参与计算
(*,t9,z,t10)
(+,t8,t10,t11)

对应生成的语法树如下:
在这里插入图片描述

在这里插入图片描述
数组的下标的下界看定义的时候从哪里开始,这里定义的时候是从1开始的所以是(-,t1,1,t2)

三、赋值语句的中间代码

在这里插入图片描述
left中间代码的生成按照正常前面的标识符变量、指针变量、域选择变量、下标变量等进行计算;right中间代码的生成按照表达式中间代码的生成计算。
(赋值语句的left可能是前面的下标变量,left需要计算;right部分可能是一个表达式,right也需要计算。)
ASSIG代表赋值操作

Assign过程中的一些操作:涉及到栈的操作,类型的比较,最后四元式的生成
在这里插入图片描述
最后直接使用(=,t8,-,t9)将两边得到的结果直接使用一句=进行操作即可。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值