ImageVerifierCode 换一换
格式:PPT , 页数:179 ,大小:1.48MB ,
资源ID:8252218      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.docduoduo.com/d-8252218.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录   微博登录 

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(6语义分析与中间代码生成.ppt)为本站会员(tkhy51908)主动上传,道客多多仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知道客多多(发送邮件至docduoduo@163.com或直接QQ联系客服),我们立即给予删除!

6语义分析与中间代码生成.ppt

1、第6章 语义分析与中间代码生成,主要内容,语法制导翻译 符号表 类型检查 中间语言 中间代码生成,源语言程序,中间代码,目标代码,词法分析,语义分析,语法分析,中间代码生成,代码生成,在编译中的逻辑阶段,前端处理,后端处理,语义处理,语义处理的任务: 静态语义检查 静态语义检查:审查静态语义 (语义分析) 动态语义处理 动态语义处理:生成(中间/目标)代码,首先是语义分析和正确性检查,若正确,则翻译成中间代码或目标代码。,在文法中,文法符号通常都有明确的意义,文法符号之间也有确定的语义关系。用属性描述语义信息,用语义规则描述属性间的的关系,将语义规则与语法规则相结合。,基本思想:根据翻译的需要

2、设置文法符号的属性, 以描述语法结构的语义。例如,一个变量的 属性有类型,作用域,存储地址等。表达式的属性有类型,值等。属性值的计算和产生式相联系。随着语法分析的进行,执行属性值的计算,完成语义分析和翻译的任务。,语义处理的环境:符号表 为语义分析提供类型、作用域等信息。 为代码生成提供类型、作用域、存储类别、存储(相对)位置等信息。,在语法分析过程中,随着分析的步步进展,根据每个产生式所对应的语义规则描述的语义动作(或语义子程序)进行翻译的办法称作语法制导翻译。,语法制导翻译,1、属性文法(syntax-directed definitions):定义翻译所必须的语义属性和语义规则,一般不涉

3、及计算顺序。是对上下文无关文法的推广。 2、翻译模式(translation schemes): 给出语义规则进行计算的顺序。,两种常用的描述语义的方法:,6.1 语法制导翻译,属性文法(attribute grammar)是在上下文无关文法的基础上,为文法每个终结符和非终结符配备若干相关的属性,这些属性代表与文法符号相关信息,如它的类型、值、代码序列、符号表内容等等 .属性与变量一样,可以进行计算和传递。对于文法的每一个产生式都配备了一组属性的计算规则,属性加工的过程即是语义处理的过程。,属性通常分为两类:综合属性和继承属性。简单地说,综合属性用于“自下而上”传递信息,而继承属性用于“自上而

4、下”传递信息。,在一个属性文法中,AP都有与之相关联的一套语义规则,规则形式为b:= f(c1,c2,ck),f 是一个函数,而且或者,2b是中文法符号的一个继承属性并且c1, c2,ck是A或中的任何文法符号的属性。,1b是A的一个综合属性并且c1,c2,ck 是中文法符号的属性,或者,在两种情况下,都说属性b依赖于属性c1,c2,ck。,1)非终结符既可有综合属性也可有继承属性,但文法开始符号没有继承属性.2)终结符只有综合属性,它们由词法程序提供.,语义规则所描述的工作可以包括属性计算、静态语义检查、符号表操作、代码(中间)生成等等。有些语义规则可能产生副作用(如产生代码),通常把这样的

5、语义规则写成函数调用。,综合属性,在分析树中,一个结点的综合属性值是从其子结点的属性值计算出来的;结点属性值的计算正好和自底向上分析建立分析树结点同步进行。,只使用综合属性的属性文法称为S-属性文法。,digitlexval:=3,Fval:=3,Tval:=3,digitlexval:=5,Fval:=5,Tval:=15,*,Eval:=15,+,digitlexval:=4,Fval:=4,Tval:=4,Eval:=19,3*5+4的带注释的分析树,继承属性每个文法符号可以和一个继承属性值 联系,属性值的设置和语法结构的语义以及翻译程序的需要有关。,一个结点的继承属性值是由该结点兄弟结

