编译原理语义分析和中间代码生成.ppt

上传人:wuy****n92 文档编号:91223598 上传时间:2023-05-24 格式:PPT 页数:169 大小:754.50KB
返回 下载 相关 举报
编译原理语义分析和中间代码生成.ppt_第1页
第1页 / 共169页
编译原理语义分析和中间代码生成.ppt_第2页
第2页 / 共169页
点击查看更多>>
资源描述

《编译原理语义分析和中间代码生成.ppt》由会员分享,可在线阅读,更多相关《编译原理语义分析和中间代码生成.ppt(169页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 第第4章章 语义分析和中间代码生成语义分析和中间代码生成 4.1 概述概述 4.2 属性文法属性文法 4.3 几种常见的中间语言几种常见的中间语言 4.4 表达式及赋值语句的翻译表达式及赋值语句的翻译 4.5 控制语句的翻译控制语句的翻译 4.6 数组元素的翻译数组元素的翻译 4.7 过程或函数调用语句的翻译过程或函数调用语句的翻译 4.8 说明语句的翻译说明语句的翻译4.9 递归下降语法制导翻译方法简介递归下降语法制导翻译方法简介 第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.1 概概 述述 4.1.1语义分析

2、的概念一个源程序经过词法分析、语法分析之后,表明该源程序在书写上是正确的,并且符合程序语言所规定的语法。但是语法分析并未对程序内部的逻辑含义加以分析,因此编译程序接下来的工作是语义分析,即审查每个语法成分的静态语义。如果静态语义正确,则生成与该语言成分等效的中间代码,或者直接生成目标代码。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 直接生成机器语言或汇编语言形式的目标代码的优点是编译时间短且无需中间代码到目标代码的翻译,而中间代码的优点是使编译结构在逻辑上更为简单明确,特别是使目标代码的优化比较容易实现。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 如同在进行

3、词法分析、语法分析的同时也进行着词法检查、语法检查一样,在语义分析时也必然要进行语义检查。动态语义检查需要生成相应的目标代码,它是在运行时进行的;静态语义检查是在编译时完成的,它涉及以下几个方面:(1)类型检查,如参与运算的操作数其类型应相容。(2)控制流检查,用以保证控制语句有合法的转向点。如C语言中不允许goto语句转入case语句流;break语句需寻找包含它的最小switch、while或for语句方可找到转向点,否则出错。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (3)一致性检查,如在相同作用域中标识符只能说明一次、case语句的标号不能相同等。语义分析阶段只产生

4、中间代码而不生成目标代码的方法使编译程序的开发变得较为容易,但语义分析不像词法分析和语法分析那样可以分别用正规文法和上下文无关文法描述。由于语义是上下文有关的,因此语义的形式化描述是非常困难的,目前较为常见的是用属性文法作为描述程序语言语义的工具,并采用语法制导翻译的方法完成对语法成分的翻译工作。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.1.2语法制导翻译方法语法制导翻译的方法就是为每个产生式配上一个翻译子程序(称语义动作或语义子程序),并在语法分析的同时执行这些子程序。语义动作是为产生式赋予具体意义的手段,它一方面指出了一个产生式所产生的符号串的意义,另一方面又按照这

5、种意义规定了生成某种中间代码应做哪些基本动作。在语法分析过程中,当一个产生式获得匹配(对于自上而下分析)或用于归约(对于自下而上分析)时,此产生式相应的语义子程序就进入工作,完成既定的翻译任务。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 语法制导翻译分为自下而上语法制导翻译和自上而下语法制导翻译,我们重点介绍自下而上语法制导翻译。假定有一个自下而上的LR分析器,我们可以把这个LR分析器的能力加以扩大,使它能在用某个产生式进行归约的同时调用相应的语义子程序进行有关的翻译工作;每个产生式的语义子程序执行之后,某些结果(语义信息)必须作为此产生式的左部符号的语义值暂时保存下来,以便

6、以后语义子程序引用这些信息。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 此外,原LR分析器的分析栈也加以扩充,以便能够存放与文法符号相对应的语义值。这样,分析栈可以存放三类信息:分析状态、文法符号及文法符号对应的语义值。扩充后的分析栈如图41所示。作为一个例子,我们考虑下面的文法及语义动作所执行的程序:第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 产生式语义动作(0)SEprintvalTOP(1)EE(1)+E(2)valTOP=valTOP+valTOP+2(2)EE(1)*E(2)valTOP=valTOP*valTOP+2(3)E(E(1)valTOP

7、=valTOP+1(4)EivalTOP=lexval(注:lexval为i的整型内部值)这个文法的LR分析表见表3.20。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 我们扩充分析栈工作的总控程序功能,使其在完成语法分析的同时也能完成语义分析工作(这时的语法分析栈已成为语义分析栈);即在用某一个规则进行归约之后,调用相应的语义子程序完成与所用产生式相应的语义动作,并将每次工作后的语义值保存在扩充后的“语义值”栈中。图42表示算术表达式79*5#的语法树及各结点值,而表4.1则给出了根据表3.20用LR语法制导翻译方法得到的该表达式的语义分析和计值过程。第第4 4章章 语义分析

8、和中间代码生成语义分析和中间代码生成 图41扩充后的LR分析栈第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图42语法制导翻译计算表达式79*5#的语法树第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 表4.1表达式79*5#的语义分析和计值过程步骤状态栈符号栈语义栈输入串主要动作10#_79*5#s3203#7_9*5#r4301#E_79*5#s44014#E+_7_9*5#s350143#E+9_7_*5#r460147#E+E_7_9*5#s5701475#E+E*_7_9_5#s38014753#E+E*5_7_9_#r49014758#E+E*E_7_

9、9_5#r2100147#E+E_7_45#r11101#E_52#acc第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.2 属属 性性 文文 法法4.2.1文法的属性属性是指与文法符号的类型和值等有关的一些信息,在编译中用属性描述处理对象的特征。随着编译的进展,对语法分析产生的语法树进行语义分析,且分析的结果用中间代码描述出来。对于一棵等待翻译的语法树,它的各个结点都是文法中的一个符号X,该X可以是终结符或非终结符。根据语义处理的需要,在用产生式AX进行归约或推导时,应能准确而恰当地表达文法符号X在归约或推导时的不同特征。第第4 4章章 语义分析和中间代码生成语义分析和中间

10、代码生成 例如,判断变量X的类型是否匹配,要用X的数据类型来描述;判断变量X是否存在,要用X的存储位置来描述;而对X的运算,则要用X的值来描述;因此,语义分析阶段引入X的属性,如X.type、X.place、X.val等来分别描述变量X的类型、存储位置以及值等不同的特征。文法符号的属性可分为继承属性与综合属性两类。继承属性用于“自上而下”传递信息。继承属性由相应语法树中结点的父结点属性计算得到,即沿语法树向下传递,由根结点到分枝(子)结点,它反映了对上下文依赖的特性。继承属性可以很方便地用来表示程序语言上下文的结构关系。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 综合属性用于

11、“自下而上”传递信息。综合属性由相应语法分析树中结点的分枝结点(即子结点)属性计算得到,其传递方向与继承属性相反,即沿语法分析树向上传递,从分枝结点到根结点。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.2.2属性文法属性文法是一种适用于定义语义的特殊文法,即在语言的文法中增加了属性的文法,它将文法符号的语义以“属性”的形式附加到各个文法的符号上(如上述与变量X相关联的属性X.type、X.place和X.val等),再根据产生式所包含的含义,给出每个文法符号属性的求值规则,从而形成一种带有语义属性的上下文无关文法,即属性文法。属性文法也是一种翻译文法,属性有助于更详细地指

12、定文法中的代码生成动作。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 例如,简单算术表达式求值的属性文法如下:产生式语义规则(1)SEprint(E.val)(2)EE(1)+TE.val=E(1).val+T.val(3)ETE.val=T.val(4)TT(1)*F T.val=T(1).val*F.val(5)TT(1)T.val=T(1).val(6)F(E)F.val=E.val(7)FiF.val=i.lexval第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 上面的一组产生式中,每一个非终结符都有一个属性val来表示整型值,如E.val表示E的整型值

13、,而i.lexval则表示i的整型内部值。与产生式关联的每一个语义规则的左部符号E、T、F等的属性值的计算由其各自相应的右部符号决定,这种属性也称为综合属性。与产生式SE关联的语义规则是一个函数print(E.val),其功能是打印E产生式的值。S在语义规则中没有出现,可以理解为其属性是一个虚属性。我们再举一例说明属性文法。一简单变量类型说明的文法GD如下:GD:DintLfloatLLL,idid第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 其对应的属性文法为:产生式语义规则(1)DTLL.in=T.type(2)TintT.type=int(3)TfloatT.type=f

14、loat(4)LL(1),idL(1).in=L.in;addtype(id.entry,L.in)(5)Lidaddtype(id.entry,L.in)注意到与文法GD相应的说明语句形式可为intid1,id2,,idn或者floatid1,id2,,idn第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 非终结符T有一个综合属性type,其值为int或float。语义规则L.in=T.type表示L.in的属性值由相应说明语句指定的类型T.type决定;属性L.in被确定后将随语法树的逐步生成而传递到下边的有关结点使用,这种结点属性称为继承属性。由此可见,标识符的类型可以通过

15、继承属性的复写规则来传递。例如,对输入串inta,b,根据上述的语义规则,可在其生成的语法树中看到用“”表示的属性传递情况,如图43所示。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图43属性信息传递情况示意第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.3 几种常见的中间语言几种常见的中间语言4.3.1抽象语法树抽象语法树也称图表示,是一种较为流行的中间语言表示形式。在抽象语法树表示中,每一个叶结点都表示诸如常量或变量这样的运算对象,而其它内部结点则表示运算符。抽象语法树不同于前述的语法树,它展示了一个操作过程并同时描述了源程序的层次结构。第第4 4章章

16、语义分析和中间代码生成语义分析和中间代码生成 注意,语法规则中包含的某些符号可能起标点符号作用也可能起解释作用。如赋值语句语法规则:SV=e其中的赋值号“=”仅起标点符号作用,其目的是把V与e分开;而条件语句语法规则:Sif(e)S1;elseS2第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 其中的保留字符号if和else起注释作用,说明当布尔表达式e为真时执行S1,否则执行S2;而“;”仅起标点符号作用。可以看出,上述语句的本质部分是V、e和Si。当把语法规则中本质部分抽象出来而将非本质部分去掉后,便得到抽象语法规则。这种去掉不必要信息的做法可以获得高效的源程序中间表示。上述

17、语句的抽象语法规则为:第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (1)赋值语句:左部表达式(2)条件语句:表达式语句1语句2与抽象语法相对应的语法树称为抽象语法树或抽象树,如赋值语句x=ab*c的抽象语法树如图44(a)所示,而图44(b)则是该赋值语句的普通语法树。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图44x=ab*c的语法树第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 抽象语法树的一个显著特点是结构紧凑,容易构造且结点数较少。图44(b)所示的普通语法树的结点为14个;而图44(a)所示的抽象语法树的结点仅有7个,且每个内部结点

18、最多只有两个分支,因此可以将每个赋值语句或表达式表示为一棵二叉树。对于含有多元运算的更为复杂的语法成分,相应的抽象语法树则为一棵多叉树,但我们总可以将其转变为一棵二叉树。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.3.2逆波兰表示法逆波兰表示法是波兰逻辑学家卢卡西维奇(Lukasiewicz)发明的一种表示表达式的方法,这种表示法把运算量(操作数)写在前面,把运算符写在后面,因而又称后缀表示法。例如,把a+b写成ab+,把a*(b+c)写成abc+*。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 1表达式的逆波兰表示表达式E的后缀表示的递归定义如下:(1)

19、如果E是变量或常数,则E的后缀表示即E自身。(2)如果E为E1opE2形式,则它的后缀表示为E1E2op;其中op是二元运算符,而E1、E2分别又是E1和E2的后缀表示。若op为一元运算符,则视E1和E1为空。(3)如果E为(E1)形式,则E1的后缀表示即为E的后缀表示。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 上述递归定义的实质是:后缀表示中,操作数出现的顺序与原来一致,而运算符则按运算先后的顺序放入相应的操作数之后(即运算符先后的顺序发生了变化)。这种表示已不再需要用括号来规定运算的顺序了。后缀表示中的计值用栈实现非常方便。一般的计值过程是自左至右扫描后缀表达式,每碰到

20、运算量就把它推进栈,每碰到K目运算符就把它作用于栈顶的K个运算量,并用运算的结果(即一个运算量)来取代栈顶的K个运算量。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 2程序语句的逆波兰表示为了用逆波兰式表示一些控制语句,我们定义转移操作如下:(1)BL:转向某标号;(2)BT:条件为真时转移;(3)BF:条件为假时转移;(4)BR:无条件转移。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 部分程序语句的逆波兰表示如下:(1)赋值语句。赋值语句“=”的逆波兰表示为=例如,赋值语句“x=a+b*c”可按逆波兰式写为“xabc*+=”。(2)GOTO语句。转向语句“G

21、OTO”的逆波兰表示为BL其中,“BL”为单目后缀运算符,“”则为BL的一个运算分量。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (3)条件语句。BR表示无条件转移单目后缀运算符。例如,“BR”表示无条件转移到“”处,这里的顺序号是BR的一个特殊运算分量,用来表示逆波兰式中单词符号的顺序号(即第几个单词),它不同于GOTO语句中的语句标号。BT和BF表示按条件转移的两个双目后缀运算符。例如:BTBF第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 分别表示当e为真或假时转移到顺序号处;其中,布尔表达式e的逆波兰式和顺序号是两个特殊的运算分量。若 使 用 BT和 B

22、F两 个 运 算 符,则 条 件 语 句if(e)S1;elseS2的逆波兰式为:BF/*e为假则转S2的第一个单词的顺序号*/*e为真则执行S1*/BR/*S1执行结束后无条件转出该条件语句*/第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (3)条件语句。BR表示无条件转移单目后缀运算符。例如,“BR”表示无条件转移到“”处,这里的顺序号是BR的一个特殊运算分量,用来表示逆波兰式中单词符号的顺序号(即第几个单词),它不同于GOTO语句中的语句标号。BT和BF表示按条件转移的两个双目后缀运算符。例如:BTBF第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 例如,条

23、件语句if(mn)k=i+1;elsek=i1的逆波兰式表示为(1)(18)为单词编号):(1)mn(4)13BF(6)ki1+=(11)18BR(13)ki1=(18)if语句的后继语句此逆波兰式也可写在一行上,即mn13BFki1+=18BRki1=第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (4)循环语句。for循环语句为:for(i=m;i=n;i+)S;其中,i为循环控制变量,m为初值,n为终值,S为循环体。循环语句不能直接用逆波兰表示,因而将其展开为等价的条件语句后再用逆波兰表示,即i=m;10:if(i=n)S;i=i+1;gotol0第第4 4章章 语义分析和

24、中间代码生成语义分析和中间代码生成 4.3.3三地址代码1三地址代码的形式三地址代码语句的一般形式为x=yopz其中,x、y和z为名字、常量或编译时产生的临时变量;op为运算符,如定点运算符、浮点算符和逻辑运算符等。三地址代码的每条语句通常包含三个地址,两个用来存放运算对象,第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 一个用来存放运算结果。在实际实现中,用户定义的名字将由指向符号表中该名字项的指针所取代。由于三地址语句只含有一个运算符,因此多个运算符组成的表达式必须用三地址语句序列来表示,如表达式x+y*z的三地址代码为:t1=y*zt2=x+t1第第4 4章章 语义分析和中

25、间代码生成语义分析和中间代码生成 其中,t1和t2是编译时产生的临时变量。三地址代码是语法树的一种线性表示,如图44(a)所示的语法树用三地址代码表示为:t1=b*ct2=at1x=t2第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 2三地址语句的种类作为中间语言的三地址语句非常类似于汇编代码,它可以有符号标号和各种控制流语句。常用的三地址语句有以下几种:(1)x=yopz形式的赋值语句,其中op为二目的算术运算符或逻辑运算符。(2)x=opy形式的赋值语句,其中op为一目运算符,如一目减uminus、逻辑否定not、移位运算符以及将定点数转换成浮点数的类型转换符。第第4 4章章

26、 语义分析和中间代码生成语义分析和中间代码生成 (3)x=y形式的赋值语句,将y的值赋给。(4)无条件转移语句gotoL,即下一个将被执行的语句是标号为L的语句。(5)条件转移语句ifxropygotoL,其中rop为关系运算符,如、=等。若x和y满足关系rop就转去执行标号为L的语句,否则继续按顺序执行本语句的下一条语句。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (6)过程调用语句parX和callP,n。源程序中的过程调用语句P(X1、X2、,Xn)可用下列三地址代码表示:parX1parX2parXncallP,n其中,整数n为实参个数。过程返回语句为returny,

27、其中y为过程返回值。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (7)变址赋值语句x=yi,其中x、y、i均代表数据对象,表示把从地址y开始的第i个地址单元中的值赋给x。xi=y则表示把y的值赋给从地址x开始的第i个地址单元。(8)地址和指针赋值语句x=&y表示将y的地址赋给x,y可以是一个名字或一个临时变量,而x是指针名或临时变量;x=*y表示将y所指示的地址单元中的内容(值)赋给x,y是一个指针或临时变量;*x=y表示指将x所指对象的值置为y的值。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 3三地址代码的具体实现三地址代码是中间代码的一种抽象形式。在编译

28、程序中,三地址代码语言的具体实现通常有三种表示方法:四元式、三元式和间接三元式。1)四元式四元式是具有四个域的记录结构,这四个域为(op,arg1,arg2,result)第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 其中,op为运算符;arg1、arg2及result为指针,它们可指向有关名字在符号表中的登记项或一临时变量(也可空缺)。常用的三地址语句与相应的四元式对应如下:x=yopz对应(op,y,z,x)x=y对应(uminus,y,_,x)x=y对应(=,y,_,x)parx1对应(par,x1,_,_)callP对应(call,_,_,P)gotoL对应(j,_,_

29、,L)ifxropygotoL对应(jrop,x,y,L)第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 例如,赋值语句a=b*(c+d)相应的四元式代码为:(+,c,d,t1)(*,b,t1,t2)(=,t2,_,a)我们约定:凡只需一个运算量的算符一律使用arg1。此外,注意这样一个规则:如果op是一个算术或逻辑运算符,则result总是一个新引进的临时变量,它用来存放运算结果。由上例也可看出,四元式出现的顺序与表达式计值的顺序是一致的,四元式之间的联系是通过临时变量实现的。四元式由于其表示更接近程序设计的习惯而成为一种普遍采用的中间代码形式。第第4 4章章 语义分析和中间代

