收藏 分享(赏)

第8章 语法制导翻译和中间代码生成.ppt

上传人:dcjskn 文档编号:4665185 上传时间:2019-01-06 格式:PPT 页数:67 大小:1.39MB
下载 相关 举报
第8章 语法制导翻译和中间代码生成.ppt_第1页
第1页 / 共67页
第8章 语法制导翻译和中间代码生成.ppt_第2页
第2页 / 共67页
第8章 语法制导翻译和中间代码生成.ppt_第3页
第3页 / 共67页
第8章 语法制导翻译和中间代码生成.ppt_第4页
第4页 / 共67页
第8章 语法制导翻译和中间代码生成.ppt_第5页
第5页 / 共67页
点击查看更多>>
资源描述

1、属性文法与属性翻译文法常见中间语言概述简单算术表达式和赋值语句的翻译布尔表达式的翻译程序流控制语句的翻译说明语句的翻译,第8章 语法制导翻译和中间代码生成,8.1 概述,1. 语义分析的概念一个源程序经过词法分析、语法分析之后,表明该源程序在书写上是正确的,并且符合程序语言所规定的语法。但是语法分析并未对程序内部的逻辑含义加以分析,因此编译程序接下来的工作是语义分析,即审查每个语法成分的静态语义。若静态语义正确,则生成与该语言成分等效的中间代码,或者直接生成目标代码。,直接生成机器语言或汇编语言形式的目标代码 优点:编译时间短且无需中间代码到目标代码的翻译。 中间代码的优点使编译结构在逻辑上更

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

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

4、程中,当一个产生式获得匹配(对于自上而下分析)或用于归约(对于自下而上分析)时,此产生式相应的语义子程序就进入工作,完成既定的翻译任务。,语法制导翻译分为自下而上语法制导翻译和自上而下语法制导翻译。本章重点介绍自下而上语法制导翻译。假定有一个自下而上的LR分析器,可以把这个LR分析器的能力加以扩大,使它能在用某个产生式进行归约的同时调用相应的语义子程序进行有关的翻译工作;每个产生式的语义子程序执行之后,某些结果(语义信息)必须作为此产生式的左部符号的语义值暂时保存下来,以便以后语义子程序引用这些信息。,此外,原LR分析器的分析栈也加以扩充,以便能够存放与文法符号相对应的语义值。这样,分析栈可以

5、存放三类信息:分析状态、文法符号及文法符号对应的语义值。扩充后的分析栈如图5.1所示。考查下面的文法及语义动作所执行的程序:,图5.1 扩充后的LR分析栈,产生式 语义动作 (0) SE print valTOP (1) EE(1)+E(2) valTOP=valTOP+valTOP+2 (2) EE(1)*E(2) valTOP=valTOP*valTOP+2 (3) E(E(1) valTOP= valTOP+1 (4) Ei valTOP=lexval (注:lexval为i的整型内部值) 这个文法的LR分析见表5.1。,扩充分析栈工作的总控程序功能在完成语法分析的同时也能完成语义分析工

6、作(这时的语法分析栈已成为语义分析栈);即在用某一个规则进行归约之后,调用相应的语义子程序完成与所用产生式相应的语义动作。将每次工作后的语义值保存在扩充后的“语义值”栈中。图5.2表示算术表达式79*5#的语法树及各结点值。表5.1则给出了用LR语法制导翻译方法得到的该表达式的语义分析和计值过程。,图5.2 语法制导翻译计算表达式79*5#的语法树,表5.1 表达式79*5#的语义分析和计值过程,5.2 属性文法与属性翻译文法,5.2.1 语义属性与属性文法属性是指与文法符号的类型和值等有关的一些信息,在编译中用属性描述处理对象的特征。随着编译的进展,对语法分析产生的语法树进行语义分析,且分析

7、的结果用中间代码描述出来。对于一棵等待翻译的语法树,它的各个结点都是文法中的一个符号X,该X可以是终结符或非终结符。根据语义处理的需要,在用产生式AX进行归约或推导时,应能准确而恰当地表达文法符号X在归约或推导时的不同特征。,例如:判断变量X的类型是否匹配,要用X的数据类型来描述;判断变量X是否存在,要用X的存储位置来描述;而对X的运算,则要用X的值来描述。因此,语义分析阶段引入X的属性,如X.type、X.place、X.val等来分别描述变量X的类型、存储位置以及值等不同的特征。,文法符号的属性:继承属性与综合属性两类。(1)继承属性用于“自上而下”传递信息继承属性由相应语法树中结点的父结

8、点属性计算得到,即沿语法树向下传递,由根结点到分枝(子)结点;继承属性反映了对上下文依赖的特性。继承属性可以很方便地用来表示程序语言上下文的结构关系。,(2)综合属性用于“自下而上”传递信息综合属性由相应语法分析树中结点的分枝结点(即子结点)属性计算得到,其传递方向与继承属性相反,即沿语法分析树向上传递,从分枝结点到根结点。,5.2.2 属性翻译文法属性文法是一种适用于定义语义的特殊文法,即在语言的文法中增加了属性的文法,它将文法符号的语义以“属性”的形式附加到各个文法的符号上(如上述与变量X相关联的属性X.type、X.place和X.val等),再根据产生式所包含的含义,给出每个文法符号属

9、性的求值规则,从而形成一种带有语义属性的上下文无关文法,即属性文法。属性文法也是一种翻译文法,属性有助于更详细地指定文法中的代码生成动作。,例如,简单算术表达式求值的属性文法如下:产生式 语义规则(1) SE print (E.val)(2) EE(1)+T E.val=E(1).val+T.val(3) ET E.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) Fi F.val=i.lexval,与产生式关联的每一个语义规则的左部符号E、T、F等的属性值的计算由其