6、点和/或父结点的属性值计算出来的。,例 进行变量说明的类型定义real a,b,c,DT L T int T real L L,id L id,c,b,D,T.type,L.in,real,L.in,,,L.in,,,a,每一个L结点处都带有继承属性in的分析树,addtype(c.entry, real),addtype(b.entry, real),addtype(a.entry, real),= real,= real,= real,= real,基于属性文法的翻译,1.依赖图 (依赖图的构造方法) for 分析树中每一结点n do for 结点n的文法符号的每一个属性a do 为a在依

7、赖图中建立一个结点;for 分析树中每一个结点n do for 结点n所用产生式对应的每一条语义规则 b:f(c1,c2,ck ) do for i:=1 to k do 从结点ci到结点b构造一条有向边;,c.entry,b.entry,每一个L结点处都带有继承属性in的分析树,T,L,L,c,L,b,D,a,real,1,2,3,4,5,6,7,8,9,10,entry,entry,entry,type,in,in,in,2. 计算顺序 拓扑排序一个有向非循环图的拓扑排序是图中结点的任何顺序m1,m2,mk,使得边必须是从序列中前面的结点指向后面的结点,也就是说,如果mimj是mi到mj的

8、一条边,那么在 序列中mi必须出现在mj的前面。,上图的一个拓扑排序是:1, 2, 3,4,5,6,7,8,9,10a.entry b.entry c.entryT.type:=real;L.in:= T.type;addtype(c.entry, L.in);L.in := L.in;addtype(b.entry, L.in);L.in := L.in;addtype(a.entry, L.in);,若依赖图中无环,则存在一个拓扑排序,它就是属性值的计算顺序。,1 .分析树法 输入串 分析树 依赖图 计算顺序,计算语义规则的方法,2. 忽略语义规则的方法:在分析过程中翻译,计算顺序由分析方

9、法来确定而表面 上与语义规则无关。实际上,使属性值的计算顺序能和语法分析过程同步进行。,计算语义规则的方法,树遍历的属性计算方法 设语法树已经建立起了,并且树中已带有开始符号的继承属性和终结符的综合属性。常采用深度优先,从左到右的遍历方法。如果需要的话,可使用多次遍历。 一遍扫描的处理方法与树遍历的属性计算文法不同,一遍扫描的处理方法是在语法分析的同时计算属性值,而不是语法分析构造语法树之后进行属性的计算,而且并无需构造实际的语法树。,在单遍扫描中完成翻译研究怎样实现这种翻译器,一个一般的属性文法的翻译器可能是很难建立的,然而有一大类属性文法的翻译器是很容易建立的. S-属性文法 适用于自底向

10、上的计算L-属性文法 适用于自顶向下的计算,也可用于 自底向上。,S-属性文法及其自下向上的计算,S属性文法,它只含有综合属性。 综合属性可以在分析输入符号串的同时自下而上计算。分析器可以保存与栈中文法符号有关的综合属性值,每当进行归约时,新的属性值就由栈中正在归约的产生式右边符号的属性值来计算。 S属性文法的翻译器通常可借助于LR分析器实现。在S属性文法的基础上,LR分析器可以改造为一个翻译器,在对输入串进行语法分析的同时对属性进行计算。,产生式 语义规则 )1 .1. ) .l )1* .1. )F .F. )() .)ii .:.LR分析器增加语义栈,在对输入串进行语法分析的同时对属性进

11、行计算。,分析器模型,总控程序,output,Input#,S1,Xm, S1, X1,S0,#,栈,状态,符号,ACTION,GOTO,LR分析表,Vm,V1,-,语义, S1,S0,Vm,V1,-,top,state,val,.,.,Z,Z.z,Y,Y.y,X,X.x,state,val,.,.,A,A .a,top,定义式 AXYZ归约时对应的翻译是 valntop:=f(valtop-2, valtop-1, valtop)(具体可执行代码)。在执行代码段之前执行:ntop:=top-r+1 r是句柄的长度,翻译输入3*5+4所做的移动,输入 state val 使用的产生式,3*5+

