东北大学秦皇岛分校编译原理课件第八章.ppt

上传人:牧羊曲112 文档编号:6533482 上传时间:2023-11-09 格式:PPT 页数:129 大小:889KB
返回 下载 相关 举报
东北大学秦皇岛分校编译原理课件第八章.ppt_第1页
第1页 / 共129页
东北大学秦皇岛分校编译原理课件第八章.ppt_第2页
第2页 / 共129页
东北大学秦皇岛分校编译原理课件第八章.ppt_第3页
第3页 / 共129页
东北大学秦皇岛分校编译原理课件第八章.ppt_第4页
第4页 / 共129页
东北大学秦皇岛分校编译原理课件第八章.ppt_第5页
第5页 / 共129页
点击查看更多>>
资源描述

《东北大学秦皇岛分校编译原理课件第八章.ppt》由会员分享,可在线阅读,更多相关《东北大学秦皇岛分校编译原理课件第八章.ppt(129页珍藏版)》请在三一办公上搜索。

1、第八章语法制导翻译和中间代码生成,8.1概述8.2属性文法和语法制导翻译8.3语义分析8.4中间代码8.5一些语句的翻译,概述 语义处理,程序设计语言的语义:按语法规则构成的各个语法成分的含义。静态语义是对程序约束的描述,这些约束无法通过抽象语法规则来妥善地描述,实质上就是语法规则的形式条件,它可以分为类型规则和作用域/可见性规则两大类,如:类型相容性 变量先声明后引用 名称相关要求动态语义 程序单位描述的计算编译程序的语义处理工作:静态语义审查、解释执行动态语义(计算)生成代码.,语义形式化 语义建模文法模型-属性文法命令式或操作式模型-操作语义学应用式模型-指称语义学公理式模型-公理语义学

2、,程序设计语言的语义分为两类:静态语义:编译时刻便可确定的语法成分的含义。动态语义:运行时刻才能理解与确定的语法成分的含义。语法制导是指在语法规则的指导下,通过计算语义规则,完成对输入符号串的语义翻译处理。,语义分析的功能,确定类型。确定标识符所关联的数据类型。(有时这个工作直接由词法分析完成)类型检查。按照语言的类型规则,对运算及进行运算的运算分量进行类型检查,检查运算的合法性与运算分量类型的一致性(相容性),必要时作相应的类型转换。识别含义。根据程序设计语言的语义定义(形式的或非形式的),确认(识别)程序中各构成组合到一起的含义,并作相应的语义处理。这时对可执行语句生成中间表示或目标代码。

3、控制流检查。控制流语句必须转移到合法的地方,如C中,break语句使得控制跳离包括该语句的最小while、for或switch语句,如果不存在包括它的这样的语句,则报错。一致性检查。在很多场合要求对象只能被说明一次,如PASCAL规定同一标识符在一个分程序中只能被说明一次等。相关名字检查。有的语言,如Ada,循环或程序块可以有一个名字,它出现在这些结构的开头或结尾,编译程序必须检查这两个地方用的名字是否相同。其它。如名字的作用域分析等也是语义分析的工作。,语法制导翻译,语法制导翻译的概念:P157语法制导翻译的基本思想:给文法中的每一个产生式添加一个成分,这个成分通常称为语义动作或翻译子程序,

4、在执行语法分析的同时,执行相应产生式的语义动作。这些语义动作不仅指明了该产生式所生成的符号串的含义,而且还根据这种意义规定了对应的加工动作,包括查填各类符号表、改变编译程序的某些变量的值,接着就执行相应的语义动作,完成规定的翻译工作。在这种情况下,语法分析工作和语义分析工作是穿插进行的。在自上而下语法分析中,若一个产生式匹配输入串成功,或者,在自下而上分析中,当一个产生式被用于归约时,此产生式相应的语义规则就被计算,完成有关语义分析和代码生成的工作。,属性文法,表达式文法 E T+T|T or T T n|b ET1+T2 T1.type=int T2.type=T1.type E.type:

