




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
语义分析和中间代码生成讲义第7章
语义分析与中间代码生成7.1中间代码的形式7.2声明语句的翻译7.3赋值语句的翻译7.4类型检查7.5控制结构的翻译7.6回填7.7switch语句的翻译7.8过程调用和返回语句的翻译7.9输入输出语句的翻译7.10本章小结2023/3/1927.1中间代码的形式中间代码的作用过渡:经过语义分析被译成中间代码序列中间代码的形式中间语言的语句中间代码的优点形式简单、语义明确、独立于目标语言便于编译系统的实现、移植、代码优化常用的中间代码语法树节)逆波兰表示、三地址码(三元式和四元式)、DAG图表示2023/3/1937.1.1逆波兰表示中缀表达式的计算顺序不是运算符出现的自然顺序,而是根据运算符间的优先关系来确定的,因此,从中缀表达式直接生成目标代码一般比较麻烦。波兰逻辑学家J.Lukasiewicz于1929年提出了后缀表示法,其优点为:表达式的运算顺序就是运算符出现的顺序,它不需要使用括号来指示运算顺序。2023/3/1947.1.1逆波兰表示例7.1下面给出的是一些表达式的中缀、前缀和后缀表示。 中缀表示 前缀表示 后缀表示 a+b +ab ab+ a*(b+c) *a+bc abc+* (a+b)*(c+d) *+ab+cd ab+cd+* a:=a*b+c*d :=a+*ab*cd abc*bd*+:=2023/3/1957.1.2三地址码所谓三地址码,是指这种代码的每条指令最多只能包含三个地址,即两个操作数地址和一个结果地址。如x+y*z三地址码为:t1:=y*zt2:=x+t1三地址码中地址的形式:名字、常量、编译器生成的临时变量。2023/3/1967.1.2三地址码例7.2赋值语句a:=(-b)*(c+d)-(c+d)的三地址码如图7.1所示t1:=minusbt2:=c+dt3:=t1*t2t4:=c+dt5:=t3-t4a:=t5图7.1a:=(-b)*(c+d)-(c+d)的三地址码2023/3/1977.1.2三地址码1.形如x:=yopz的赋值指令;2.形如x:=opy的赋值指令;3.形如x:=y的复制指令;4.无条件跳转指令gotoL;5.形如ifxgotoL(或iffalsexgotoL)的条件跳转指令;6.形如ifxrelopygotoL的条件跳转指令;7.过程调用和返回使用如下的指令来实现:
paramx用来指明参数;
callp,n和y=callp,n用来表示过程调用和函数调用;
returny表示过程返回;8.形如x:=y[i]和x[i]:=y的变址复制指令;9.形如x:=&y、x:=*y和*x:=y的地址和指针赋值指令。2023/3/198四元式
四元式是一种比较常用的中间代码形式,它由四个域组成,分别称为op、arg1、arg2和result。op是一个一元或二元运算符,arg1和arg2分别是op的两个运算对象,它们可以是变量、常量或编译器生成的临时变量,运算结果则放入result中。图7.2(a)图7.1中三地址码的四元式表示2023/3/199三元式
为了节省临时变量的开销,有时也可以使用只有三个域的三元式来表示三地址码。三元式的三个域分别称为op,arg1和arg2,op,arg1和arg2的含义与四元式类似,区别只是arg1和arg2可以是某个三元式的编号(图7.2(b)中用圆括号括起来的数字),表示用该三元式的运算结果作为运算对象。图7.2(b)图7.1中三地址码的三元式表示2023/3/1910生成三地址码的语法制导定义2023/3/19117.1.3图表示类似于表达式的抽象语法树一样,在dag(directedacyclicgraph)中,每个节点对应一个运算符,代表表达式的一个子表达式,其子节点则与该运算符的运算对象相对应,叶节点对应的是变量或者常量,可以看成是原子运算。利用dag可以很容易地消除公共子表达式例7.3表达式a+a*(b-c)-(b-c)/d的dag如图7.5所示。图7.5a+a*(b-c)-(b-c)/d的dag图2023/3/1912生成dag的语法制导定义产生式语义规则⑴
E→E1+TE.node:=mknode('+',E1.node,T.node)⑵
E→E1-TE.node:=mknode('-',E1.node,T.node)⑶
E→TE.node:=T.node⑷
T→T1*FT.node:=mknode('*',T1.node,F.node)⑸
T→T1/FT.node:=mknode('/',T1.node,F.node)⑹
T→FT.node:=F.node⑺F→(E)F.node:=E.node⑻F→idF.node:=mkleaf(id,id.entry)⑼F→numF.node:=mkleaf(num,num.val)2023/3/19137.2声明语句的翻译声明语句的作用为程序中用到的变量或常量名指定类型类型的作用类型检查:类型检查的任务是验证程序运行时的行为是否遵守语言的类型的规定,也就是是否符合该语言关于类型的相关规则。辅助翻译:编译器从名字的类型可以确定该名字在运行时所需要的存储空间。在计算数组引用的地址、加入显式的类型转换、选择正确版本的算术运算符以及其它一些翻译工作时同样需要用到类型信息。编译的任务在符号表中记录被说明对象的属性(种别、类型、相对地址、作用域……等),为执行做准备2023/3/19147.2.1类型表达式类型可以具有一定的层次结构,因此用类型表达式来表示。类型表达式的定义如下:1.基本类型是类型表达式。 典型的基本类型包括boolean、char、integer、real及void等。2.类型名是类型表达式。3.将类型构造符array应用于数字和类型表达式所形成的表达式是类型表达式。 如果T是类型表达式,那么array(I,T)就是元素类型为T、下标集为I的数组类型表达式。4.如果T1和T2是类型表达式,则其笛卡尔乘积T1×T2也是类型表达式。2023/3/19157.2.1类型表达式5.类型构造符record作用于由域名和域类型所形成的表达式也是类型表达式。记录record是一种带有命名域的数据结构,可以用来构成类型表达式。例如,下面是一段Pascal程序段:typerow=recordaddress:integer;lexeme:array[1..15]ofcharend;vartable:array[1..10]ofrow;该程序段声明了表示下列类型表达式的类型名row:record((address×integer)×(lexeme×array(1..15,char)))2023/3/19167.2.1类型表达式6.如果T是类型表达式,那么pointer(T)也是类型表达式,表示“指向类型为T的对象的指针”。函数的类型可以用类型表达式D→R来表示。考虑如下的Pascal声明:functionf(a,b:char):↑integer;其定义域类型为char×char,值域类型为pointer(integer)。所以函数f的类型可以表示为如下的类型表达式:char×char→pointer(integer)7.类型表达式可以包含其值为类型表达式的变量。2023/3/19177.2.2类型等价许多类型检查的规则都具有如下的形式:if两个类型表达式等价then返回一种特定类型else返回type_error。如果用图来表示类型表达式,当且仅当下列条件之一成立时,称两个类型T1和T2是结构等价的:T1和T2是相同的基本类型;T1和T2是将同一类型构造符应用于结构等价的类型上形成的;T1是表示T2的类型名。如果将类型名看作只代表它们自己的话,则上述条件中的前两个将导致类型表达式的名字等价两个类型表达式名字等价当且仅当它们完全相同2023/3/19187.2.3声明语句的文法P→progid(input,output)D;SD→D;D|List:T|procidD;SList→List1,id|idT→integer|real|arrayCofT1|T1|recordDC→[num]C|ε
D——程序说明部分的抽象S——程序体部分的抽象T——类型的抽象,需要表示成类型表达式C——数组下标的抽象2023/3/1919语义属性、辅助过程与全局变量的设置文法变量T(类型)的语义属性type:类型(表达式)width:类型所占用的字节数辅助子程序enter:将变量的类型和地址填入符号表中array:数组类型处理子程序全局变量offset:已分配空间字节数,用于计算相对地址2023/3/19207.2.4过程内声明语句的翻译P→{offset:=0}DD→D;DD→id:T{enter(,T.type,offset);offset:=offset+T.width}T→integer{T.type:=integer;T.width:=4}T→real{T.type:=real;T.width:=8}T→array[num]ofT1
{T.type:=array(num.val,T1.type);T.width:=num.val*T1.width}T→↑T1{T.type:=pointer(T1.type);T.width:=4}P→MDM→{offset:=0}2023/3/1921例x:real;i:integer的翻译enter(x,real,0)offset=0offset=8T.type=realT.width=8offset=12T.type=integerT.width=4enter(i,integer,8)D→id:T{enter(,T.type,offset);offset:=offset+T.width}2023/3/1922例x:real;i:integer的翻译P{offset:=0}D{offset:=0}D;D{offset:=0}x:T{enter(x,T.type,offset);offset:=offset+T.width};D{offset:=0}x:real{T.type:=real;T.width:=8}{enter(x,T.type,offset);offset:=offset+T.width};Dx:real{(x,real,0);offset:=8};Dx:real{(x,real,0);offset:=8};i:T{enter(,T.type,offset);offset:=offset+T.width}x:real{(x,real,0);offset:=8};i:integer{T.type:=integer;T.width:=4}{enter(i,T.type,offset);offset:=offset+T.width}x:real{(x,real,0)};i:integer{(i,integer,8);offset:=12}2023/3/19237.2.5嵌套过程中声明语句的翻译所讨论语言的文法
Pprogid(input,output)D;S
DD;D|id:T|procidD;S
语义动作用到的函数mktable(previous):创建一个新的符号表;enter(table,name,type,offset)addwidth(table,width):符号表的大小;enterproc(table,name,newtable)
在table指向的符号表中为name建立一个新表项;2023/3/1924Pprogid(input,output)MD;S{addwidth(top(tblptr),top(offset));pop(tblptr);pop(offset)}M
{t:=mktable(nil); push(t,tblptr);push(0,offset)}DD1;D2Dprocid;ND1;S{t:=top(tblptr);addwidth(t,top(offset));pop(tblptr);pop(offset); enterproc(top(tblptr),,t)}Did:T{enter(top(tblptr),,T.type,top(offset)); top(offset):=top(offset)+T.width}N
{t:=mktable(top(tblptr)); push(t,tblptr);push(0,offset)}7.2.5嵌套过程中声明语句的翻译2023/3/1925programsort(input,output); vara:array[0..10]ofinteger;x:integer;procedurereadarray; vari:integer;begin…a…end;
procedureexchange(i,j:integer); beginx:=a[i];a[i]:=a[j];a[j]:=x;end;
procedurequicksort(m,n:integer); vark,v:integer; functionpartition(y,z:integer):integer; vari,j:integer; begin…a… …v……exchange(i,j)…end; begin…end;
begin…end;例一个带有嵌套的pascal程序(图7.11)2023/3/1926表头空sortoffsettblptrtoptop02023/3/1927表头空sortoffsettblptrtoptop40aarray02023/3/1928xinteger40aarray0表头空sortoffsettblptrtoptop442023/3/1929表头空sortreadarrary表头offsettblptrtoptop440aarray0xinteger402023/3/1930表头空sortreadarrary表头offsettblptrtoptop444aarray0xinteger40iinteger02023/3/1931表头空sortreadarrary表头4offsettblptrtoptop44aarray0xinteger40iinteger0readarray指向readarray2023/3/1932表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头toptop02023/3/1933表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange2023/3/1934表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头quicksort02023/3/1935表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头quicksort4kinteger02023/3/1936表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头quicksort8kinteger0vinteger42023/3/1937表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头quicksort8kinteger0vinteger4表头partition02023/3/1938表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头quicksort8kinteger0vinteger4表头partition4iinteger02023/3/1939表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头quicksort8kinteger0vinteger4表头partition8iinteger0jinteger42023/3/1940表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头quicksort8kinteger0vinteger4表头8partitioniinteger0jinteger4partition2023/3/1941表头空sortreadarrary表头4offsettblptr44aarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头8quicksortkinteger0vinteger4表头8partitioniinteger0jinteger4partitionquicksort2023/3/1942表头44空sortreadarrary表头4offsettblptraarray0xinteger40iinteger0readarray指向readarrayexchange表头0toptopexchange指向exchange表头8quicksortkinteger0vinteger4表头8partitioniinteger0jinteger4partitionquicksort2023/3/19437.2.6记录的翻译空间分配设置首地址和各元素的相对地址大于所需的空间(对齐)例:structNode{floatx,y;structnode*next;}node;0482023/3/19447.2.6记录的翻译符号表及有关表格处理为每个记录类型单独构造一张符号表将域名id的信息(名字、类型、字节数)填入到该记录的符号表中所有域都处理完后,offset将保存记录中所有数据对象的宽度总和T.type通过将类型构造器record应用于指向该记录符号表的指针获得2023/3/19457.2.6记录的翻译TrecordDendTrecordLDend {T.type:=record(top(tblptr)); T.width:=top(offset); pop(tblptr);pop(offset)}L
{t:=mktable(nil); push(t,tblprt);push(0,offset)}2023/3/19467.3赋值语句的翻译翻译的需求充分了解各种语言现象的语义包括:控制结构、数据结构、单词充分了解它们的实现方法目标语言的语义了解中间代码的语义了解运行环境2023/3/1947辅助子程序与语义属性设置辅助子程序gencode(code),emit(code):产生一条中间代码newtemp:产生新的临时变量lookup:检查符号表中是否出现某名字语义属性设置中间代码序列:code地址:addr下一条四元式序号:nextquad2023/3/19487.3.1简单赋值语句的翻译Sid:=E {p:=lookup(); ifpnilthen gencode(p,‘:=’,E.addr) elseerror}EE1+E2 {E.addr:=newtemp; emit(E.addr,‘:=’,E1.addr,‘+’,E2.addr)}E
E1{E.addr:=newtemp; emit(E.addr,‘:=’,‘uminus’,E1.addr)}E(E1){E.addr:=E1.addr}Eid{p:=lookup(); ifpnilthenE.addr:=pelseerror}2023/3/1949临时名字的重用大量临时变量的使用对优化有利大量临时变量会增加符号表管理的负担也会增加运行时临时数据占的空间EE1+E2的动作产生的代码的一般形式为 计算E1到t1
计算E2到t2 t3:=t1+t2 (())((()())())临时变量的生存期像配对括号那样嵌套或并列2023/3/1950基于临时变量生存期特征的三地址代码x:=ab+cdef语句计数器c的值0$0:=ab1$1:=cd2$0:=$0+$11$1:=ef2$0:=$0$11x:=$00引入一个计数器c,它的初值为0。每当临时变量仅作为运算对象使用时,c减去1;每当要求产生新的临时名字时,使用$c并把c增加1。2023/3/19517.3.2数组元素的寻址数组元素引用的翻译完成上下界检查生成完成相对地址计算的代码目标x:=y[i]和y[i]:=xy为数组地址的固定部分——相当于第1个元素的地址,i是相对地址,不是数组下标数组说明的翻译符号表及有关表格(内情向量)的处理维数、下标上界、下标下界、类型等首地址、需用空间计算按行存放、按列存放——影响具体元素地址的计算2023/3/1952数组元素地址计算——行优先一维数组A[low1:up1](nk=upk-lowk+1)addr(A[i])=base+(i-low1)*w =(base-low1*w)+i*w=c+i*w二维数组A[low1:up1,low2:up2];A[i1,i2]addr(A[i1,i2])=base+((i1-low1)*n2+(i2-low2))*w =base+(i1-low1)*n2*w+(i2-low2)*w =base-low1*n2*w-low2*w+i1*n2*w+i2*w =base-(low1*n2-low2)*w+(i1*n2+i2)*w =c+(i1*n2+i2)*wA[1,1],A[1,2],A[1,3]A[2,1],A[2,2],A[2,3]2023/3/1953数组元素地址计算的翻译方案设计下标变量访问的产生式
Lid[Elist]|id ElistElist,E|E为了使数组各维的长度n在我们将下标表达式合并到Elist时是可用的,需将产生式改写为:
LElist]|id ElistElist,E|id[E2023/3/1954数组元素地址计算的翻译方案设计LElist]|idElistElist,E|id[E目的使我们在整个下标表达式列表Elist的翻译过程中随时都能知道符号表中相应于数组名id的表项,从而能够了解登记在符号表中的有关数组id的全部信息。于是我们就可以为非终结符Elist引进一个综合属性Elist.array,用来记录指向符号表中相应数组名字表项的指针。2023/3/1955数组元素地址计算的翻译方案设计属性Elist.array,用来记录指向符号表中相应数组名字表项的指针。Elist.ndim,用来记录Elist中下标表达式的个数,即数组的维数。Elist.addr,用来临时存放Elist的下标表达式计算出来的值。函数limit(array,j),返回nj2023/3/19567.3.3带有数组引用的赋值语句的翻译SLeft:=EEE+EE(E)ELeftLeftElist]LeftidElistElist,EElistid[E2023/3/1957赋值语句的翻译模式Leftid{Left.addr:=id.addr;Left.offset:=null}Elistid[E{Elist.addr:=E.addr;Elist.ndim:=1; Elist.array:=id.addr}ElistElist1,E{t:=newtemp;m:=Elist1.ndim+1;gencode(t,‘:=’,Elist1.addr,‘’,limit(Elist1.array,m));gencode(t,‘:=’,t,‘+’,E.addr);Elist.array:=Elist1.array;Elist.addr:=t;Elist.ndim:=m}LeftElist] {Left.addr:=newtemp;Left.offset:=newtemp;gencode(Left.addr,‘:=’,base(Elist.array),‘’,invariant(Elist.array));gencode(Left.offset,‘:=’,Elist.addr,‘’,w)}i1*n2(i1*n2)+i2((i1*n2)+i2)*wbase-(low1*n2-low2)*w2023/3/1958赋值语句的翻译模式ELeft{ifLeft.offset=nullthen/Left是简单变量/ E.addr:=Left.addr elsebeginE.addr:=newtemp; gencode(E.addr,‘:=’,Left.addr,‘[’,Left.offset,‘]’)end}EE1+E2{E.addr:=newtemp; gencode(E.addr,‘:=’,E1.place,‘+’,E2.addr)}E(E1){E.addr:=E1.addr}SLeft:=E{ifLeft.offset=nullthen/Left是简单变量/ gencode(Left.addr,‘:=’,E.addr) else gencode(Left.addr,‘[’,Left.offset,‘]’,‘:=’,E.addr)}((i1*n2)+i2)*w+(base-(low1*n2-low2)*w)((i1*n2)+i2)*w+(base-(low1*n2-low2)*w)2023/3/1959例:设A是一个10×20的整型数组
——w=4
S:=Left.place:=xLeft.offset:=nullxE.addr:=t4Left.addr:=t2Left.offset:=t3Elist.addr:=t1Elist.ndim:=2Elist.array:=A,Elist.addr:=yElist.ndim:=1Elist.array:=AE.addr:=zLeft.addr:=zLeft.offset:=nullE.addr:=yLeft.addr:=yLeft.offset:=nullA[z]y
x:=A[y,z]的注释分析树2023/3/1960例S:=Left.addr:=xLeft.offset:=nullxE.addr:=t4Left.addr:=t2Left.offset:=t3Elist.addr:=t1Elist.ndim:=2Elist.array:=A,Elist.addr:=yElist.ndim:=1Elist.array:=AE.addr:=zLeft.addr:=zLeft.offset:=nullE.addr:=yLeft.addr:=yLeft.offset:=nullA[z]y
x:=A[y,z]的注释分析树t1:=y20t1:=t1+z2023/3/1961例S:=Left.addr:=xLeft.offset:=nullxE.addr:=t4Left.addr:=t2Left.offset:=t3Elist.addr:=t1Elist.ndim:=2Elist.array:=A,Elist.addr:=yElist.ndim:=1Elist.array:=AE.addr:=zLeft.addr:=zLeft.offset:=nullE.addr:=yLeft.addr:=yLeft.offset:=nullA[z]yx:=A[y,z]的注释分析树t1:=y20t1:=t1+zt2:=baseA84t3:=4t1
2023/3/1962例S:=Left.addr:=xLeft.offset:=nullxE.addr:=t4Left.addr:=t2Left.offset:=t3Elist.addr:=t1Elist.ndim:=2Elist.array:=A,Elist.addr:=yElist.ndim:=1Elist.array:=AE.addr:=zLeft.addr:=zLeft.offset:=nullE.addr:=yLeft.addr:=yLeft.offset:=nullA[z]y
x:=A[y,z]的注释分析树t1:=y20t1:=t1+zt4:=t2[t3]t2:=baseA84t3:=4t1
2023/3/1963例S:=Left.addr:=xLeft.offset:=nullxE.addr:=t4Left.addr:=t2Left.offset:=t3Elist.addr:=t1Elist.ndim:=2Elist.array:=A,Elist.addr:=yElist.ndim:=1Elist.array:=AE.addr:=zLeft.addr:=zLeft.offset:=nullE.addr:=yLeft.addr:=yLeft.offset:=nullA[z]yx:=A[y,z]的注释分析树t1:=y20t1:=t1+zt4:=t2[t3]x:=t4
t2:=baseA84t3:=4t1
2023/3/19647.4类型检查类型检查具有发现程序错误的能力,为了进行类型检查,编译程序需要为源程序的每个语法成分赋予一个类型表达式,名字的类型表达式保存在符号表中,其他语法成分(如表达式E或语句S)的类型表达式则作为文法符号的属性保存在语义栈中。类型检查的任务就是确定这些类型表达式是否符合一定的规则,这些规则的集合通常称为源程序的类型系统2023/3/19657.4.1类型检查的规则类型综合从子表达式的类型确定表达式的类型要求名字在引用之前必须先进行声明iff的类型为s→tandx的类型为sthen表达式f(x)的类型为t
类型推断根据语言结构的使用方式来确定其类型经常被用于从函数体推断函数类型iff(x)是一个表达式then对某两个类型变量α和β,f具有类型→βandx具有类型
2023/3/19667.4.2类型转换x:=y+ij(x和y的类型是real,i和j的类型是integer)中间代码t1:=iintjt2:=inttorealt1
t3:=yreal+t2
x:=t32023/3/19677.4.2类型转换EE1+E2的语义子程序{E.addr:=newtempifE1.type=integerandE2.type=integerthenbegin gencode(E.addr,‘:=’,E1.addr,‘int+’,E2.addr); E.type=integerendelseifE1.type=integerandE2.type=realthenbegin u:=newtemp; gencode(u,‘:=’,‘inttoreal’,E1.addr); gencode(E.addr,‘:=’,u,‘real+’,E2.addr); E.type:=realend...}2023/3/19687.5控制结构的翻译高级语言的控制结构顺序结构begin语句;…;语句end分支结构if_then_else、if_then switch、case循环结构while_do、do_whilefor、repeat_untilgoto语句三地址码goton (j,_,_,n)ifxrelopygoton (jrelop,x,y,n)2023/3/19697.5.1布尔表达式的翻译基本文法BB1orB2|B1andB2|notB1|(B1)|E1relopE2|true|false处理方式数值表示法(与算术表达式的处理类似)真:B.addr=1假:B.addr=0真假出口表示法(作为其他语句的条件改变控制流程,隐含着程序中的位置)真出口:B.true假出口:B.false2023/3/19707.5.1布尔表达式的翻译aorbandnotct1:=notct2:=bandt1t3:=aort2a<b100:ifa<bgoto103101:t:=0102:goto104103:t:=11042023/3/1971用数值表示布尔值的翻译nextquad是下一条三地址码指令的序号,每生成一条三地址码指令gencode便会将nextquad加1BB1orB2{B.addr:=newtemp;gencode(B.addr':='B1.addr‘or'B2.addr)}BB1andB2{B.addr:=newtemp;gencode(B.addr':='B1.addr‘and'B2.addr)}BnotB1{B.addr:=newtemp; gencode(B.addr':=''not'B1.addr)}2023/3/1972用数值表示布尔值的翻译B(B1){B.addr:=B1.addr}BE1relopE2{B.addr:=newtemp;gencode('if‘E1.addrrelop.opE2.addr'goto'nextquad+3); gencode(B.addr':=''0');gencode('goto'nextquad+2); gencode(B.addr':=''1')}Btrue{B.addr:=newtemp;gencode(B.addr':=''1')}Bfalse{B.addr:=newtemp;gencode(B.addr':=''0')}2023/3/1973例7.8对a<borc<dande<f的翻译100:ifa<bgoto103 107:t2:=1101:t1:=0 108:ife<fgoto111102:goto104 109:t3:=0103:t1:=1 110:goto112104:ifc<dgoto107 111:t3:=1105:t2:=0 112:t4:=t2andt3106:goto108 113:t5:=t1ort42023/3/19747.5.2常见控制结构的翻译文法S→ifBthenS1S→ifBthenS1elseS2S→whileBdoS1S→beginSlistendSlist→Slist;S|SB是控制结构中的布尔表达式函数newlabel返回一个新的语句标号属性B.true和B.false分别用于保存B为真和假时控制流要转向的语句标号2023/3/19757.5.2常见控制结构的翻译翻译S时允许控制从S.code中跳转到紧接在S.code之后的那条三地址码指令,但在某些情况下,紧跟S.code的指令是跳转到某个标号L的跳转指令,用继承属性S.next可以避免从S.code中跳转到一条跳转指令这样的连续跳转。S.next的值是一个语句标号,它是S的代码执行后应执行的第一个三地址码指令的标号。while语句中用S.begin保存语句的开始位置
2023/3/19767.5.2常见控制结构的翻译B.codeS1.codeB.true:...指向B.true指向B.false(a)if-thenB.codeS1.codeB.true:...指向B.true指向B.falseB.false:gotoS.nextS2.code(b)if-then-elseB.codeS1.codeB.true:...指向B.true指向B.falsegotoS.beginS.begin:(c)while-doS1.codeS2.codeS1.next:...(d)S1;S2图7.25if-then、if-then-else和while-do语句的目标代码结构2023/3/19777.5.2常见控制结构的翻译SifBthenS1{B.true:=newlabel;B.false:=S.next;S1.next:=S.next;S.code:=B.code||gencode(B.true,‘:’)||S1.code}B.codeS1.codeB.true:...指向B.true指向B.false(a)if-then2023/3/19787.5.2常见控制结构的翻译SifBthenS1elseS2{B.true:=newlabel;B.false:=newlabel;S1.next:=S.next;S2.next:=S.next;S.code:=B.code||gencode(B.true,‘:’)||S1.code||gencode(‘goto’,S.next)||gen(B.false,‘:’)||S2.code}B.codeS1.codeB.true:...指向B.true指向B.falseB.false:gotoS.nextS2.code(b)if-then-else2023/3/19797.5.2常见控制结构的翻译SwhileBdoS1
{S.begin:=newlabel;B.true:=newlabel;B.false:=S.next;S1.next:=S.begin;S.code:=gencode(S.begin,‘:’)||B.code||gencode(B.true,‘:’)||S1.code||gencode(‘goto’,S.begin)}B.codeS1.codeB.true:...指向B.true指向B.falsegotoS.beginS.begin:(c)while-do2023/3/19807.5.2常见控制结构的翻译SS1;S2{S1.next:=newlabel;S2.next:=S.next;S.code:=S1.code||gencode(S1.next,‘:’)||S2.code}S1.codeS2.codeS1.next:...(d)S1;S22023/3/19817.5.3布尔表达式的控制流翻译属性(继承属性)B.true,B为真时控制到达的位置;B.false,B为假时控制到达的位置。a<bifa<bgotoB.truegotoB.falseB→B1orB2如果B1为真,则立即可知B为真,即B1.true与B.true相同;如果B1为假,则必须计算B2的值,令B1.false为B2的开始B2的真假出口分别与B的真假出口相同2023/3/1982简单布尔表达式的翻译示例
——例7.9a<borc<dande<fifa<bgotoLtruegotoL1L1:ifc<dgotoL2gotoLfalseL2:ife<fgotoLtruegotoLfalse2023/3/19837.5.3布尔表达式的控制流翻译BB1orB2{B1.true:=B.true;B1.false:=newlabel; B2.true=B.true;B2.false:=B.false;B.code:=B1.code||gencode(B1.false’:’)||B2.code}BB1andB2{B1.true:=newlabel;B1.false:=B.false;B2.true=B.true;B2.false:=B.false;B.code:=B1.code||gencode(B1.true’:’)||B2.code}BnotB1{B1.true:=B.false;B1.false:=B.true;
B.code:=B1.code}2023/3/19847.5.3布尔表达式的控制流翻译B(B1){B1.true:=B.
true;B1.false:=B.false;
B.code:=B1.code}BE1relopE2{B.code:=gencode(‘if’E1.addrrelopE2.addr‘goto’B.true);
||gencode('goto'B.false)}Btrue{B.code:=gencode('goto'B.true)}Bfalse{B.code:=gencode('goto'B.false)}2023/3/1985例7.10:翻译下列语句whilea<bdo B1ifc<dthen B2S1x:=y+zelseS2x:=y-zS32023/3/1986生成的三地址代码序列L1:ifa<bgotoL2gotoLnextL2:ifc<dgotoL3gotoL4L3:t1:=y+zx:=t1
gotoL1L4:t2:=y-zx:=t2gotoL1Lnext:B1.codeB2.codeS1.codeS2.codeS3.codewhilea<bdoifc<dthenx:=y+zelsex:=y-z2023/3/19877.5.4混合模式的布尔表达式翻译EE1relopE2│E1+E2│E1andE2│idE1+E2、id产生算术结果E1relopE2、E1andE2产生布尔值E1andE2:E1和E2必须都是布尔型的引入语义属性E.type:arith或者boolE.true,E.falseE.addr2023/3/19887.5.4混合模式的布尔表达式翻译EE1relopE2{E.code:=E1.code||E2.code||gencode(‘if’E1.addrrelopE2.addr‘goto‘E.true)||
gencode('goto'E.false)}2023/3/1989混合模式的布尔表达式翻译EE1+E2{E.type:=arith;ifE1.type=arithandE2.type=ariththenbeginE.addr:=newtemp;E.code:=E1.code||E2.code||gencode(E.addr'='E1.addr'+'E2.addr)endelseifE1.type=arithandE2.type=boolthenbeginE.addr:=newtemp;E2.true:=newlabel;2.false:=newlabel;E.code:=E1.code||E2.code||gencode(E2.true':'E.addr':='E1.addr+1)||gencode('goto'nextstate+2)||gencode(E2.false':'E.addr':='E1.addr)elseif…….}2023/3/1990混合模式布尔表达式的翻译示例
——例如:4+a>b-canddt1=4+at2=b-cift1>t2gotoL1gotoLfalseL1:ifdgotoLtruegotoLfalse2023/3/19917.6回填两遍扫描从给定的输入构造出一棵语法树;对语法树按深度优先进行遍历,在遍历过程中执行语法制导定义中给出的翻译动作
效率较低2023/3/19927.6回填一遍扫描问题:生成跳转语句时可能不知道要转向指令的标号先产生暂时没有填写目标标号的转移指令 对于每一条这样的指令作适当的记录,建一个链表一旦确定了目标标号,再将它“回填”到相应的指令中E.truelistE.falselist2023/3/19937.6回填翻译模式用到如下三个函数:
1.makelist(i):创建一个只包含i的新表,i
是四元式数组的一个索引(下标),或者说
i是四元式代码序列的一个标号。
2.merge(p1,p2):合并由指针p1和p2指向的两个表并且返回一个指向合并后的表的指针。
3.backpatch(p,i):把i作为目标标号回填到
p所指向的表中的每一个转移指令中去。此处的“表”都是为“回填”所拉的链2023/3/19947.6.1布尔表达式的回填式翻译BB1orMB2{backpatch(B1.falselist,M.quad);B.truelist:=merge(B1.truelist,B2.truelist);B.falselist:=B2.falselist}M
ε{M.quad:=nextquad}B1的代码B.falselistB1.falselistB2.falselistB2的代码M.quadB1.truelistB2.truelistB.truelistor2023/3/19957.6.1布尔表达式的回填式翻译BB1andMB2{backpatch(B1.truelist,M.quad);B.truelist:=B2.truelist;
B.falselist:=merge(B1.falselist,B2.falselist);}B1的代码B.truelistB1.truelistB2.truelistB2的代码M.quadB1.falselistB2.falselistB.falselistand2023/3/19967.6.1布尔表达式的回填式翻译BnotB1{B.truelist:=B1.falselist;B.falselist:=B1.truelist;}B(B1){B.truelist:=B1.truelist;B.falselist:=B1.falselist;}2023/3/19977.6.1布尔表达式的回填式翻译BE1relopE2{B.truelist:=makelist(nextquad);B.falselist:=makelist(nextquad+1);gencode(‘if’E1.addrrelopE2.addr‘goto-’);gencode(‘goto-’)}2023/3/19987.6.1布尔表达式的回填式翻译Btrue{B.truelist:=makelist(nextquad);gencode(‘goto-’)}Bfalse{B.falselist:=makelist(nextquad);gencode(‘goto-’)}2023/3/1999例7.11B.t={100,104}B.f={103,105}M.q:={102}B.t:={100}B.f:={101}<B.t={104}B.f={103,105}B.t={102}B.f={103}B.t={104}B.f={105}图7.27a<borc<dande<f的注释分析树aborεM.q:={104}andε<cd<ef100:ifa<bgoto–101:goto-102:ifc<dgoto104103:goto–104:ife<fgoto–105:goto-100:ifa<bgoto–101:goto-102:ifc<dgoto–103:goto-104:ife<fgoto–105:goto-100:ifa<bgoto–101:goto102102:ifc<dgoto104103:goto–104:ife<fgoto–105:goto-M.q:={102}M.q:={104}B.t代表B.truelistB.f代表B.falselistM.q代表M.quad2023/3/191007.6.2常见控制结构的回填式翻译SifBthenMS1 |ifBthenM1S1NelseM2S2 |whileM1BdoM2S1 |S1;MS2
Mε{M.qu
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 模具设计师资格认证考试万无一失试题及答案
- 2024年农作物种子繁育员考试的闭卷复习试题及答案
- 2024模具设计师考试模拟试题及答案
- 2024年农业植保员考试解析与试题及答案
- 准备2024年游泳救生员考试的资料与试题及答案
- 2024年体育经纪人考试工具手册试题及答案
- 2024年职业能力测试体育经纪人试题及答案
- 深入分析农作物种子供给链的试题及答案
- 2024年游泳救生员考试的有用工具试题及答案
- 2024年湖北省考公务员考试村干部定向岗结构化面试真题试题试卷答案解析
- 煤矿标准成本消耗定额(定额装订版)
- 《骑鹅旅行记》阅读题(有答案,内容全)
- 【越南】环境保护法
- 《C语言程序设计》教案(清华谭浩强)
- ●粘度对离心泵性能影响最新标准初析及粘液泵选型经验
- 环己烷安全周知卡-原料
- 三宝证盟荐亡往生功德文疏
- YY∕T 1849-2022 重组胶原蛋白
- 行政管理工作流程优化方案
- 鼓式制动器毕业设计
- 医院内部医疗废物收集运送流程图
评论
0/150
提交评论