10、各自相应的右部符号决定,这种属性也称为综合属性。与产生式SE关联的语义规则是一个函数print(E.val),其功能是打印E产生式的值。S在语义规则中没有出现,可以理解为其属性是一个虚属性。另一说明属性文法例:一简单变量类型说明的文法如下: GD:Dint Lfloat LLL, idid,注意到与文法GD相应的说明语句形式可为 int id1,id2,,idn 或者 float id1,id2,,idn 其对应的属性文法为:产生式 语义规则(1) DTL L.in=T.type(2) Tint T.type=int(3) Tfloat T.type=float(4) LL(1),id L(1

11、).in=L.in; addtype(id.entry,L.in)(5) Lid addtype(id.entry,L.in),非终结符T有一个综合属性type,其值为int或float。语义规则L.in=T.type表示L.in的属性值由相应说明语句指定的类型T.type决定;属性L.in被确定后将随语法树的逐步生成而传递到下边的有关结点使用,这种结点属性称为继承属性。由此可见,标识符的类型可以通过继承属性的复写规则来传递。,图5.3 属性信息传递情况示意,例如,对输入串int a,b,根据上述的语义规则,可在其生成的语法树中看到用“”表示的属性传递情况,如图所示。,3*5+4的带注释的分析

12、树,只使用综合属性。,S,E.val=19,E.val=15,T.val=4,T.val=15,F.val=4,T.val=3,F.val=3,F.val=5,digit.lexval=4,digit.lexval=5,digit.lexval=3,+,*,3*5+4的带注释的分析树,S-属性文法和自下而上翻译,一个一般的属性文法的翻译器是很难建立的,然而有一大类属性文法的翻译器是很容易建立的,那就是L-属性文法。S-属性文法(L-属性文法的特例) S-属性文法是只含有综合属性的属性文法。 综合属性可以在分析输入符号的同时自下而上的来计算。 通常借助LR分析器实现。 保存与栈中文法符号相关的综

13、合属性值。当归约时,新的属性值由正在归约的产生式右边符号的 属性值来计算。,G:EE E T+T E ToT T n T b,G:EE E T+T E ToT T n T b,G:EE E T+T E ToT T n T b,G:EE E T+T E ToT T n T b,L-属性文法在自上而下分析中的实现,L-属性文法,对于每一个产生式A X1 X2 Xn,其每个语义规则中的每个属性或者是综合属性,或者是Xj(1j n)的一个继承属性且这个继承属性仅依赖于: (1)产生式Xj在左边符号X1, X2, Xj-1的属性; (2)A的继承属性。 可以借助LL分析器实现。 可以借助LR分析器实现。

14、,L-属性文法在自上而下分析中的实现,例5.3 将中缀表达式翻译成相应的后缀表达式的属性文法E E addop T print(addop.Lexeme) TT num print(num.val),例5.3 将中缀表达式翻译成相应的后缀表达是式的属性文法(LR),其中addop表示或。E E addop T print(addop.lexme)TT num print(num.val)对表达式2+3-5的分析:打印出23 5 ,E,E,T,-,print,E,+,T,print,5,print5,T,print2,3,2,print3,上述文法含有左递归,如采用LL(1)分析须改写如下:E