5、=int E T1 or T2 T1.type=bool T2.type=T1.type E.type:=bool T n T.type:=int T b T.type:=bool,属性文法,语法制导翻译是通过属性文法来实现的。属性:对文法的每一个符号,引进一些属性,这些属性代表与文法符号相关的信息,例如类型、值、代码序列、符号表内容等。属性一般用标识符(或数)表示,它的意义局部于它所在的产生式。与这些属性相关的信息,即属性值,可以在语法分析过程中通过文法中的产生式而层层计算和传递(有时从产生式的左边向右传递,有时从产生式的右边向左边传递),当语法树最终构造完成时,就得到文法开始符号的属性值,

6、它也是该文法所描述的对象的最终语义,属性加工的过程即语义处理过程。属性又分为综合属性和继承属性。综合属性用于“自下而上”传递信息,也称推导型属性;而继承属性用于“自上而下”传递信息,也称归约型属性。通常规定:每个文法符号的继承属性和综合属性之交集为空。在语法树分析中,一个结点的综合属性的值由其子结点的属性值确定,而一个结点的继承属性的值由该结点的兄弟和/或父结点的属性值来计算。,语义规则,为文法的每一个规则配备的计算属性的计算规则,称为语义规则。语义规则的工作可以包括:属性计算、静态语义检查、符号表操作、代码生成等。语义规则可能产生副作用(如产生代码),也可能不是变元的严格函数(如某个规则给出

7、可用的下一个数据单元的地址)。这样的语义规则通常写成过程调用或过程段。属性文法:对于某个压缩了的上下文无关文法,当为每个文法符号引进一组属性,并且让该文法中的产生式附加以对属性进行处理的语义规则时,称该上下文无关文法为属性文法。根据不同的语法成分的语义,可以设计对不同的语法成分进行翻译的属性文法。其间要注意在不同时刻对不同信息的保存与获取,而这些也是通过属性文法中对文法符号属性的处理来实现的。,中间代码,为了使编译程序在逻辑上更为简单明确,特别是为了使目标代码的优化比较容易实现,许多编译程序都采用了某种中间语言程序(中间代码)。一般而言,中间代码是一种独立于具体硬件的记号系统。该记号系统含义明

8、确,便于处理。在第2章中PL/0语言所生成的伪代码实际上也是一种中间代码。比较常见的中间语言有逆波兰表示法、树型表示、三元式和四元式等。使用中间代码形式有如下好处:语义分析通常与机器无关,而目标代码往往与机器相关。把语义分析与目标代码生成分开,可以让一个语义分析程序适用于多个目标代码生成程序。可以对中间形式进行与机器无关的优化,有利于提高目标代码的质量。使各阶段的开发复杂性降低,有利于编译程序的开发。,逆波兰记号,逆波兰记号是最简单的一种中间代码表示形式。逆波兰表示法将运算对象写在前面,把运算符号写在后面,用这种表示法表示的表达式也称作后缀式。逆波兰表示的特点为:标识符(或运算对象)出现的顺序

9、(从左到右)和原有顺序相同。运算符是按实际计算顺序(从左到右)出现的。运算符紧跟在运算对象的后面出现,并且没有括号。,例题,答案:b,答案:b,三元式,例题,答案:d,四元式,例:,其它类型题,属性文法和语法制导翻译,虽然形式语义学(如指称语义学、公理语义学、操作语义学等)的研究已取得了许多重大的进展,但目前在实际应用中比较流行的语义描述和语义处理的方法主要还是属性文法和语法制导翻译方法。,属性文法,属性文法(attribute grammar)是一个三元组:A=(G,V,F),其中 G:是一个上下文无关文法V:有穷的属性集,每个属性与文法的一个终结符或非终结符相连,这些属性代表与文法符号相关

10、信息,如它的类型、值、代码序列、符号表内容等等.属性与变量一样,可以进行计算和传递。属性加工的过程即是语义处理的过程。F:关于属性的属性断言或一组属性的计算规则(称为语义规则).断言或语义规则与一个产生式相联,只引用该产生式左端或右端的终结符或非终结符相联的属性。,属性有两种 继承的和综合的属性,属性通常分为两类:综合属性和继承属性。简单地说,综合属性用于“自下而上”传递信息,而继承属性用于“自上而下”传递信息。出现在产生式左边的继承属性和出现在产生式右边的综合属性不由所给定的产生式的属性计算规则进行计算,它们由其它产生式的属性规则计算或者由生计算器的参数提供。AX1 X2 XnA的综合属性,