12、4 - -,*5+4 3 3,*5+4 F 3 Fdigit,*5+4 T 3 TF,5+4 T* 3-,+4 T* 5 3-5,+4 T* F 3-5 F digit,+4 T 15 T T*F,+4 E 15 E T,4 E+ 15-,E+4 15-4,E+F 15-4 F digit,E+T 15-4 T F,E 19 E E+T,输入 state val 使用的产生式,总结:对S-属性定义进行翻译可结合自底向上语法分析,例如LR分析,把S-属性定义变成可执行的代码段,就构成了翻译程序。把语法制导翻译比做一座建筑,语法分析是构架,语义处理是装修。这样,随着语法分析的进行,归约前调用相应的

13、语义子程序,完成翻译的任务。,L-属性文法和自顶向下翻译 定义一个属性文法是L-属性文法,如果AX1X2XnP,其每一个语义规则中的每一个属性都是一个综合属性,或Xj(1j n)的一个继承属性仅依赖于 1 产生式中Xj的左边符号X1,X2,Xj-1的属性; 2A的继承属性。每一个S-属性文法都是L-属性文法。,产生式,语义规则,ALMA QR,L.i:=y(A.i) M.i:=m(L.s) A.s:=f(M.s) R.i:=r(A.i) Q.i:=q(R.s) A.s:=f(Q.s),该属性文法不是L-属性文法,文法符号Q的继承属性依赖于它右边文法符号R的属性,一种自然的计算属性的顺序是按深度

14、优先 访问分析树结点的顺序。L-属性文法可以按深度优先顺序计算属性值。,深度优先顺序计算属性 PROCEDURE dfvisit(n:node); BEGINFOR n 的每个子结点m,从左至右 DOBEGIN计算m的继承属性; dfvisit(m) END; 计算n的综合属性 END;,翻译模式 定义翻译模式是属性文法的一种便于翻译的书写形式。其中语义规则或语义动作用花括号 括起来,可被插入到产生式右部的任何合适的位置上。这是一种语法分析和语义动作交错的表示法,它表达在按深度优先遍历分析树的过程中 何时执行语义动作。翻译模式给出了使用语义规则进行计算的顺序。可看成是分析过程中翻译的注释。,设

15、计翻译模式(根据属性文法) 条件:属性文法是L-属性文法保证语义动作不会引用还没有计算的属性值。 1. 只需要综合属性的情况为每一个语义规则建立一个包含赋值的动作,并把这个动作放在相应的产生式右边的末尾。例如:TT1*F Tval:=T1 val*F valTT1*F Tval:=T1 val*F val,2. 既有综合属性又有继承属性 产生式右边的符号的继承属性必须在这个符号以前的动作中计算出来。 一个动作不能引用这个动作右边符号的综合属性。 产生式左边非终结符号的综合属性只有在它所引用的所有属性都计算出来以后才能计算。计算这种属性的动作通常可放在产生式右端的末尾。,自顶向下的翻译 只有综合

16、属性的翻译模式适用于自底向上或自顶向下 即有综合属性又有继承属性的翻译模式适用于自顶向下,注意: 对于一个翻译模式,若采用自顶向下分析,必须消除左递归和提取公共左因子。,自下而上计算继承属性,从翻译模式中去掉嵌入在产生式中间的动作 分析栈中的继承属性 用综合属性代替继承属性,从翻译模式中去掉嵌入在产生式中间的动作转换方法: 引入新的非终结符N和产生式N ,把嵌入在产生式中间的动作用非终结符N代替,并把这个动作放在产生式N 后面.,例:ETR R + T print (+) R R- T print (-) R R Tnum print (num.val) 文法变换后,接受的语言相同.,ETR