30、码生成语义分析和中间代码生成 2)三元式三元式是具有三个域的记录结构,这三个域为(op,arg1,arg2)其中,op为运算符;arg1、arg2既可指向有关名字在符号表中的登记项或临时变量,也可以指向三元式表中的某一个三元式。例如,相应于赋值语句a=(b+c)*(b+c)的三元式代码为:第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (+,b,c)(+,b,c)(*,)(=,a,)上述三元式表示的结果与的结果相乘。由上例可知,三元式出现的先后顺序和表达式各部分的计值顺序是一致的。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 3)间接三元式在三元式代码表的基础上另

31、设一张表,该表按运算的次序列出相应三元式在三元式表中的位置,这张表称为间接码表。三元式表只记录不同的三元式语句,而间接码表则表示由这些语句组成的运算次序。例如,赋值语句a=(b+c)*(b+c)对应的三元式表与间接码表为:三元式表:(+,b,c)(*,)(=,a,)间接码表:第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 在三元式表示中,每个语句的位置同时有两个作用:一是可作为该三元式的结果被其它三元式引用;二是三元式位置顺序即为运算顺序。在代码优化阶段,需要调整三元式的运算顺序时会遇到困难,这是因为三元式中的arg1、arg2也可以是指向某些三元式位置的指针,当这些三元式的位置