11、计算 S(A):=f(I(X1),I(Xn)Xj的继承属性,计算 T(Xj):=f(I(A),.I(Xn)1)非终结符既可有综合属性也可有继承属性,但文法开始符号没有继承属性。2)终结符只有综合属性。,在一个属性文法中,对应于每个产生式A都有一套与之相关联的语义规则,每条规则的形式为b:=f(c1,c2ck)这里,f是一个函数,而且或者(1)b是A的一个综合属性并且c1,c2ck是产生式右边文法符号的属性;或者(2)b是产生式右边某个文法符号的一个继承属性并且c1,c2ck是A或产生式右边任何文法符号的属性。在两种情况下,我们都说属性b依赖于属性c1,c2ck。,一个属性文法的例子 例8.1

12、非终结符E、T及F都有一个综合属性val,符号digit有一个综合属性,它的值由词法分析器提供。与产生式LEn对应的语义规则仅仅是打印由E产生的算术表达式的值的一个过程,我们可认为这条规则定义了L的一个虚属性。某些非终结符加下标是为了区分一个产生式中同一非终结符多次出现,语 义 规 则,L E,E E1+T,E T,T T1*F,T F,F(E),F digit,Print(E.val),E.val:=E1.val+T.val,E.val:=T.val,T.val:=T1.val F.val,T.val:=F.val,F.val:=E.val,F.val:=digit.lexval,产 生 式

13、,设表达式为35+4,则语义动作打印数值19,.,L,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的带注释的分析树,继承属性,一个结点的继承属性值是由此结点的父结点和/或兄弟结点的某些属性来决定的。例8.2 继承属性L.in,生 产 式,语 义 规 则,D TL,T int,T real,L L1,id,L id,L.in:=T.type,T.type=integer,T.type:=real,L1

14、.in:=L.in,addtype(id.entry,L.in),addtype(id.entry,L.in),D,L.in=real,L.in=real,L.in=real,T.type=real,real,id2,id1,id3,.,Real id1,id2,id3,,,,,语法制导的翻译,一个翻译是符号串对的一个集合。在一个编译程序定义的翻译中,符号串对是源程序和目标程序。各个编译阶段定义一个翻译,词法分析:(字符串,单词串)语法分析:(单词串,语法树)代码生成(语法树,汇编语言)设是输入字母表且是输出字母表。定义由语言 L1*到语言L2*的一个翻译是由*到*的一个关系T,使得T的定义域

15、为L1且T的值域为L2。使(x,y)T的句子y叫做x的一个输出.,语法制导的翻译,直观地说,一个语法制导翻译的基础是一个文法,其中翻译成分依附在每一产生式上。例8.4:下列翻译模式,它定义翻译,即对每个输入x,其输出y是x的逆转。定义此翻译的规则是,产生式,翻译规则,(1)s0s,(2)s1s,(3)s,(1)s=s0,(2)s=s1,(3)s=,输入输出对可由(,)表示,其中是输入句子形式而是输出句子形式。(S,S)开始用产生式s0s来扩展得到(0S,S0).再用一次规则(1),得到(00S,S00)。再用规则(2),就得到(001S,S100).然后应用规则(3)并得到(001,100)。

16、,例8.5:把下述产生式定义的算术表达式映射到后缀波兰表示:,EE+T,E T,T TF,T F,F(E),F a,E=ET+,E=T,T=TF,T=F,F=E,F=a,产生式,翻译规则,确定输入a+aa的输出:(E,E)(E+T,ET+)(T+T,TT+)(F+T,FT+)(a+T,aT+)(a+TF,aFF+)(a+FF,aFF+)(a+aF,aaF+)(a+aa,aaa+),定义:一个语法制导的翻译模式是一个五元组T=(N,,R,S),其中(1)N是非终结符的有限集。(2)是有限的输入字母表。(3)是有限的输出字母表。(4)R是形如A,的规则的有限集,其中(N)*,(N)*且中那组非终结