17、R + T M R R- T N RR Tnum print (num.val) M print (+) N print (-) 目的: 使所有嵌入的动作都出现在产生式的末尾,可以自下而上处理继承属性.,分析栈中的继承属性,自下而上分析器对产生式AXY的右部是通过把X和Y从分析栈中移出并用A代替它们。假设X有一个综合属性X.s,按照前面所介绍的方法它与X对应放在分析栈中。 由于X.s的值在Y以下的子树中的任何归约之前已经放在栈中,这个值可以被Y继承。也就是说,如果继承属性Y.i是由复写规则Y.i: = X.s定义的,则可以在需要y.i值的地方使用X.s的值。在自下而上分析中计算属性值时复写规则

18、起非常重要的作用。看下面例子。,标识符的类型通过继承属性的复写规则来传递,翻译模式为: D T L.in: = T.type L T int T.type: = integer T real T.type: = real L L1.in: = L.in L1, id addtype(id.entry, L.in) L id addtype (id.entry, L.in),id3,id2,D,T.type,L.in,real,L.in,,,L.in,,,id1,每一个L结点处都带有继承属性in的分析树,addtype(id3.entry, real),addtype(id2.entry, re

19、al),addtype(id1.entry, real),= real,= real,= real,= real,输入 符号 使用产生式 real id1,id2,id3#id1,id2,id3# real id1,id2,id3# T Treal,id2,id3# Tid1,id2,id3# TL L idid2,id3# TL,id3# TL,id2,id3# TL L L,idid3# TL,# TL,id3# TL L L,id# D D TL,输入串real id1,id2,id3的分析过程中当L的右部被归约时,T恰好在这个右部的下面。,翻译模式: D T L.in: = T.typ

20、e L T int T.type: = integer T real T.type: = real L L1.in: = L.in L1, id addtype(id.entry, L.in) L id addtype (id.entry, L.in),翻译模式: D T L T int T.type: = integer T real T.type: = real L L1, id addtype (id.entry, ) L id addtype (id.entry, ) ,L.in: = T.type,L1.in: = L.in,L.in,L.in,T.type,T.type,扩充分析栈

21、Vali存放文法符号X的综合属性X.s. 归约时T.type在栈中相对于栈顶的位置已知。,DT L Tint Valntop = integer Treal Valntop = real LL, id addtype (Valtop, Valtop-3) Lid addtype (Valtop, Valtop-1),翻译器归约时的代码(嵌入LR分析器中),由于X.s的值在Y以下的子树中的任何归约之前已经放在栈中,这个值可以被Y继承。也就是说,如果继承属性Y.i是由复写规则Y.i: = X.s定义的,则可以在需要y.i值的地方使用X.s的值。,用综合属性代替继承属性,改变基础文法可能避免继承属性

22、。例如,一个Pascal的说明由一标识符序列后跟类型组成,如, m, n: integer。这样的说明的文法可由下面形式的产生式构成 DL:T Tinteger|char LL, id|id因为标识符由L产生而类型不在L的子树中,我们不能仅仅使用综合属性就把类型与标识符联系起来。事实上,如果非终结符L从第一个产生式中它的右边T中继承了类型,则我们得到的属性文法就不是L属性的,因此,基于这个属性文法的翻译工作不能在语法分析的同时进行。,1 .分析树法 输入串 分析树 依赖图 计算顺序,总结:计算语义规则的方法,2. 一遍扫描的处理方法, 属性值的计算顺序能和语法分析过程同步进行。S-属性文法及其

23、翻译模式 适用于自底向上的计算,也可用于自顶向下。L-属性文法及其翻译模式适用于自顶向下的计算,也可用于自底向上。,语法制导翻译的过程:1.根据上下文无关文法设计属性文法 2.属性文法一般为L-属性文法,将其改写为翻译模式 3.若翻译模式只有综合属性,则翻译与自底向上结合若翻译模式既有综合属性又有继承属性,则翻译与自顶向下结合,6.2 符号表,概述 符号表的组织与内容 非分程序结构语言的符号表组织 分程序结构语言的符号表组织,编译器的逻辑模型,出错处理,语法分析程序,语义分析程序,目标代码生成程序,词法分析程序,中间代码生成程序,代码优化程序,表格管理,编译的前端 (Front End),编译

