《第8章语法制导翻译和中间代码生成.ppt》由会员分享,可在线阅读,更多相关《第8章语法制导翻译和中间代码生成.ppt(97页珍藏版)》请在三一办公上搜索。
1、第8章 语法制导翻译和中间代码生成,语法分析的作用是判断一个输入是否为一个句子,并且同时获得该句子的语法结构,即语法树。例如在算术表达式的翻译中,不仅要知道表达式中各个运算的先后次序,即语法结构,而且还要知道该表达式中的各个变量和常量的内存地址或值,要知道计算过程的中间结果所存放的内存地址或值,甚至还要知道其数据类型。这些信息都被称为语义信息,而对语义信息进行相应的分析处理就叫做语义分析。因此,翻译是一个语法分析和语义分析综合在一起进行的过程。,在编译程序中使用了这样的一种技术,就是在语法分析的同时进行语义分析的工作,并同步地完成相应语句的翻译。这种技术就称为语法制导翻译。,第5章教学内容,属
2、性文法的概念;语法制导翻译的概念;常用的中间代码形式;程序设计语言的语法结构的自底向上的语法制导翻译方法。,一、属性文法,属性文法是在上下文无关文法的基础上为每个文法符号(终结符或非终结符)配备若干个相关的“值”(称为属性)。这些属性代表与文法符号相关的信息,例如它的类型、值、代码序列、符号表内容等等。属性和变量一样,可以进行计算和传递。属性一般分为两类:综合属性和继承属性。简单的说,综合属性用于“自下而上”传递信息,而继承属性用于“自上而下”传递信息。,属性加工的过程即是语义处理的过程,对于文法的每一个产生式都配备了一组属性的计算规则,则称为语义规则。在一个属性文法中,对应于每个产生式A都有
3、一套与之相关联的语义规则,每条语义规则的形式为:b:=f(c1,c2,ck)这里f是一个函数,而且或者(1)b是A的一个综合属性并且c1,c2,ck是产生式右边文法符号的属性;或者(2)b是产生式右边某个文法符号的一个继承属性并且c1,c2,ck是A或产生式右边任何文法符号的属性。在这两种情况下,属性b依赖于属性c1,c2,ck。,要特别强掉的是:终结符只有综合属性,它由词法分析器提供;非终结符既可以有综合属性也可以有继承属性,文法开始符号的所有继承属性作为属性计算前的初始值。,一般来讲,对出现在产生式右边的继承属性和出现在产生式左边的综合属性都必须提供一个计算规则,属性计算规则中只能使用相应
4、产生式的文法符号的属性,这有利于产生式范围内“封装”属性的依赖性。然而,出现在产生式左边的继承属性和出现在产生式右边的综合属性不由所给的产生式的属性计算规则进行计算,它们由其它产生式的属性规则计算,由属性计算器的参数提供。,语义规则所描述的工作可以包括属性计算、静态语义检查、符号表操作、代码生成等。语义规则可能产生副作用(如产生代码),也可能不是变元的严格函数(如某个规则给出可用的下一个数据单元的地址)。这样的语义规则通常写成过程调用,或过程段。,综合属性,在语法树中,一个结点的综合属性的值由其子结点的属性值确定。因此,通常使用自底向上的方法在每一个结点处使用语义规则计算综合属性的值。仅仅使用
5、综合属性的属性文法称S属性文法。,继承属性,在语法树中,一个结点的继承属性由此结点的父结点和/或兄弟结点的某些属性确定。用继承属性来表示程序语言结构中的上下文依赖关系很方便。,属性文法的定义,【定义】一个属性文法AG是一个四元组,即AG=(G,A,R,B),其中G=(N,T,S,P)是一个前后文无关文法;A=X NT A(X)是一个属性的有限集合;R=p P R(p)是一个语义规则式的有限集合;B=p P B(p)是一个条件的有限集合;,属性文法的定义,并且满足以下两个条件:1对任意两个符号的X和Y,若XY,则A(X)A(Y)=;2对于任何在L(G)的句子所对应的语法树上出现的符号X,X的任意
6、一个属性X.a的计算,至多只有一条语义规则式可以应用。,属性文法示例,【例51】简单台式计算器的算术表达式的属性文法:产生式集G:语义规则式集R:L E print(E.val)E E1+T E.val=E1.val+T.valE T E.val=T.valT T1*F T.val=T1.val F.valT F T.val=F.valF(E)F.val=E.valF digit F.val=digit.lexval,示例,在该描述中,每个非终结符都有一个属性:一个整数值的称作val的属性。按照语义规则对每个产生式来说,它的左部E,T,F的属性值的计算来自它右部的非终结符,这种属性称作综合属性
7、。单词digit仅有综合属性,它的值是由词法分析程序提供的。和产生式L E相联的语义规则是一个过程,打印由E产生的表达式的值。我们可以理解为L的属性是空的或是虚的。,设表达式为3*5+4,则语义动作打印数值19,LR分析器可以改造为一个翻译器,在对输入串进行语法分析的同时对属性进行计算。LR分析器增加语义栈。,#,X1,Xm,I0,I1,Im,语义栈,-,X1.VAL,Xm.VAL,SLR(1)分析表,LR分析:增加语义栈 归约时进行语义动作。给出*的分析和计值过程。,二.语义分析的任务,编译程序的任务是把源程序翻译成目标程序,这个目标程序必须和源程序的语义等同,也就是说,尽管它们的语法结构完
8、全不同,但它们所表达的结果应完全相同。通常,在词法分析程序和语法分析程序对源程序的语法结构进行分析之后,要么由语法分析程序直接调用相应的语义子程序进行语义处理,要么首先生成语法树或该结构的某种表示,再进行语义处理。,编译中的语义处理是指两个功能:审查每个语法结构的静态语义,即验证语法结构合法的程序是否真正有意义。有时把这个工作称为静态语义分析或静态审查。如果静态语义正确,语义处理则要执行真正的翻译,即,要么生成程序的一种中间表示形式(中间代码),要么生成实际的目标代码。,通常包括:类型检查。控制流检查。控制流语句必须使控制转移到合法的地方。例如,在C语言中break语句使控制跳离包括该语句的最
9、小while、for或switch语句。如果不存在包括它的语句,则报错。一致性检查。在很多场合要求对象只能被定义一次。例如Pascal语言规定同一标识符在一个分程序中只能被说明一次,同一case语句的标号不能相同,枚举类型的元素不能重复出现等等。相关名字检查。有时,同一名字必须出现两次或多次。例如,Ada语言程序中,循环或程序块可以有一个名字,出现在这些结构的开头和结尾,编译程序必须检查这两个地方用的名字是相同的。名字的作用域分析。,三、中间代码,翻译为中间语言的好处:(1)便于进行与机器无关的代码优化;(2)使编译程序改变目标机更容易;(3)使编译程序的结构在逻辑上更为简单明确,以中间语言为
10、界面,编译前端和后端的接口更清晰。编译程序所使用的中间代码有多种形式。常见的有逆波兰式、三元式和树形、四元式表示。,1.逆波兰式,逆波兰式是最简单的一种中间代码表示形式,早在编译程序出现之前,它就用于表示算术表达式,是波兰逻辑学家卢卡西维奇发明的。这种表示法将运算对象写在前面,把运算符号写在后面,比如把a+b写成ab+,把a*b写成ab*,用这种表示法表示的表达式也称做后缀式。,示例,后缀表示法表示表达式,其最大的优点是易于计算机处理表达式。常用的算法是使用一个栈,自左至右扫描算术表达式(后缀表示),每扫描到运算对象,就把它推进栈;扫描到运算符,若该运算符是二目的,则对栈顶部的两个运算对象实施
11、该运算,并将运算结果代替这两个运算对象而进栈;若是一目运算符,则对栈顶元素执行该运算,并以运算结果代替该元素进栈,最后的结果留在栈顶。由于后缀式表示上的简洁和计值的方便,特别适用于解释执行的程序设计语言的中间表示,也方便具有堆栈体系的计算机的目标代码生成。,2.三元式和树形表示,另一类中间代码形式是三元式。把表达式及各种语句表示成一组三元式。每个三元式由三个部分组成,分别是:(算符op,第一运算对象ARG1,第二运算对象ARG2)运算对象可能是源程序中的变量,也可能是某个三元式的结果,用三元式的编号表示。对于一目算符op,只需选用一个运算对象,不妨规定只用ARG1。至于多目算符,可用若干个相继
12、的三元式表示。,示例,【例如】a=b*c+d*e的三元式表示为:(1)(*,b,c)(2)(*,d,e)(3)(+,(1),(2)(4)(,(3),a),树形表示,树形表示是三元式表示的翻版。,3.四元式,四元式是一种比较普遍采用的中间代码形式。四元式的四个组成成分是:算符op第一运算对象ARG1第二运算对象ARG2运算结果RESULT运算对象和运算结果有时指用户自己定义的变量,有时指编译程序引进的临时变量。,示例,四元式形式:(op,arg1,arg2,result)【例如】a=b*c+d*e的四元式为:(1)(*,b,c,T1)(2)(*,d,e,T2)(3)(+,T1,T2,T3)(4)
13、(=,T3,a),四元式表示很类似于三地址指令,确实,有时把这类中间表示称为“三地址代码”,因为这种表示可看作一种虚拟三地址机的通用汇编码,即这种虚拟机的每条“指令”包含操作符和三个地址,两个是为运算对象的,一个是为结果的。这种表示对于代码优化和目标代码生成都较有利。,示例,为了更直观,也把四元式的形式写成简单赋值形式或更易理解的形式:resultarg1 op arg2【例如】把上述四元式序列写成:(1)t1=b*c(2)t2=b*d(3)t3=t1+t2(4)a=t3(jump,L)写成goto L(jrop,B,C,L)写成if B rop C goto L,例如:A+B*(C-D)+E
14、/(C-D)N,四、简单赋值语句的翻译,语义过程GEN表示产生一个四元式,并且填入四元式表中。语义过程Newtemp表示生成一个临时变量,每调用一次,生成一新的临时变量。语义变量Eplace,表示存放E值的变量名在符号表的登录项或一整数码(若此变量是一个临时变量)。语义变量Entry(id)回送标识符id在符号表中的入口地址。,简单赋值语句的属性文法,产生式 语义规则 Sid=E GEN(=,E.Place,_,Entry(id))EE1+E2 E.place=Newtemp;GEN(+,E1.place,E2.place,E.place)EE1*E2 Eplace=Newtemp;GEN(*
15、,E1.place,E2.place,E.Place)EE1 E.place=Newtemp;GEN(,E1.place,_,E.place)E(E1)E.place=E1.place Eid E.place=Entry(id),a=b*c+d*e的翻译过程,a=b*c+d*e,E(c),E,E(b),E(d),E(e),T11.(*,b,c,T1),E,T22.(*,d,e,T2),E,T33.(+,T1,T2,T3),S,4.(=,T3,_,a),(1)(*,b,c,T1)(2)(*,d,e,T2)(3)(+,T1,T2,T3)(4)(=,T3,_,a),a=b*c+d*e的翻译结果,a=
16、-b*(c+d)的翻译过程,略。,类型转换的语义处理,实际上,在一个表达式中可能会出现各种不同类型的变量或常数。即编译程序还应执行这样的语义动作:对表达式中的运算对象应进行类型检查,如不能接受不同类型的运算对象的混合运算,则应指出错误;如能接受混合运算,则应进行类型转换的语义处理。例如,算术表达式可以进行实型量与整型量的混合运算,并且约定,当两个不同类型的量进行运算时,必须首先将整型量转换为实型量。,语义变量,语义变量Etype表示E的类型信息;为区别整型加(乘)和实型加(乘),把+(*)分别写作+i(*i)和+r(*r)。用一目算符itr表示将整型运算对象转换成实型。,示例,产生式:EE1*
17、E2语义动作:Eplace=Newtemp;if E1.type=int AND E2.typeint GEN(*i,E1.place,E2.place,E.place,);Etype=int else if E1.type=real AND E2.type=real GEN(*r,E1place,E2place,E.place);E.type=real,示例,else if E1.typeint/*and E2.type=real*/t=Newtemp;GEN(itr,E1.place,_,t);GEN(*r,t,E2.place,E.place,)E.type=real else/*E1t
18、ypereal and E2typeint*/t=Newtemp;GEN(itr,E2.place,_,t);GEN(*r,E1.place,t,E.place,)Etype=real,五、布尔表达式的翻译,程序设计语言中的布尔表达式有两个作用。一是计算逻辑值,二是用做改变控制流语句中的条件表达式,如在if-then,if-then-else,或是while-do语句中那样。,布尔表达式是由布尔算符and,or和not施于布尔变量或关系表达式而成。即布尔表达式的形式为E1 rop E2,其中E1和E2都是算术表达式,rop是关系符,如,等等。只考虑简单的布尔表达式文法:EE and E|E o
19、r E|not E|id rop id|id并且按通常习惯,约定布尔算符的优先顺序(从高到低)为not、and、or,并且and和or服从左结合。,布尔表达式的翻译方法,通常,计算布尔表达式的值有两种办法,第一种办法,如同计算算术表达式一样,计算出各部分的真假值,最后计算出整个表达式的值。例如,用数值1表示true,用0表示false。那么布尔表达式1 or(not 0 and 0)or 0的计算过程是:1 or(not 0 and 0)or 01 or(1 and 0)or 01 or 0 or 01 or 01,布尔值的翻译方案,EE1 or E2E.place=Newtemp;GEN(o
20、r,E1.place,E2.place,E.place)EE1 and E2 E.place=Newtemp;GEN(and,E1.place,E2.place,E.place)Enot E1 E.place=Newtemp;GEN(not,E1.place,_,E.place)E(E1)E.place=E1.placeEid1 rop id2 E.place=Newtemp;GEN(jrop,Entry(id1),Entry(id2),E.place)Eid E.place=Entry(id),另一种计算方法是采取某种优化措施,只计算部分表达式:A or B,若A的值为1,则无需计算B的值,
21、因为不管B的值为何结果,A or B的值都为1。A and B,若A的值为0,则无需计算B的值,因为不管B的值为何结果,A and B的值都为0。,控制语句中布尔表达式的翻译,条件控制语句if E then S1 else S2的目标代码结构如下:,“真”出口与“假”出口,布尔表达式E的作用仅在于控制对S1和S2的选择,而无须最终保留E值,故作为转移条件的布尔表达式E,可赋予它两种出口:“真”出口 E.TC S1“假”出口 E.FC S2,作为转移条件的布尔表达式E,可翻译为如下的四元式序列:(jnz,A,_,p)表示 if A goto p(jrop,A1,A2,p)表示 if A1 rop
22、 A2 goto p(j,_,_,p)表示 goto p,示例,【例如】条件语句 if A or BC then S1 else S2 可翻译为:(1)(jnz,A,_,(5)(2)(j,_,_,(3)(3)(j,B,C,(5)(4)(j,_,_,(p+1)(5)关于S1的四元式序列(p)(j,_,_,(q)(p+1)关于S2的四元式序列(q),如何确定一个表达式的真假出口,考虑E为E1 or E2的形式:若E1为真,则E为真,所以E1的真出口就是整个E的真出口。若E1为假,则必须计算E2,E2代码的第一个四元式标号就是E1的假出口,而E2的真出口和假出口就是整个E的真出口和假出口。,如何确定
23、一个表达式的真假出口,考虑E为E1 and E2的形式:若E1为假,则E为假,所以E1的假出口就是整个E的假出口。若E1为真,则必须计算E2,E2代码的第一个四元式标号就是E1的真出口,而E2的真出口和假出口就是整个E的真出口和假出口。考虑E为not E1 的形式:只需调换E1 的真假出口即可得到E的真假出口。,拉链,为了记录需回填地址的四元式,常采用一种“拉链”的办法。把需回填ETC的四元式拉成一条链子,把需回填EFC的四元式拉成一条链子,分别称做真链和假链。,示例,若有四元式序列:(10)gotoETC(20)gotoETC(30)gotoETC则把需回填E.TC的四元式(10),(20)
24、和(30)链成:(10)goto(0)(20)goto(10)(30)goto(20)把地址(30)称作链首,0为链尾标志,即地址(10)为链尾。,自底向上分析中的一种翻译方案,E E1 or E2(1)EAE1 or Backpatch(E1.FC,NXQ);EA.TC=E1.TC(1)E EAE2 E.FC=E2.FC;E.TC=Merg(EA.TC,E1.TC)【说明】Backpatch(p,t):将p链接的四元式的第四元都回填t;Merg(p1,p2):将以p1和p2为链首的两条链合并为一条链,返回时的函数值作为合并后的链首。,E E1 and E2(2)EBE1 and Backpa
25、tch(E1.TC,NXQ);EB.FC=E1.FC(2)E EBE2 E.TC=E2.TC;E.FC=Merg(EB.FC,E1.FC)(3)Enot E1 E.TC=E1.FC;E.FC=E1.TC,(4)E(E1)E.TC=E1.TC;E.FC=E1.FC(5)Eid1 rop id2 E.TC=NXQ;E.FC=NXQ+1;GEN(jrop,Entry(id1),Entry(id2),0);GEN(j,_,_,0)(6)Eid E.TC=NXQ;E.FC=NXQ1;GEN(jnz,Entry(id),_,0);GEN(j,_,_,0),六、控制语句的翻译,考虑if then,if th
26、en else和while do语句的翻译。GS:S if E then S|if E then S else S|while E do S|begin L end|A L L;S|S其中各非终结符号的意义是:S-语句L-语句串A-赋值句E-布尔表达式,1.条件语句if的翻译,考虑if 语句的翻译。产生式 S if E then S|if E then S else S,两个问题,布尔式E的真、假出口尚待回填E.TC,E.FC。if E then S1 else S2 else S3 在翻译完S2之后,S1后的无条件转移目标仍无法确定,因为它不仅要跨越S2还应跨越S3。即转移目标的确定和语句所
27、处的环境密切相关。故也可象处理布尔表达式一样,让非终结符S(和L)含有一项语义值SCHAIN(和LCHAIN)。也是一条链,它把所有那些四元式串在一起,这些四元式期待在翻译完S(L)之后回填转移目标。真正的回填工作将在处理S的外层环境的某一适当时候完成。,单分支条件语句的目标结构,if E then S1 的目标代码结构如下:,多分支条件语句的目标结构,if E then S1 else S2的目标代码结构如下:,翻译方案,if E then S1 C if E then Backpatch(E.TC,NXQ);C.CHAIN=E.FC S C S1 S.CHAIN=Merg(C.CHAIN,
28、S1.CHAIN),if E then S1 else S2C if E then Backpatch(E.TC,NXQ);C.CHAIN=E.FC TP C S1 else q=NXQ;GEN(j,_,_,0);Backpatch(C.CHAIN,NXQ);TP.CHAIN=Merg(S1.CHAIN,q)S TP S2 S.CHAIN=Merg(TP.CHAIN,S2.CHAIN),2.循环语句的翻译,while E do S1 的目标代码结构如下:,翻译方案,W while W.quad=NXQ Wd W E do Backpatch(E.TC,NXQ);Wd.CHAIN=E.FC;Wd
29、.quad=W.quad S Wd S1 Backpatch(S1.CHAIN,Wd.quad);GEN(j,_,_,Wd.quad);S.CHAIN=Wd.quad,第一个四元式的地址,示例,while(AB)do if(CD)then X=Y+Z将被翻译成如下的一串四元式:100(j,A,B,102)101(j,_,_,107)102(j,C,D,104)103(j,_,_,100)104(+,Y,Z,T1)105(=,T1,_,X)106(j,_,_,100)107,3.for循环语句,for i=E1 step E2 until E3 do S1为了简单起见,假定E2总是正的。在这种假
30、定下,上述循环句的意义等价于:i=E1;goto OVER;AGAIN:i=i+E2;OVER:if iE3 thenbegin S1;goto AGAIN end;,七、简单说明语句的翻译,程序设计语言中的说明语句旨在定义各种形式的有名实体,如常量、变量、数组、记录(结构)、过程、子程序等等,说明语句的种类也多,对象说明、变量说明、类型说明、过程说明等等。编译程序把说明语句中定义的名字和性质登记在符号表中,用以检查名字的引用和说明是否一致。许多说明语句的翻译并不生成相应的目标代码。过程说明和动态数组的说明有相应的代码。,简单说明句的文法,程序设计语言中最简单的说明句的语法描述为:D inte
31、gernamelist|realnamelistnamelisenamelist,id|id即使用关键字integer和real定义一串名字的性质。对这种说明句的翻译是指在符号表中登录该名和性质。,翻译方案,语义变量D.type:用以记录说明句所引入的名字的性质(int还是real);语义过程enter(id,A):把名字id和类型A登录在符号表中。(1)Dinteger id enter(id,int);D.type=int(2)Drealid enter(id,real);D.type=real(3)DD1,id enter(id,D1.type);D.type=D1.type,八、数组元
32、素访问的翻译,讨论包括数组元素的表达式和赋值语句的翻译问题。一个数组是由同一类型数据所组成的某种n维矩形结构。沿着每一维的距离称为一个下标。每维的下标只能在该维的上、下限之内变动。数组的每个元素是矩形结构中的一个点,它的位置可通过给出每维的下标来确定。,数组的存储,数组的存储表示有多种形式,最简单的一种是把整个数组按行(或按列)存放在一片连续存储区中。例如,若A是一个23的二维数组,每个元素占一个单元,那么,所谓按行和按列的存储方式分别如图所示。有些程序语言,如 FORTRAN,要求以列为序存放数组;另一些,如 PLl,要求以行为序;还有一些则取决于编译程序设计者的意愿。,数组按列存放,数组按
33、行存放,计算数组元素的地址,数组元素的地址计算和数组的存储方式密切相关。在以行为序的情形下,如何计算数组元素的地址。例如,假定A是一个1020的二维数组,各维的下限为1,每个元素占用一个机器字(令存储器是以字编址的),数组的首地址,即Al,1的地址为a,那么,数组元素Ai,j的地址为 a十(i1)20十(jl)或等价地表示成(a21)(20 i j),以行为序计算数组元素的地址,设A是一个 ALGOL n维数组 array Al1:u1,l2:u2,ln:un令di ui一1i十1,i1,2,n,a为数组的首地址,即Al1,l2,ln的地址。元素Ai1,i2,in的地址D为:D a+(i1-l
34、1)d2d3dn+(i2-l2)d3 d4dn+(in-1-ln-1)dn+(in-ln),经因子分解后得 DCONSPART VARPART其中CONSPARTaCC(l1d2+l2)d3+13)d4+ln1)dn+lnVARPART(i1d2+i2)d3+i3)d4+in1)dn+in,数组元素引用的中间代码,1.将产生两组计算数组元素地址的四元式。一组计算VARPART,并将它放在某个临时单元T中;另一组计算CONSPART,并把它放在另一个临时单元T1中。同时用TiT表示数组元素的地址。,数组元素引用的中间代码,2.对应“数组元素引用”(引用其值)和“对数组元素赋值”有两个相应的四元式
35、:“变址取数”和“变址存数”。“变址取数”的四元式是:(,T1T,_,X)即XT1T“变址存数”的四元式是:(,X1,_,T1T)即T1TX,赋值语句中数组元素的翻译,含数组元素的赋值语句的文法为:A VE V i|i,E|E E EE|(E)|V,为了产生计算VARPART的四元式序列,需要如下的语义变量和过程:elistARRAY:表示数组名在符号表中的位置,即数组名的符号表入口。elistDIM:下标的个数(数组维数)计数器。elistPLACE:记存业已形成的VARPART的中间结果单元名字在符号表中的位置,或是一个临时变量的整数码。LIMIT(ARRAY,k):这是一个函数过程,它给
36、出数组ARRAY的第k维长度dk。其中,ARRAY是数组名在符号表中的位置。,说明,每个变量V有两项语义值(属性),VPLACE和VOFFSET。若V是一个简单变量名i,则VPLACE就是指此名的符号表入口,而VOFFSET将为null。若V是一个下标变量名i,则VPLACE就是指保存CONSPART的临时变量名的整数码,而VOFFSET则指保存VARPART的临时变量名的整数码。注意,null是一个特殊值,它是区分简单变量名和下标变量名的标志。,翻译方案,(1)A VE IF(V.OFFSET=null)THEN*V是一个简单变量名*GEN(=,E.PLACE,_,V.PLACE)ELSE
37、GEN(=,E.PLACE,_,V.PLACEV.OFFSET)此处,若V是一个下标变量,那么,我们产生“变址存数”的四元式。,(2)E E1E2 TNewtemp;GEN(+,E1.PLACE,E2.PLACE,E.PLACE);(3)E(E1)EPLACEE1PLACE,(4)E V IF(VOFFSETnull)THEN*V是简单变量名*EPLACEVPLACE ELSE*V是一个下标变量名,产生“变址取数的指令*TNEWTEMP;GEN(=,V.PLACEV.OFFSET,_,T);E.PLACET,(5)V TNEWTEMP;GEN(_,elistARRAY,C,T);VPLACET
38、;VOFFSETelistPLACE 此处C是常数(d2d3dnd3dndnl)。四元式(_,elistARRAY,C,T)指把数组ARRAY的首地址a减去C。这里我们假定,通过数组名的符号表入口不仅能获得地址a而且能得到常数C。,(6)V i VPLACEENTRY(i);VOFFSETnull,(7)1,E TNEWTEMP;kelist1DIM1;dkLIMIT(elist1ARRAY,k);GEN(*,elist1PLACE,dk,T);GEN(,EPLACE,T,T);elistARRAYelist1ARRAY;elistPLACE T;elistDIMk 这里所产生的两个四元式相当
39、于执行 elist1PLACE*dkik其中ik为E,PLACE,结果值保存在T中。这是用乘、加运算累计VARPART过程。,(8)(elist)iE elistPLACEEPLACE;elistDIM1;elistARRAYENTRY(i)这里,elistARRAY指向数组名 i的符号表入口,作为指示 VARPART初值的elistPLACE,指向第一个下标式 E的结果值单元。,示例,例如,令A是一个1020的数组,即d110,d220。赋值句XAI,J的四元式序列为:(*,I,20,T1)*其中 20指d2*(,J,T1,T1)*T1为VARPART*(一,A,21,T2)*相当于T2a一C*(,T2T1,_,T3)*T3T2T1*(,T3,_,X),示例,赋值句AI十2,JIMN的四元式序列为:(+,I,2,T1)(+,J,l,T2)(*,T1,20,T3)(+,T2,T3,T3)*T3VARPART*(-,A,21,T4)*T4CONSPART*(+,M,N,T5)(,T5,_,T4T3)*T4T3T5*,本章小结,语义分析与中间代码生成的任务。弄清属性文法的概念。弄清语法制导翻译的概念。掌握常用的中间代码形式:逆波兰式和四元式。掌握一般语法成分,如赋值语句,条件语句,循环语句和简单说明语句等结构的翻译。,再见!,
链接地址:https://www.31ppt.com/p-5667640.html