15、TR R addop T print(addop.lexme)R1T num print(num.val)对表达式2+3-5的分析:打印出23+5-,R,R,print-,+,5,-,3,print5,T,print2,2,print3,E,T,print+,T,R,L-属性文法在自下而上分析中的实现,自下而上计算继承属性有两种办法 (1)从翻译模式中去掉嵌入在产生式中间的动作; (2)用综合属性代替继承属性。为了使所有的嵌入的动作都出现在产生式的末尾,可以采用方法:引入一个新的非终结符N和产生式 N ,把嵌入在产生式中间的动作用非终结符N代替,并把这个动作放在产生式后面。,例如: ET R

16、ET R R +T print(+) R1 引入M和N R + T MR1 R -T print(-) R1 变换 R - TNR1 R R T num print(num.val) T num print(num.val)M print(+) N print(-),用综合属性代替继承属性,改变基础文法是一种可能的办法。例如Pascal标识符说明语句的文法如下: DL: T /L.in=T.type ,继承自右部,不符合 L-属性文法 Tinteger|char L L,id|id 以综合属性代替继承属性,重新构造文法 Did L L, id L|:T T integer|char,属性文法

17、Did L addtype(id.entery,L.type) L, id L L.type:=L.type;addtype(id.entery,L.type) L :T L.type:=T.type T integer T.type:=int T char T.type:=ch,5.3 常见中间语言概述,何谓中间代码( Intermediate code) 是源程序的一种内部表示。 复杂性介于源语言和目标机语言之间。 中间代码的作用 使编译程序的逻辑结构更加简单明确; 利于进行与目标机无关的优化; 利于在不同目标机上实现同一种语言的前端编译程序设计。 中间代码的形式 逆波兰式、四元式、三元式

18、、间接三元式、树,中间代码的层次,中间代码按照其与高级语言和机器语言的接近程度,分成三个层次。 高级:最接近高级语言,保留了大部分源语言的 结构。 中级:介于二者之间,与源语言和机器语言都有 一定差异。 低级:最接近机器语言,能够反映目标机的系统 结构,因而经常依赖于目标机。,不同层次的中间代码举例,5.4 简单算术表达式和赋值语句的翻译(1) 对非终结符E定义语义变量E.place,即用E.place表示存放E值的变量名在符号表中的入口地址或临时变量名的整数码。(2) 定义语义函数newtemp( ),即每次调用newtemp( )时都将回送一个代表新临时变量的整数码;临时变量名按产生的顺序