24、的后端 (Back End),概述,(1) 什么是符号表? 编译过程中,编译程序需要不断汇集和反复查证出现在源程序中各种名字的属性和特征等有关信息。这些信息通常记录在一张或几张符号表中。 符号表的每一项包含两部分: 名字(标识符): 程序名、过程名、函数名、用户定义类型名、变量名、常量名、枚举值名、标号名等。 特性信息: 上述名字的种类、类型、维数、参数个数、数值及目标地址(存储单元地址)等。,概述,(2)建表和查表的必要性(符号表在编译过程中的作用) 源程序中变量要先声明,然后才能引用。 用户通过声明语句,声明各种名字,并给出它们的类型、维数等信息,编译程序在处理这些声明语句时,应该将声明中

25、的名字及其信息登录到符号表中,同时编译程序还要给变量分配存储单元,而存储单元地址也必须登录在符号表中。 当编译程序编译到引用所声明的变量时(赋值或引用其值),要进行语法语义正确性检查(类型是否符合要求)和生成相应的目标程序,这就需要查符号表以取得相关信息。,概述,(3)有关符号表的操作:填表和查表 填表:当分析到程序中的说明或定义语句时,应将说明或定义的名字,以及与之有关的信息填入符号表中。例:Procedure P( ) 查表: (1) 填表前查表,检查在程序的同一作用域内名字是否重复定义; (2) 检查名字的种类是否与说明一致; (3) 对于强类型语言,要检查表达式中各变量的类型是否一致;

26、 (4) 生成目标指令时,要取得所需要的地址。 .,符号表的组织与作用,符号表的基本结构“名字”域: 存放名字,一般为标识符的符号串,也可为指向标识符字符串的指针。 “信息”域: 可包括多个子域, 分别表示标识符的有关信息,,第一项(入口1),第二项(入口2),第N项(入口N),信息域表示标识符的相关信息,名字(标识符)的种类:简单变量、函数、过程、数组、标号、参数等 类型:如整型、浮点型、字符型、指针等 性质:变量形参、值形参等 值: 常量名所代表的数值 地址:变量所分配单元的首址或地址位移 大小:所占的字节数 作用域的嵌套层次: 对于数组: 维数、上下界值、计算下标变量地址所用的信息(数组

27、信息向量)以及数组元素类型等。 对于记录(结构、联合):域的个数,每个域的域名、地址位移、类型等。 对于过程或函数:形参个数、所在层次、函数返回值类型、局部变量所占空间大小等。 对于指针:所指对象类型等。,对符号表可能的操作,在整个编译期间,对符号表的操作大致可以归纳为五类: 对给定的名字,查询此名是否已在表中; 往表中填入一个新的名字 对给定名字,访问它的某些信息; 对给定名字,往表中填写或更新它的某些信息 删除一个或一组无用的项。,符号表的组织方式,1.统一符号表:不论什么名字都填入统一格式的符号表中 符号表表项应按信息量最大的名字设计,填表、查表比较方便, 结构简单, 但是浪费大量空间。

28、 2.对于不同种类的名字分别建立各种符号表 节省空间, 但是填表和查表不方便。 3.折中办法:大部分共同信息组成统一格式的符号表,特殊信息另设附表,两者用指针连接。,符号表的整理和查找,符号表的初始化: 在编译程序刚开始时,符号表或者是空的,或者预先存放了一些保留字和标准函数名的有关项。 在编译的其他阶段,主要是对符号表进行查填的操作: 线性查找方法最简单,但效率低 二叉树查找效率高,但实现上略显困难 Hash表效率最高,可实现比较复杂而且要消耗一些额外的存储空间。,线性表,构造符号表最简单和最容易的办法就是按符号出现的顺序填写各个项。 线性表中每一项的先后顺序是按先来者先填的原则安排的,编译