17、符是中那组非终结符的置换。(5)S是N中一个特别的非终结符,即开始符。,定义:若T=(N,R,S)是SDTS,(T)则称为语法制导的翻译(SDT),文法Gi=(N,P,S),其中P=A|A,属于R),称为SDTS T的基础(或输入)文法。文法G0=(N,P,S),,其中P=A|A,属于R,称为T的输出文法。把语法制导的翻译方法看成是将输入文法Gi中的推导树变换成输出文法G0中的推导树。给了输入句子x,可以按如下方式得到x的一个翻译:先为推导x构造一棵推导树,再变换该树到输出文法中的一棵树,然后取此输出树的边缘作为x的一个翻译。,语义制导翻译中的规则A,对应于每一个文法产生式A 都有与之相关联的

18、一套语义描述属性文法(attribute grammar)是一个三元组:A=(G,V,F)属性文法可以看作是关于语言翻译的高级规范说明,其中隐去实现细节,使用户从明确说明翻译顺序的工作中解脱出来,语法制导翻译实现,从概念上讲,语法制导翻译即基于属性文法的处理过程通常是这样的:对单词符号串进行语法分析,构造语法分析树,然后根据需要遍历语法树并在语法树的各结点处按语义规则进行计算输入符号串 分析树 属性依赖图 语义规则的计算顺序,依赖图,由称为依赖图的一个有向图 描述分析树中的继承属性和属性中间的相互依赖关系。依赖图的构造算法:for分析树中每一个结点n do for 结点的文法符号的每一个属性a

19、 do 为a在依赖图中建立一个结点;for 分析树中每一个结点n do for结点n所用产生式对应的每一个语义规则 b:=f(c1,c2,ck)do for i:=1 to k do 从ci结点到b结点构造一条有向边,依赖图-例8.2,例8.2 继承属性L.in,生 产 式,语 义 规 则,D TL,T int,T real,L L1,id,L id,L.in:=T.type,T.type=integer,T.type:=real,L1.in:=L.in,addtype(id.entry,L.in),addtype(id.entry,L.in),例8.2 Real id1,id2,id3分析树

20、的依赖图,5,6,7,8,9,10,T,4,D,L,L,L,Real,type,in,in,in,3 entry,2 entry,entry,id3,id2,id1,.,.,1,依赖图中的结点由数字来标识。从代表T.type的结点4有一条有向边连到代表L.in的结点5,因为根据产生式ETL的语义规则L1.in=L.in,可知L1.in依赖于L.in,所以有两条向下的有向边分别进入结点7和9。每一个与L产生式有关的语义规则addtype(id.Entry,L.in)都产生一个虚属性,结点 6、8和10都是为这些虚属性构造的。,良定义的属性文法。,很显然,一条求值规则只有在其各变元值均已求得的情况

21、下才可以使用。但有时候可能会出现一个属性对另一个属性的循环依赖关系。从事贸易如,p、c1、c2都是属性,若有下求值规则:p:=f1(c1)、c1:=f2(c2)、c2:=f3(p)时,就无法对p求值。如果一属性文法不存在属性之间的循环依赖关系,那么称该文法为良定义的。为了设计编译程序,我们只处理良定义的属性文法。,属性的计算顺序,一个有向非循环图的拓扑序是图中结点的任何顺序m1,m2,mk,使得边必须是从序列中前面的结点指向后面的结点。也就是说,如果mimj是mi到mj的一条边,那么在序列中mi必须出现在mj之前。一个依赖图的任何拓扑排序都给出一个分析树中结点的语义规则计算的有效顺序。这就是说

22、,在拓扑排序中,在一个结点,语义规则b:=f(c1,c2,ck)中的属性c1,c2,ck在计算b以前都是可用的。,属性文法说明的翻译是很精确的。最基本的文法用于建立输入符号串的分析树。依赖图如上面讨论的那样建立。从依赖图的拓扑排序中,我们可以得到计算语义规则的顺序。用这个顺序来计算语义规则就得到输入符号串的翻译。例8.2Real id1,id2,id3分析树的依赖图每一条边都是从序号较低的结点指向序号较高的结点。历此,依赖图的一个拓扑排序可以从低序号到高序号顺序写出。从这个拓扑排序中我们可以得到下列程序,用an来代表依赖图中与序号n的结点有关的属性:a4:=reala5:=a4 addtype