32、顺序发生变化时,含有指向这些三元式位置指针的相关三元式也需随之改变指针值。因此,变动一张三元式表是很困难的。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 对四元式来说,引用另一语句的结果可以通过引用该语句的result(通常是一个临时变量)来实现,而间接三元式则通过间接码表来描述语句的运算次序。这两种方法都不存在语句位置同时具有两种功能的现象,代码调整时要做的改动只是局部的,因此,当需要对中间代码表进行优化处理时,四元式与间接三元式都比三元式方便得多。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.4 表达式及赋值语句的翻译表达式及赋值语句的翻译4.4.1简单

33、算术表达式和赋值语句的翻译简单算术表达式是一种仅含简单变量的算术表达式;简单变量是指普通变量和常数,但不含数组元素及结构引用等复合型数据结构。简单算术表达式的计值顺序与四元式出现的顺序相同,因此很容易将其翻译成四元式形式,这些翻译方法稍加修改也可用于产生三元式或间接三元式。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 考虑以下文法GA:Ai=EEE+EE*EE(E)i在此,非终结符A代表“赋值句”。文法GA虽然是一个二义文法,但通过确定运算符的结合性及规定运算符的优先级就可避免二义性的发生。为了实现由表达式到四元式的翻译,需要给文法加上语义子程序,以便在进行归约的同时执行对应的