29、程序不做任何排序的工作。 显式说明的程序设计语言,根据名字在说明部分出现的顺序填入表中(表尾) 隐式说明的程序设计语言,根据各名字首次引用的先后顺序填入表中。 当需要查找某个名字时,就从该表的第一项开始顺序查找。 查表操作的平均长度为(n+1)/2,78,对折查找与二叉树,在造表时把表格中的项按照名字的“大小”顺序整理排列。 这种经顺序整理了的表格的查找可以用对折法。 查表操作的平均长度Log2N 1 对一遍扫描的编译程序来说,符号表是边填边引用的,这意味着每填进一个新项都需要做顺序化的整理工作。 折中办法是把符号表组织成一棵二叉树。 查找效率比对折查找要低一些,但顺序化时间要少很多 需要额外

30、的存储空间。,Hash表,对于表格处理来说,根本问题在于如何保证查表与填表两方面工作都能高效的进行。 线性表:填表快,查表慢; 对折法:填表慢,查表快。 设有一个足够大的区域,可以填写一张含N项的符号表 构造一个地址函数H,对任何名字SYM,H(SYM)取值于0至N-1之间。 对于地址函数H,其计算要简单、高效 函数值能比较均匀的分布在0至N-1之间。 把所有取值相同的项串成一串,便于线性查找。,非分程序结构语言的符号表组织,非分程序结构语言: 每个可独立进行编译的程序单元是一个不包含有子模块的单一模块,如FORTRAN语言。,非分程序结构语言的符号表组织,标识符的作用域 全局:子程序名,函数

31、名和公共区名。 局部: 程序单元中定义的变量。 符号表的组织:,非分程序结构语言的符号表组织,基本处理办法: 1.子程序、函数名和公共区名填入全局符号表。 2.在子程序(函数)声明部分读到标识符,造局部符号表。3.在语句部分读到标识符,查表:,非分程序结构语言的符号表组织,基本处理办法: 4.程序单元结束: 释放该程序单元的局部符号表。 5. 程序编译完成: 释放全部符号表。,编译技术,分程序结构语言的符号表组织,分程序结构语言:模块内可嵌入子模块 标识符的作用域:标识符局部于所定义的模块(最小模块) 模块中所定义的标识符作用域是定义该标识符的子程序,分程序结构语言的符号表组织,分程序结构语言

32、:模块内可嵌入子模块 标识符的作用域:标识符局部于所定义的模块(最小模块) 过程或函数说明中定义的标识符(包括形参)其作用域为本过程体。,分程序结构语言的符号表组织,分程序结构语言:模块内可嵌入子模块 标识符的作用域:标识符局部于所定义的模块(最小模块) 循环语句中定义的标识符,其作用域为该循环语句。不能从循环体外转到循环体内。循环语句应看作一层,分程序结构语言的符号表组织,符号表的处理办法:建查符号表均要遵循标识符的作用域规定进行。 建表:不能重复,不能遗漏 查表:按标识符作用域,分程序结构语言的符号表组织,符号表的处理方法: 1.在程序声明部分读到标识符时(声明性出现),建表:2.在语句中

33、读到标识符(引用性出现),查表:,分程序结构语言的符号表组织,符号表的处理方法: 3.标准标识符的处理 主要是语言定义的一些标准过程和函数的名字,它们是标识符的子集。如sin con abs. 特点: 1) 用户不必声明,就可全程使用 2) 设计编译程序时,标准名字及其数目已知 处理方法: 1) 单独建表:使用不便,费时。 2) 预先将标准名填入名字表中,2019/6/16,当过程和函数体编译完成后,应将与之相应的参数名和局部变量名以及后者的特性信息从符号表中删去。,知识结构,6.3 类型检查,类型体制 静态和动态的类型检查 类型表达式 一个简单的类型检查程序 一个简单地语言 表达式的类型检查