23、(id3,entry,a5);a7:=a5;addtype(id2,entry,a7)a9:=a7 addtype(id1,entry,a9)这些语义规则的计算将把real类型填入到每个标识符对应的符号表项中。,属性计算方法,树遍历的属性计算方法设语法树已经建立起了,并且树中已带有开始符号的继承属性和终结符的综合属性。然后以某种次序遍历语法树,直至计算出所有属性。最常用的遍历方法是深度优先,从左到右的遍历方法。如果需要的话,可使用多次遍历(或称遍)。一遍扫描的处理方法与树遍历的属性计算文法不同,一遍扫描的处理方法是在语法分析的同时计算属性值,而不是语法分析构造语法树之后进行属性的计算,而且无无

24、需构造实际的语法树。因为一遍扫描的处理方法与语法分析器的相互作用,它与下面两个因素密切相关:(1)所采用的语法分析方法(2)属性的计算次序。,例:定义定点二进制数的CFG:,(1)NSS(2)SSB(3)SB(4)B0(5)B1,非终结符N表示整个二进制数的数值,综合属性v附加在N上:N v 非终结符B 表示一个二进制数字,它有自己的值v,但该值分配给N的值与它的位置有关,是与2成比例,比例因子f是从S继承的属性,所以:B v f 非终结符S 表示一个二进制数字串,它也有值,但该值与串的位置有关,与f有关与串的长度l有关:S f v l,构造数值的属性断言可以如下:,N vS f1 v 1 l

25、1 S f 2 v 2 l2 v=v1+v2;f 1=1;f2=2-l2 S f v l S f1v1 l 1B f 2v2 f1=2f;f 2=f;v=v 1+v2;l=l1+1 B f v l=1 B f v0 v=0 1 v=f,N v S i1 l1“”S i2 l2 v=i1+2-l2 i2 S i l S i1 l 1 Bi2 i=2 i1+i2;l=l1+1 B i l=1 B i“0”i=0“1”i=1,在某些情况下可用一遍扫描实现属性文法的语义规则计算。也就是说在语法分析的同时完成语义规则的计算,无须明显地构造语法树或构造属性之间的依赖图。因为单遍实现对于编译效率非常重要 具

26、体的实现希望在单遍扫描中完成翻译研究怎样实现这种翻译器。一个一般的属性文法的翻译器可能是很难建立的,然而有一大类属性文法的翻译器是很容易建立的 s-属性 适用于自底向上的计算 L-属性 适用于自顶向下的分析,也可用于自底向上。,S属性文法的自下而上计算,S属性文法,它只含有综合属性。综合属性可以在分析输入符号串的同时自下而上的分析器来计算。分析器可以保存与栈中文法符号有关的综合属性值,每当进行归约时,新的属性值就由栈中正在归约的产生式右边符号的属性值来计算。S属性文法的翻译器通常可借助于LR分析器实现。在S属性文法的基础上,LR分析器可以改造为一个翻译器,在对输入串进行语法分析的同时对属性进行

27、计算。,产生式 语义规则)(.)1.1.).l)1*.1.)F.F.)().)ii.:.LR分析器可以改造为一个翻译器,在对输入串进行语法分析的同时对属性进行计算。LR分析器增加语义栈,*的分析和计值过程,步骤 动作 状态栈 语义栈(值栈)符号栈 余留输入串)3*)3*)*)*)*)*)*)*)*)*)*)()*#)()()接受,BOTTOMUP语义处理是作类型检查,对二目运算符的运算对象进行类型匹配审查。(LR分析):增加语义栈 归约时进行语义动作.例8.7GE:(1)E T+T(2)E T or T(3)T n(4)T b,ET1+T2 if T1.type=int and T2.type

28、=int then E.type:=int else error E T1 or T2 if T1.type=bool and T2.type=bool then E.type:=bool else error T n T.type:=intT b T.type:=bool,GE:(1)E T+T(2)E T or T(3)T n(4)T b,L属性文法和自顶向下翻译,一个属性文法称为L属性文法,如果对于每个产生式AX1X2Xn,其每个语义规则中的每个属性或者是综合属性,或者是Xj(1jn)的一个继承属性且这个继承属性仅依赖于:(1)产生式Xj在左边符号X1,X2,Xj-1的属性;(2)A的继