34、语义子程序。语义子程序所涉及的语义变量、语义过程及函数说明如下:第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (1)对非终结符E定义语义变量E.place,即用E.place表示存放E值的变量名在符号表中的入口地址或临时变量名的整数码。(2)定义语义函数newtemp(),即每次调用newtemp()时都将回送一个代表新临时变量的整数码;临时变量名按产生的顺序可设为T1、T2、。(3)定义语义过程emit(op,arg1,arg2,result),emit的功能是产生一个四元式并填入四元式表中。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (4)定义语义函数lo

35、okup(i.name),其功能是审查i.name是否出现在符号表中,是则返回i.name在符号表的入口指针,否则返回NULL。使用上述语义变量、过程和函数,可写出文法GA中的每一个产生式的语义子程序。(1)Ai=Ep=lookup(i.name);if(p=NULL)error();elseemit(=,E.place,_,P);(2)EE(1)+E(2)E.place=newtemp();emit(+,E(1).place,E(2).place,E.place);第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (3)EE(1)*E(2)E.place=newtemp();em

36、it(*,E(1).place,E(2).place,E.place);(4)EE(1)E.place=newtemp();emit(uminus,E(1).place,_,E.place);(5)E(E(1)E.place=E(1).place;(6)Eip=lookup(i.name);if(p!=NULL)E.place=p;/*另一种表示为E.place=entry(i)*/elseerror();第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 例4.1试分析赋值语句X=B*(C+D)的语法制导翻译过程。解答赋值语句X=B*(C+D)的语法制导翻译过程如表4.2所示(加工

37、分析过程参考表4.1)。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 表4.2赋值语句X=B*(C+D)的翻译过程输入串归约产生式符号栈语义栈(place)四元式X=B*(C+D)#_=B*(C+D)#(6)#i_XB*(C+D)#i=_X_B*(C+D)#i=_X_*(C+D)#(6)#i=i_X_B*(C+D)#(4)#i=E_X_B(uminus,B,_,T1)*(C+D)#i=E_X_T1第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (C+D)#i=E*_X_T1_C+D)#i=E*(_X_T1_+D)#(6)#i=E*(i_X_T1_C+D)#i=E*

38、(E_X_T1_CD)#i=E*(E+_X_T1_C_)#(6)#i=E*(E+i_X_T1_C_D)#(2)#i=E*(E+E_X_T1_C_D(+,C,D,T2)#i=E*(E_X_T1_T2#(5)#i=E*(E)_X_T1_T2_#(3)#i=E*E_X_T1_T2(*,T1,T2,T3)#(1)#i=E_X_T3(=,T3,_,X)#A_X第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.4.2布尔表达式的翻译在程序语言中,布尔表达式一般由运算符与运算对象组成。布尔表达式的运算符为布尔运算符,即、,或为not、and和or(注:C语言中为!、&和|),其运算对象为布尔

39、变量,也可为常量或关系表达式。关系表达式的运算对象为算术表达式,其运算符为关系运算符、=、等。关系运算符的优先级相同但不得结合,其运算优先级低于任何算术运算符。布尔运算符的运算顺序一般为、,且和服从左结合,第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 布尔算符的运算优先级低于任何关系运算符(注意,此处的运算优先级约定不同于C语言)。此外,对布尔运算、关系运算、算术运算的运算对象的类型可不区分布尔型或算术型,假定不同类型的变换工作将在需要时强制执行。为简单起见,我们遵循以上运算约定讨论下述文法GE生成的布尔表达式:GE:EEEEEE(E)iiropi第第4 4章章 语义分析和中间

40、代码生成语义分析和中间代码生成 另一种方法是根据布尔运算的特点实施某种优化,即不必一步一步地计算布尔表达式中所有运算对象的值,而是省略不影响运算结果的运算。例如,在计算AB时,若计算出的A值为1,则B值就无需再计算了;因为不管B的结果是什么,AB的值都为1。同理,在计算AB时若发现A值为0,则B值也无需计算,AB的值一定为0。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 在后面的论述中,我们假定函数过程的工作不出现上述的副作用情况。如何确定一个表达式的真假出口呢?考虑表达式E(1)E(2),若E(1)为真,则立即知道E也为真,因此,E(1)的真出口也就是整个E的真出口;若E(1

41、)为假,则E(2)必须被计值,此时E(2)的第一个四元式就是E(1)的假出口。当然,E(2)的真假出口也就是整个E的真假出口。类 似 的 考 虑 适 用 于 对 E(1)E(2)的 翻 译。我 们 将E(1)E(2)和E(1)E(2)的翻译用图45表示,而对形如E(1)的表达式则只需调换E(1)的真假出口就可得到该表达式E的真假出口。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图45E(1)E(2)和E(1)E(2)的翻译图(a)E(1)E(2);(b)E(1)E(2)第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 在自下而上的分析过程中,一个布尔式的真假出口往

42、往不能在产生四元式的同时就填上,我们只好把这种未完成的四元式的地址(编号)作为E的语义值暂存起来,待到整个表达式的四元式产生完毕之后,再来填写这个未填入的转移目标。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 对于每个非终结符E,我们需要为它赋予两个语义值E.tc和E.fc,以分别记录E所对应的四元式需要回填“真”、“假”出口的四元式地址所构成的链。这是因为在翻译过程中,常常会出现若干转移四元式转向同一个目标但目标位置又未确定的情况,此时可用“拉链”的方法将这些四元式链接起来,待获得转移目标的四元式地址时再进行返填。例如,假定E的四元式需要回填“真”出口的有p、q、r这三个四元

43、式,则它们可链接成如图46所示的一条真值链(记作tc)。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图46拉链法链接四元式示意第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 为了处理E.tc和E.fc这两项语义值,我们需要引入如下的语义变量和函数:(1)nxq:始终指向下一条将要产生的四元式的地址(序号),其初值为1。每当执行一次emit语句后,nxq自动增1。(2)merge(p1,p2):把以p1和p2为链首的两条链合并为一条以p2为链首的链(即返回链首值p2)。(3)Backpatch(p,t):把链首p所链接的每个四元式的第四区段(即result)都改写

44、为地址t。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 merge()函数如下:merge(p1,p2)if(p2=0)return(p1);elsep=p2;while(四元式p的第四区段内容不为0)第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 p=四元式p的第四区段内容;把p1填进四元式p的第四区段;return(p2);Backpatch()函数如下:Backpatch(p,t)Q=p;while(Q!=0)第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 q=四元式Q的第四区段内容;把t填进四元式Q的第四区段;Q=q;第第4 4章章 语义分析

45、和中间代码生成语义分析和中间代码生成 为了便于实现布尔表达式的语法制导翻译,并在扫描到“”与“”时能及时回填一些已经确定了的待填转移目标,我们将前述文法GE改写为下面的文法GE,以利于编制相应的语义子程序:GE:EEAEEBEE(E)iiropiEAEEBE第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 这时,文法GE的每个产生式和相应的语义子程序如下:(1)EiE.tc=nxq;E.fc=nxq+1;emit(jnz,entry(i),_,0);emit(j,_,_,0);(2)Ei(1)ropi(2)E.tc=nxq;E.fc=nxq+1;emit(jrop,entry(i(

46、1),entry(i(2),0);emit(j,_,_,0);(3)E(E(1)E.tc=E(1).tc;E.fc=E(1).fc;(4)EE(1)E.tc=E(1).fc;E.fc=E(1).tc;第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 (5)EAE(1)Backpatch(E(1).tc,nxq);EA.fc=E(1).fc;(6)EEAE(2)E.tc=E(2).tc;E.fc=merge(EA.fc,E(2).fc);(7)EBE(1)Backpatch(E(1).fc,nxq);EB.tc=E(1).tc;(8)EEBE(2)E.fc=E(2).fc;E.tc=

47、merge(EB.tc,E(2).tc);第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 例4.2试给出布尔表达式abcd作为控制条件的四元式中间代码。解答设四元式序号从100开始,则布尔表达式abcd的分析过程如图47所示。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图47表达式abcd分析示意第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 即:100(jnz,a,_,102)101(j,_,_,104)102(jnz,b,_,106)103(j,_,_,104)104(j,c,d,106)105(j,_,_,q)T:106F:q第第4 4章章

48、语义分析和中间代码生成语义分析和中间代码生成 当然,我们也可以通过图48的分析得到上述四元式序列。由例4.2可知,每一个布尔变量a都对应一真一假两个四元式,并且格式是固定的,即(jnz,a,_,0)/*a为布尔变量*/(j,_,_,0)而每一个关系表达式同样对应一真一假两个四元式,其格式也是固定的,即(jrop,X,Y,0)/*X、Y为关系运算符两侧的变量或值*/(j,_,_,0)第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图48abcd的翻译图第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.5 控制语句的翻译控制语句的翻译在源程序中,控制语句用于实现程序流

49、程的控制。一般程序流程控制可分为下面三种基本结构:(1)顺序结构,一般用复合语句实现;(2)选择结构,用if和case等语句实现;(3)循环结构,用for、while、do(即repeat)等语句实现。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 4.5.1条件语句if的翻译1条件语句if的代码结构我们按下面的条件语句if的模式进行讨论:if(E)S1;elseS2条件语句if(E);elseS2中布尔表达式E的作用仅在于控制对S1和S2的选择,因此可将作为转移条件的布尔式E赋予两种“出口”:一是“真”出口,出向S1;一是“假”出口,出向S2。于是,条件语句可以翻译成如图49所

50、示的代码结构。第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 图49条件语句if(E)S1;elseS2的代码结构第第4 4章章 语义分析和中间代码生成语义分析和中间代码生成 我们知道,非终结符E具有两项语义值E.tc和E.fc,它们分别指出了尚待回填真假出口的四元式串。E的“真”出口只有在扫描完布尔表达式E后的“)”时才能知道,而它的“假”出口则需要处理过S1之后并且到else时才能明确。这就是说,必须把E.fc的值传下去,以便到达相应的else时才进行回填。S1语句执行完就意味着整个if-else语句也已执行完毕,因此,第第4 4章章 语义分析和中间代码生成语义分析和中间代码

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 大学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