34、 语句的类型检查 类型转换,一般静态检查包括:,(1)类型检查。验证程序中执行的每个操作是否遵守语言的类型系统的过程.,编译程序必须报告不符合类型系统的信息。 (2)控制流检查。控制流语句必须使控制转移到合法的地方。例如,在C语言中break语句使控制跳离包括该语句的最小while、for或switch语句。如果不存在包括它的这样的语句,则就报错。 (3)唯一性检查。在很多场合要求对象只能被定义一次。例如Pascal语言规定同一标识符在一个分程序中只能被说明一次,同一case语句的标号不能相同,枚举类型的元素不能重复出现等等。 (4)关联名字检查。有时,同一名字必须出现两次或多次。例如,Ada

35、 语言程序中,循环或程序块可以有一个名字,出现在这些结构的开头和结尾,编译程序必须检查这两个地方用的名字是相同的。,类 型 检 查,本节内容 静态检查中最典型的部分 类型检查:类型系统、类型检查、多态函数、重载。 忽略其它的静态检查:控制流检查、唯一性检查 、相关名字检查。,类型体制,每个程序设计语言都有自己的类型机制,包括类型说明和使用。类型分析是编译器语义分析的重要组成部分 。编译器首先根据类型说明,确定每一个变量和常量的类型 ,计算其使用存储空间的大小,从而建立其到存储空间的映射。进而,编译器要确定每个语言结构的类型,以完成下面的主要任务: (1) 判定重载算符(函数)在程序中代表的是哪

36、一个运算;(2) 进行类型转换;(3) 对语言结构进行类型检查。,类型检查,类型检查可以分为动态和静态两种。 动态检查在运行时刻完成。功效很低。但是如果语言允许动态确定类型,动态检查是必须的。 静态检查在编译时刻完成。静态检查是高效的。 如果一个语言能够保证经过静态检查之后,程序没有运行时刻的类型错误,则称为强类型的。 类型检查的内容包括: 表达式 语句 函数,1. 类型表达式定义 语言结构的类型由类型表达式表示,类型表达式依赖于程序语言的类型体制。类型表达式或者是简单类型表达式,或者是构造符作用在类型表达式上得到的类型表达式。类型表达式的定义如下: (1) 类型名和基本类型是类型表达式。in

37、teger、char、real、boolean是基本类型,所以它们是类型表达式。另外,void表示“无类型”,type_error表示“出错类型”,它们也是类型表达式。,(2) 类型构造符作用于类型表达式的结果 仍然是类型表达式。类型构造符包括: (a)数组构造符ARRAY:若T是类型表达 式,则ARRAY(I,T)是类型表达式。 (b)笛卡儿乘积:若T1、T2是类型表达 式,则T1 T2是类型表达式,且是左结合的。 (c)记录类型构造符RECORD:若有标识符N1、N2、Nn与类型表达式T1、T2、Tn, 则RECORD(N1 T1) (N2 T2) (Nn Tn)是一个类型表达式,它表示一

38、个记录类型。,1. 类型表达式定义,(d)指针类型构造符POINTER:若T是类型表达式,则POINTER(T)是类型表达式,它表示一个指针类型。 (e)函数类型构造符:若D1、D2、Dn和R是类型表达式,则D1D2 DnR是类型表达式,其中优先于,它表示从定义域类型D1 D2 Dn到值域类型R的映射。 (3) 类型表达式中可出现类型变量,变量的值是类型表达式。,类型构造符还包括:,图:内部结点是类型构造符,叶结点是基本类型,类型名或类型变量。例如,FUNCTION f (a,b:char):integer: charcharpointer(integer),类型表达式的表达方法图,检查运算对

