形式语言与编译 15 语法制导下的语义翻译过程

时间:2020-07-22 21:16:47   收藏:0   阅读:81

语法制导翻译和中间代码生成

语法分析之后进行语义分析。

语义分析包含两项工作:

中间代码的表示形式有很多,逆波兰记号、树形表示、三元式、四元式。

这些都是介于单词流目标指令之间的中间产品。


困难:语义分析(中间代码生成)不如词法分析、语法分析有比较成熟的数学工具(形式化工具)。语义分析的数学工具尚未诞生。虽然有属性文法,但是属性文法并不是一个完美的形式系统

解决办法:为每一个产生式配一个 翻译子程序 ,在语法分析的同时执行它。

在语法分析的过程中,每使用一个产生式就会使用一个语义动作,这里的语义动作我们主要使用的是 属性文法。在这样语法分析的过程中会产生中间代码。

我们语义分析的示例主要是使用自底向上的分析方法。但是要知道,自上而下也是可以进行语法制导的语义分析的。

我们并不是有源程序直接得到目标代码,而是在之间用中间代码过渡一下。尽管理论上是可以直接由源程序得到目标代码。

应用属性文法进行语义分析

技术分享图片

先运算e,等于0的话,到了y;不等于0的话,到了x;

技术分享图片

注意到上面??,\(p ~jump是一个一元运算符;e1~e2~p~jlt,是一个三元运算符;e~p~jez二元运算符\)

且第一个是绝对跳;后两个是条件跳

技术分享图片

对后缀表达式做出更改,使得其可以跳转到别的位置;这样原来的后缀表达式是没有的。比如上面的:先判断e是否等于0,如果等于0的话,跳转到p1,否则顺序执行x,执行完之后强制跳转到p2。

技术分享图片

用语法制导方式生成后缀表达式(逆波兰式)

技术分享图片

技术分享图片

逆波兰式比较适用于表达式类,但是其它类型语句效果就不一定好了

语法制导生成 三元式和树

三元式和我们的x86汇编语言很像。

技术分享图片

技术分享图片

还有另外一种三元式,是对上面的三元式表的一种优化

技术分享图片

可以少算一回

技术分享图片

语法制导产生树

语义方程

技术分享图片

四元式

对三元式进行优化,除了三元式原来的三个量,多了每一步计算得出的量,称为中间临时变量,保存临时中间结果。原来的三元式就做不到使用中间变量。四元式也是使用比较多的一种中间表示。

技术分享图片

技术分享图片

要清楚上面的这些所有中间表示都是语义分析阶段的输出,我们目前的难点就是要通过这些中间表示反推 花括号中的语义方程。看看写入什么语义方程才可以得到上面的各种中间表示。

后面我们使用四元式还是比较多

怎么样通过语法分析得到上面的中间表示,具体地说是四元式

一、先看表达式与赋值语句怎么分析(翻译)?

设计语义动作(语义过程确实也比较难,需要大量practice\看看别人的样例)

一般套路:定义好语义值;再列写四元式

要是属性比较多的话,语义栈中就会是结构体。我们的示例比较简单,属性只有一个,所以并未使用结构体

技术分享图片

技术分享图片

ENTRY表示查找符号表 entry(i)表达为变量i的存储地址

技术分享图片

自底向上归约

技术分享图片

归约过程自动产生四元式表

技术分享图片

终结符没有语义值;变量才有。所以对终结符只进行进入符号栈操作就行了,相应的语义栈会填入一个占位符。

每次归约的时候实际上都可以产生一个四元式,只不过根据语义动作,语义栈里的变量有的使用原来的语义值,有的gen()使用新的语义值,而我们通常写的时候只把有新变量的语义值写出来。

输入的符号如果是终结符,该符进符号栈,语义栈填充占位符;如果是非终结符,该符进语义栈,符号栈用终结符i占位。

表中有四元式的行,只是在归约过程中使用的是有gen语义动作的产生式。

上例中输入的是一个句型,输出的是一组四元式

技术分享图片

技术分享图片

技术分享图片

对原来的语义方程进行添加语义值E.mode


布尔表达式到四元式的翻译(属于控制语句部分)

研究布尔表达式的目标是研究第二大类——控制语句的一部分工作

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

布尔式的翻译

技术分享图片

真链、假链对应程序为真或者程序为假的情况下跳转

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

任何布尔表达式都有真转、假转两种去向。

翻译模式的方式:

技术分享图片

控制语句的翻译,两种方法:

技术分享图片

产生四元式的是下面这条emit = gen,标记方式不同

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

扫描完then有语义动作,因此需要归约;扫描完else之后也有语义动作,因此也需要归约

可以说是把原来的if else断开了,如下所示

技术分享图片

断开成3部分

改写之后的语义子程序

then扫描完知道回填(真出口)

else 产生一 个新的四元式(直接跳类型的)+回填(假出口)

else扫描完知道了假出口,并且产生一个可以跳过s2的直接跳转指令,但是这个跳转指令在哪里,又不知道,保留一个链

技术分享图片

发现确实有一些还没回填完毕,这些没有回填的语句观察发现都是指向程序段结束后,也就是(14),然后通过拉链法,串成一串,序号从小到大,一直指向(14)

技术分享图片

技术分享图片


while语句实际上就是带有标号的 if语句。

技术分享图片

while语句改写如上,旁边就是对应的四元式

回填序号可以通过流程图看出来

技术分享图片

技术分享图片

技术分享图片

技术分享图片

不变部分 CONSPART,编译之前就可以求出来,提前求出来;

可变部分 VARPART, 和具体求取的元素角标有关,运行时求出来

技术分享图片

技术分享图片

内情向量表是符号表的一部分,如果符号是数组,就会有一个地址栏,里面会是 内情向量表的指针。 扫描过程中找到数组名,发现是数组,进而可以找到内情向量表的地址

内情向量表有 维数、上界、下界、每一维尺寸、类型、C、起始地址等量

可变数组,不会提前建立内情向量表,因为有好多量不知道,无法建立。因此只能申请一块内存,然后就不要管了,在这块内存上动态、自由的发挥!

基地址+变地址

技术分享图片

技术分享图片

技术分享图片

技术分享图片

数组变量赋值例子:

先读取数组,然后可以从数组的内情向量表中读取,首地址a,C = 21 ,\(d_2 = 20,m=1\).然后进行数组赋值\(X~:=A[i,j]\)生成四元式序列。

技术分享图片

对于这个句子,逐词扫描:

根据题意,计算出C,type。再假设一个a

技术分享图片

\(-C = -l_1d_2-l_2,固定部分,我们只需要算i_1d_2+i_2\)

技术分享图片

技术分享图片

原文:https://www.cnblogs.com/fennleo/p/13363032.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!