29、承属性。S属性文法一定是L属性文法,因为(1)、(2)限制只用于继承属性。L属性文法允许一次遍历就计算出所有属性值。LL(1)这种自上而下分析文法的分析过程,从概念上说可以看成是深度优先建立语法树的过程,因此,我们可以在自上而下语法分析的同时实现L属性文法的计算。,例(中缀表达式翻译成相应的后缀表达式)ETRRaddop T print(addop.Lexeme)R1|Tnum print(num.val),翻译模式(Translation schemes)适合语法制导翻译的另一种描述形式。翻译模式给出了使用语义规则进行计算的次序,可把某些实现细节表示出来。在翻译模式中,和文法符号相关的属性和

30、语义规则(这里我们也称语义动作),用花括号括起来,插入到产生式右部的合适位置上。,输入串95+2的语法树,每个语义动作都作为相应产生式左部符号的结点的儿子,按深度优先次序执行图中的动作后,打印输出952+。,ET R9 print(9)-T print(-)R 5 print(5)+T print(+)R 2 print(2),L属性文法在自顶向下分析中的实现,带左递归的文法的翻译模式EE1+T E.val:=E1.val+T.valEE1T E.val:=E1.valT.valET E.val:=T.valT(E)T.val:=E.valTnum T.val:=num.val,消除左递归的同

31、时考虑属性,构造新的翻译模式,ETR.i:=T.val R E.val:=R.sR+T R1.i:=R.i+T.val R1 R.s:=R1.sR-T R1.i:=R.i-T.val R1 R.s:=R1.sRR.s:=R.iT(E)T.val:=E.valTnum T.val:=num.val,计算表达式9-5+2,.,E,R.i=9,T.val=5,T.val=9,R.i=4,R.i=6,T.val=2,num.val=9,num.val=5,num.val=2,_,+,在上页的翻译模式中,每个数都是由T产生的,并且T.val的值就是由属性num.val给出的数的词法值。子表达式95中的数

32、字9是由最左边的T生成的,但是减号和5是由根的右子结点R生成的。继承属性R.i从T.val得到值9。计算95并把结果4传递到中间的R结点这是通过产生式中嵌入的下面动作实现:R1.i:=R.iT.val类似的动作把2加到95的值上,在最下面的R结点处产生结果R.i6。这个结将成为根结点处E.val的值,R的综合属性s在图中没有表示出来,它用来向上复制这一结果一直到树根。,对于自顶向下分析,我们假设动作是在处于相同位置上的符号被展开(匹配成功)时执行的。如图中的第二个产生式中,第一个动作(对R1.i赋值)是在T被完全展开成终结符号后执行的,第二个动作是在R1被完全展开成终结符号后执行的。正如前面我

33、们所讨论的,一个符号的继承属性必须由出现在这个符号之前的动作来计算,产生式左边非终结符的综合属性必须在它所依赖的所有属性都计算出来以后才能计算。,转换左递归翻译模式的方法推广到一般,假设翻译模式1:AA1YA.a:=g(A1。a,Y.y)AX A.a:=f(X.x)每个文法符号都有一个综合属性,用相应的小写字母表示,g和f是任意函数 消除左递归,文法转换成:AXR RYR再考虑语义动作,翻译模式变为2AXR.i:=f(X.x)R A.a:=R.sRYR1.i:=g(R.i,Y.y)R1R.s:=R1.sRR.s:=R.i,翻译模式1和翻译模式2的结果是一样的。可以给出串XY1Y2两棵带注释的语