39、象之间的类型是否满足相容条件,函数lookup(e)取符号表中保存在条目e中的类型。 Enum E.type:=integer Eid E.type:=lookup(id.entry) EE1 MOD E2 E.type:=IF (E1.type=integer)AND(E2.type=integer) THEN integer ELSE type_error EE1E2 E.type:=IF(E2.type=integer)AND(E1.type=ARRAY(s,t) THEN t ELSE type_error EE1 E.type:=IF E1.type=POINTER(t) THEN

40、t ELSE type_error表达式的类型检查的翻译模式,表达式的类型检查,语句的类型检查主要包括:赋值语句类型的相容性,控制表达式的结果类型检查。指派给语句的类型是基本类型void,如果在语句中发现类型错误, 指派给语句的类型是type_error。,语句的类型检查,Sid:=E S.type:=IF id.type=E.type THEN void ELSE type_error SIF E THEN S1 S.type:=IF E.type=boolean THEN S1.type ELSE type_error SWHILE E DO S1S.type:=IF E.type=boo

41、lean THEN S1.type ELSE type_error SS1;S2S.type:=IF (S1.type=void)AND(S2.type=void) THEN void ELSE type_error 图65检查语句类型的翻译模式,类型转换,一般的程序设计语言中都规定了某些类型之间的转换关系:比如说整数量可以被当作实数量参与运算,并且不需要程序员显式说明。 不同类型的常数在计算机中有不同的表示。当一个值需要转换成为其它类型使用的时候,需要使用某些代码进行转换。 因此,编译程序要识别需要进行类型转换的地方,并相应地生成代码。 程序设计语言的设计者需要考虑什么情况下需要和可以进行转

42、换。,考虑表达式x +i,其中x是实型,i是整形,它的 后缀式可能是 x i inttoreal real+ 语言的定义会指出必须要做的类型转换。 例如,当整数赋给实型变量时,应该把赋值号右边对 象转换成左边对象的类型。,类型转换,Enum E.type:=integer Enum . num E.type:=real Eid E.type:=lookup(id.entry) EE1 op E2 E.type:=IF (E1.type=integer)AND(E2.type=integer) THEN integer ELSE IF (E1.type=integer)AND(E2.type=r

43、eal) THEN real ELSE IF (E1.type=real)AND(E2.type=integer) THEN real ELSE IF (E1.type=real)AND(E2.type=real) THEN real ELSE type_error 需要强制类型转换的类型检查,“中间代码生成”程序的任务是:把经过语法分析和语义分析而获得的源程序中间表 示翻译为中间代码表示。 方法:语法制导翻译。 采用独立于机器的中间代码的好处:1. 便于编译系统的 建立和编译系统的移植;2. 便于进行独立于机器的代码优化工作。 常见的中间语言形式逆波兰表示法N-元式表示法图表示法,6.4 中

44、间语言,逆波兰表示法(后缀式),特点:运算符直接写在其运算对象之后。 不再有括号 运算对象出现的次序未变 求值过程简单,宜于用栈实现 例: a+b ab+a*b+c ab*c+a*(b+c/d) abcd/+*a*b+c*d ab*cd*+a:=b*c+d*e abc*de*+:=,一般形式:,N-元表示法,OP,ARG1,ARG2,ARGn,每条指令由N个域组成。其中,第一个域OP通常表示操作符,其余的N-1个域表示操作数或中间及最后结果。,对于语句a =b*-c+b*-c 的三种表示方法,(0) (1) (2) (3) (4) (5), * * + =,c b c b t2 t5,arg1

45、,t1t3 t4,arg2,result,t1 t2 t3 t4 t5 a,op,三地址语句的四元式表示,四元式需要利用较多的临时单元,四元式之 间 的联系通过临时变量实现。,(0) (1) (2) (3) (4) (5), * * + =,c b c b (1) a,arg1,(0)(2) (3) (4),arg2,op,三地址语句的三元式表示,三元式中使用指向三元式语句的指针。,(0) (1) (0) (1) (2) (3),间接代码,三地址语句的间接三元式表示,(0) (1) (2) (3), * + =,c b (1) a,arg1,(0) (1) (2),arg2,op,图表示法,图(或语法树)是一种常见的中间代码形式,它描述了源程序的自然层次结构。图的表示方法与前面介绍的逆波兰表示和三元式、四元式表示有密切的关系,相互之间的转换很容易。三元式和逆波兰表示都是树的直接的线性表示,树的后序遍历可以产生逆波兰表示,一个三元式对应一棵二叉子树。,

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


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

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

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