编译原理第七章语义分析和中间代码生成内容总结

一、学习内容

第七章我们主要学习语义分析和中间代码生成。语义分析的任务一是审查每一个语法结构的静态语义,即验证语法正确的结构是否有意义;二是在语义正确的基础上生成一种中间代码或目标代码。语义分析的范围主要有确定类型、类型检查、识别含义、控制流检查、一致性检查、相关名字检查等。重点学习几种常用的中间语言形式:逆波兰表示法、图表示法、三元式、四元式。图表示法有抽象语法树和无循环有向图(DAG),二者基本上一样,对表达式中的每个子表达式,DAG中都有一个结点,一个内部结点表示一个操作符,它的孩子表示操作数,两者所不同的是,在一个DAG中代表公共子表达式的结点具有多个父结点,而在一棵抽象语法树中公共子表达式被表示为重复的子树。三元式由三个部分组成:算符OP,第一运算分量ARG1,第二运算分量ARG2。在三元式的基础上附加一张指示器表─间接码表,按运算的先后顺序列出有关三元式在三元式表中的位置,这种表示方法称为间接三元式。四元式是一个带有四个域的记录结构:op,arg1,arg2及result,它实际上就是一条三地址的指令。再往下我们学习了几种语句的四元式及翻译:说明语句的翻译,程序语言中的说明语句都是给编译程序提供信息的,诸如类型、维数、每维的界种类等,因此一般不生成目标,只是在编译时把有关信息填入相应表格即可;赋值语句的翻译,需要类型转换,可以把类型信息反映到运算符中。有的程序设计语言允许混合运算,有的不允许,如果不允许,则发现有类型不相同的运算分量就应该报错,如果允许,就要进行类型转换;控制流语句的翻译可以仿照算术表达式的翻译来进行,此部分内容较多为具体应用,在下文知识运用具体写。

二、知识运用

1.数组元素的地址计算公式

   若数组A的元素存放在一片连续单元里,则可以较容易的访问数组的每个元素。假定数组的每个元素的宽度为w,则一维数组A[i] 这个元素的起始地址为:base + (i –low)*w,其中low为数组下标的下界, base是分配给数组的相对地址,即base为A的第一个元素A[low]的相对地址。base+ (i–low)*w可整理为:i*w+ (base–low*w)。

2.二维数组

若二维数组A按行存放,则可用如下公式计算A[i1,i2]的相对地址:base+ ((i1–l1)*d2+i2–l2) *w,其中,l1、l2分别为i1、i2的下界;di界差。若ui为i的上界,则di=ui–li+1,假定i1,i2是编译时唯一尚未知道的值,我们可以重写上述表达式为:(base–((l1*d2) +l2) *w)+ ( (i1*d2) +i2) *w,其中前一项子表达式(base–(l1*d2) +l2) *w)的值是可以在编译时确定的记为常数CONSPART,后一子项随i1, i2而改变是一个变数记VARPART。

3.标号和无条件转移的翻译

   (1)对于说明性出现的标号,很容易处理:L: S

     当这种语句被处理之后,标号L被称为“定义了”的,在符号表中,标号L的“地址”栏将登记上语句S的第一个四元式的地址(编号)。

   (2)对于先定义后应用的无条件转移(向后转移的goto L ),也很容易处理。对L查表得到它的定义地址p,就可生成goto L的四元式(j,--,--,p)。

   (3)对于先应用后定义的情况(前向转移goto  L ):

     拉链返填:把所有以L为转移目标的四元式串在一起,链的首地址放在符号表中L的“地址”栏中。

     建链的方法:若L尚未在符号表中出现,则把L填入表中,置L的“定义否”为“未”,把nextquad填进L的地址栏中作为新链头。然后产生四元式(j,--,--,0),其中0为链末标志;若L已在符号表出现但“定义否”为“未”,则把它的地址栏的编号q取出,把nextquad填进该栏作新链头,然后产生四元式(j,--,--,q)。一旦标号L定义时,我们将根据这条链回填那些待填转移目标的四元式,直到某个四元式的地址部分为0(链尾)。

 

三、我的感受

第七章的难度较第六章小一点,相对而来掌握的更好。重点是布尔表达式的翻译和三地址表示形式、逆波兰表示等。对于其他的翻译方法没有深入讲解只了解了大概,看的比较粗糙。做了题目有的细节部分出错,比如没有注意逆波兰的符号运算次序和布尔表达式翻译中回填等。总体来说,对于本章内容要细心学习,不能浮于表面,要学习其中的编程思想,慢慢培养自己的逻辑思维能力,对编译原理有个更好的理解,打下良好基础。

猜你喜欢

转载自blog.csdn.net/xmj1886480/article/details/80633689
今日推荐