19、可设为T1、T2、。(3) 定义语义过程emit(op,arg1,arg2,result), emit的功能是产生一个四元式并填入四元式表中。,简单赋值语句的四元式翻译 (4) 定义语义函数lookup(i.name),其功能是审查i.name是否出现在符号表中,是则返回i.name在符号表的入口指针,否则返回NULL。GA : Ai=E EE(1)+E(2)E(1)*E(2)E(1)(E(1) Ei 使用上述语义变量、过程和函数,可写出文法GA中的每一个产生式的语义子程序。,(1) Ai=E p=lookup(i.name);if(p=NULL) error( );else emit(=,E

20、.place,_,p); (2) EE(1)+E(2) E.place=newtemp( );emit(+,E(1) .place, E(2).place,E.place);(3) EE(1)*E(2) E.place=newtemp( );emit(,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) Ei p=lookup(i.name);if(p!=NULL) E.plac

21、e=p; /*另一种表示为E.place=entry(i)*/else error( );,例5.5 试分析赋值语句X= B*(C+D)的语法制导翻译过程。,Ai=E EE(1)+E(2)E(1)*E(2)E(1) (E(1) Ei,(4)EE(1) E.place=newtemp( ); emit(uminus,E(1) .place,_,E.place);,Ai=E EE(1)+E(2)E(1)*E(2)E(1) (E(1) Ei,(2) EE(1)+E(2) E.place=newtemp( );emit(+,E(1).place, E(2) .place,E.place);,(3) E

22、E(1)*E(2) E.place=newtemp( );emit(,E(1).place, E(2).place,E.place);,(1) Ai=E p=lookup(i.name);if(p=NULL) error( ); else emit(=,E.place,_,p); ,类型转换的语义处理产生式 语义动作 EE1+E2 E.place:= newtemp;if(E1type=int AND E2.type=int thenbegin emit(E.place“:=”E1.place“+”E2.place)E.type:=int; end;else if(E1type=real AN

23、D E2.type=real thenbegin emit(E.place“:=”E1.place“+”E2.place)E.type:=real; end;,else if(E1type=int ) then /两个运算量类型不同begin t:=newtemp;emit(t“:=”,itr,E1.place) /转换成实型(real)emit(E.place“:=”t“+”E2.place)E.type:=real; end; else begin t:=newtemp;emit(t“:=”,itr,E2.place)emit(E.place“:=”E1.place“+”t)E.type:

24、=real; end;,5.5 布尔表达式的翻译,程序设计语言中的布尔表达式的作用 计算逻辑值; 用做改变控制流语句中的条件表达式。 只考虑下面文法生成的布尔表达式 EE and E|E or E|not E|id rop id|true|false 约定布尔运算符的优先顺序(从高到低)为:not、and、or, 并且and和or服从左结合。,布尔表达式的翻译方法,计算布尔表达式的两种办法: (1)非简洁 (2)简洁 布尔表达式翻成四元式的描述例如: a or b and not c 翻译成的四元式序列为:(1) t1=not c(2) t2=b and t1(3) t3=a or t2,布尔

25、表达式的翻译方法,对于像ab这一类的关系表达式,可以视为等价的条件语句if ab then 1 else 0 , 它翻译成的四元式序列为:(1) if ab goto(4)(2) t=0(3) goto (5)(4) t=1(5) 其中:临时变量 t 存放布尔表达式ab的值;(5)为后续的四元式序号。,具体的布尔表达式翻译成四元式的描述如下: EE1 or E2 E.place:= newtemp;emit(E.place“:=” E1.place“or”E2.place)EE1 and E2 E.place:= newtemp;emit(E.place“:=” E1.place“and”E2

26、.place)Enot E1 E.place:=newtemp;emit(E.place“:=”“not” E1.place)E( E1 ) E.place:=E1.place),Eid1 rop id2 E.place:= newtemp;emit(if id1 .place “rop” id2 .place “goto” nextstart+3);emit(E.place“:=”“0”)emit( “goto” nextstart+2) emit(E.place“:=”“1”) Etrue E.place:=newtemp; emit(E.place“:=”“1”) Efalse E.pl

27、ace:=newtemp; emit(E.place“:=”“0”) 其中:nextstat 给出在输出序列中下一四元式序号。emit 过程每被调用一次,nextatat 增加1。,5.6 程序流程控制语句的翻译,控制语句,S,if E then S,1,else S,2,E,的代码,E,.true,E.false,E,.true:,S,1,的代码,goto out,E.false:,S,2,的代码,out:,作为条件转移的E,仅把E翻译成代码是一串条件转移和无条件转移的四元式。基本思路是对于E为a rop b的形式生成代码为:if a rop b goto E.true 和 goto E.f

28、alse 例8.5 af 翻译如下:,这不是最优的,因为(2)是不需要的。由代码优化阶段解决。 用E.true和E.false分别表示整个表达式 af的真假出口。,语句if af then s1 else s2的四元式序列:(1) if af goto (7) / 表达式为true时,转到S1处(6) goto p+1 / 表达式为false时,转到S2处(7) (p) goto q(p+1)(q),5.9 说明语句的翻译,一个程序或过程或分程序中的说明语句,以标识符的形式定义了数据对象,如常量、变量、数组等,这就需要为这些数据对象分配存储空间,同时,为了管理,将在符号表中登记这些数据信息(名

29、字、类型、分配的存储地址等),用以检查名字的引用和说明是否一致。许多说明语句的翻译并不生成目标代码。过程说明和动态数组的说明有相应的代码。,简单说明语句的翻译,程序设计语言中简单的说明语句的语法描述:D integer|real ,id|id即使用关键字integer和real定义一串名字的性质。对这种说明语句的翻译是指在符号表中登录该名和性质。 改写: D D1,id|integer id|real id,定义产生式所对应的语义动作(1) D integer id enter(id,int);D.att:=int(2) D real id enter(id,real);D.att:=real(3) D D1 ,id enter(id,D1.att);D.att:=D1.att D.att记录说明语句所引入的名字的性质int 还是 real 使用过程enter(id,A)把名字id和性质A登录在名表中。,本章小结,语义分析阶段的任务 检查静态语义错误(类型相容、惟一性、控制流检查) 生成中间代码 中间代码 四元式 逆波兰式 语义分析方法 属性文法(L属性文法) 自下而上语法制导翻译 自上而下语法制导翻译 赋值语句、布尔表达式、说明语句的翻译,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 语法

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报