34、法树看出来,一棵是根据翻译模式1自下而上计算属性的。一棵是根据翻译模式2自上而下计算的。,AA1YA.a:=g(A1。a,Y.y)AX A.a:=f(X.x),A.a=g(g(f(X.x,Y1.y),Y2.y)A.a=g(f(X.x,Y1.y)Y2A.a=f(X.x)Y1 X,A A YA Y X,AXR.i:=f(X.x)RYR1.i:=g(R.i),Y.y)R A.a:=R.s R1R.s:=R1.s,AXR RYR AX R Y1 R Y2 R,AX R.i=f(X.x)Y1 R.i=g(f(X.x,Y1.y)Y2 R.i=g(g(f(X.x,Y1.y),Y2.y),思考问题-把建立语法

35、树的翻译模式变换成适合预测分析的模式,EE1+T E.nptr:=mknode(+,E1.nptr,T.nptr)E E1-T E.nptr:=mknode(-,E1.nptr,T.nptr)E T E.nptr:=T.nptr),自下而上计算继承属性,讨论在自下而上的分析过程中实现L属性文法的方法。这种方法可以实现任何基于LL(1)文法的L属性文法,它还可以实现许多(不是所有)基于LR(1)文法的L属性文法。这种方法是S-属性文法的自下而上翻译技术的一般化,自下而上分析器对产生式AXY的右部是通过把X和Y从分析栈中移出并用A代替它们。假设X有一个综合属性X.s,按照前面所介绍的方法我们把它与

36、X一起放在分析栈中。由于X.s的值在Y以下的子树中的任何归约之前已经放在栈中,这个值可以被Y继承。也就是说,如果继承属性Y.i是由复写规则Y.i:=X.s定义的,则可以在需要y.i值的地方使用X.s的值。在自下而上分析中计算属性值时复写规则起非常重要的作用。看下面例子。,假设某翻译模式为:DTL.in:=T.typeLTintT.type:=integerTrealT.type:=realLL1.in:=L.inL1,idaddtype(id.entry,L.in)Lidaddtype(id.entry,L.in),回顾例8.2 Real id1,id2,id3分析树的依赖图,5,6,7,8,

37、9,10,T,4,D,L,L,L,Real,type,in,in,in,3 entry,2 entry,entry,id3,id2,id1,.,.,1,例8.2输入串real Real id1,id2,id3的分析过程当L的右部被归约时,T恰好在这个右部的下面,输入 状态(符号)使用产生式Real id1,id2,id3#id1,id2,id3#real id1,id2,id3#T Treal,id2,id3#Tid1,id2,id3#TL L id id2,id3#TL,id3#TL,id2,id3#TL L Li,d id3#TL,#TL,id3#TL L Li,d#D D TL,用综合属

38、性代替继承属性,有时,改变基础文法可能避免继承属性。例如,一个Pascal的说明由一标识符序列后跟类型组成,如,m,n:integer。这样的说明的文法可由下面形式的产生式构成DL:TTinteger|charLL,id|id因为标识符由L产生而类型不在L的子树中,我们不能仅仅使用综合属性就把类型与标识符联系起来。事实上,如果非终结符L从第一个产生式中它的右边T中继承了类型,则我们得到的属性文法就不是L属性的,因此,基于这个属性文法的翻译工作不能在语法分析的同时进行。,一个解决的方法是重新构造文法,使类型作为标识符表的最后一个元素:Did LL,id L|:TTinteger|char这样,类

39、型可以通过综合属性L.type进行传递,当通过L产生每个标识符时,它的类型就可以填入到符号表中。,语义制导翻译的编译实现:,例8.6E TEE A T E|T FTT M F T|F(E)|intA+|-M*|/,E-TEE-A T E rhs=PopOperand();lhs=PopOperand();switch(PopOperator()case ADD:PushOperand(lhs+rhs);break;case SUB:PushOperand(lhs-rhs);break;|/*empty,do nothing*/T-FTT-M F T rhs=PopOperand();lhs=P

40、opOperand();switch(PopOperator()case MUL:PushOperand(lhs*rhs);break;case DIV:PushOperand(lhs/rhs);break;|/*empty,do nothing*/A-+PushOperator(ADD);|-PushOperator(SUB);M-*PushOperator(MUL);|/PushOperator(DIV);F-int PushOperand(intval);|(E)/*handled during parsing of E*/,parse 2+4*3:,分析动作桥 分析栈 运算对象栈 运算

41、符栈Predict E TE E#Predict T FT TE#Predict F int FTE#Match int intTE#Predict T TE#2Predict E ATE ATE#2Predict A+ATE#2Match+TE#2Predict T FT TE#2+Predict F int FTE#2+Match int intTE#2+Predict T MFT TE#4 2+Predict M*MFTE#4 2+Match*FTE#4 2+Predict F int FTE#4 2*+Match int intTE#4 2*+Predict T TE#3 4 2*+P

42、redict E E#12 2+Success!#14,Yacc或bison作为编译程序的生成工具,利用的就是语法制导翻译方法。它使用符号$表示产生式左端的属性,$n表示存取产生式右端第n个文法符号相联的属性,如例8.3作为Yacc的输入,可写成:P DS$2.dl=$1.dlD1 var V;D$.dl=addlist($2.name,$4.dl)|$.dl=nullS1 V:=e;Scheck($1.name,$.dl);$5.dl=$.dl|V x$.name=x|y$.name=y|z$.name=z,如果数据结构attribute定义属性name和dl,可以具体化为:type str

43、uct_attribute char*name;struct_attribute*list;attribute;,P DS$2.list=$1.listD1 var V;D$.list=add_to_list($2.name,$4.list)|$.list=nullS1 V:=e;Scheck($1.name,$.list);$5.list=$.list|V x$.name=x|y$.name=y|z$.name=z,语义分析,语义分析属性文法和语法制导翻译方法和技术应用于语义分析中。,语义分析,通常包括:(1)类型检查。验证程序中执行的每个操作是否遵守语言的类型系统的过程.,编译程序必须报告

44、不符合类型系统的信息。(2)控制流检查。控制流语句必须使控制转移到合法的地方。例如,在C语言中break语句使控制跳离包括该语句的最小while、for或switch语句。如果不存在包括它的这样的语句,则就报错。(3)一致性检查。在很多场合要求对象只能被定义一次。例如Pascal语言规定同一标识符在一个分程序中只能被说明一次,同一case语句的标号不能相同,枚举类型的元素不能重复出现等等。(4)相关名字检查。有时,同一名字必须出现两次或多次。例如,Ada 语言程序中,循环或程序块可以有一个名字,出现在这些结构的开头和结尾,编译程序必须检查这两个地方用的名字是相同的。(5)名字的作用域分析,类型

45、和声明(Types and declarations),一个类型是一组值和在这些值上的一组操作,程序设计语言中有三种类型:基本类型:int,float,double,char,bool等等.也可能允许在基本类型基础上用户自己定义的类型,如枚举型.复合类型:数组,指针,记录/结构/联合,类等等.这些类型由基本类型构成.复杂类型:链表,栈,队,树,堆,表格等等.可以把它们组织成ADT.一个语言不一定支持这类高级的抽象。声明是程序中的一个语句,是把数据对象的名称和类型,以及生命周期信息传给编译,声明的地方传递生命周期信息也有些语言允许声明初始化变量。如:double calculate(int a,

46、double b);/function prototypeint x=0;/global variables available throughoutdouble y;/the programint main()int m3;/local variables available only in mainchar*n;.,强类型的-任何数据类型都可以在 编译时确定弱类型的.进行类型检查的时间:编译时,运行时,或者两者结合.静态类型检查 编译时进行类型检查动态类型检查,将类型信息并到运行时每个数据单元中.隐含类型转换.,PD;EDD;|id:TTchar|integer|aray numof T|

47、TEliteral|num|id|E mod E|E E|EP代表程序;D代表说明;E代表表达式。如程序语句:key:integer;key mod 1999语言本身提供两种基本类型:char和integer。除此之外还有缺省的基本类型type_ error和void。假定所有数组都从下标1开始,确定标识符类型的部分翻译模式,(1)PD;E(2)DD;D(3)Did:T addtype(id.Entry,T.type)(4)Tchar T.Type:=char(5)Tinteger T.Type:=integer(6)TT1 T.Type:=pointer(T1.type)(7)Tarray

48、numof T1 T.Type:=array(num.Val,T1.type),语句的类型检查的翻译模式,Sid:=E if id.Type=E.Type Then S.Type:=void else S.Type:=type_ errorSif E then S1 if E.type=boolean then S.Type:=S1.type else S.type:=type_ errorSwhile E do S1 if E.type=boolean Then S.type:=S1.Type else S.type:=type_ error,设计类型检查程序,1.辨认语言中可用的类型2.辨

49、认具有类型的语言结构3.辨认语言的语义规则,In Decaf,base types:int,double,bool,string compound types:arrays and classes.An array can be made of any type(either a base type,a class,or out of other arrays).Classes are a bit special in that the class name must be declared before it can be used in a declaration.ADTs can be

50、constructed using classes,but they arent handled in any way differently than classes,so we dont need to consider them specially.,In Decaf the relevant language constructs,constants,every constant has an associated type.A scanner tells us these types as well as the associated lexeme.variables:all var

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号