第六章 中间代码生成.pptx

上传人:s****8 文档编号:68961219 上传时间:2022-12-30 格式:PPTX 页数:167 大小:3.04MB
返回 下载 相关 举报
第六章 中间代码生成.pptx_第1页
第1页 / 共167页
第六章 中间代码生成.pptx_第2页
第2页 / 共167页
点击查看更多>>
资源描述

《第六章 中间代码生成.pptx》由会员分享,可在线阅读,更多相关《第六章 中间代码生成.pptx(167页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、HUANG Xiaoxi编译原理编译原理Principle of Compiler第六章 中间代码生成黄孝喜在编译器的“分析-综合”模型中,前端前端对源程序进行分析并产生中间表示,而关于目标机器的细节则在后端后端处理。本章内容涉及中间代码表示、静态类型检查和中间代码生成。2引子引子语法语法 分析器分析器静态检静态检查程序查程序中间代码中间代码生成器生成器代码代码 生成器生成器中间中间代码代码前端前端后端后端“中间代码生成”的任务任务把经过语法分析和语义分析而获得的源程序中间表示翻译为中间代码表示。不同的编译器对中间表示的选择和设计各有不同。中间表示可以是一种真正的语言,也可以是各个处理阶段共享

2、的多个内部数据结构。早期的C+编译器就把C语言作为中间表示方法:语法制导翻译采用独立于机器的中间代采用独立于机器的中间代 码的好处码的好处1.便于编译系统建立和编译系统的移植;2.便于进行独立于机器的代码优化工作。3引子引子中间语言语法树有向非循环图DAG三地址代码表示类型检查常用语句的中间代码生成方法说明语句赋值语句布尔表达式与控制流语句回填4提纲提纲常用的中间代码(语言)语法树后缀式(逆波兰式)三地址代码表示特点形式简单、语义明确、便于翻译独立于目标语言56.1 6.1 中间语言中间语言抽象语法(AbstractSyntax)从具体语法中抽象出抽象出语言结构的本质性的东西,而不考虑语言的具

3、体符号表示,从而可简化语义的形式描述。在不同的语言中赋值语句有不同的写法x=y;x:=y;yx等等可以用抽象形式assignment(variable,expression)把前面各种具体形式统一起来。66.1.16.1.1图表示法图表示法抽象语法(AbstractSyntax)抽象语法树(AST)反映了抽象的语法结构,而分析树反映的是具体语法结构。语法树是分析树的抽象形式或压缩形式。在抽象语法树表示中,每一个叶结点都表示诸如常量或变量这样的运算对象,而其它内部结点则表示运算符。抽象语法树不同于分析树,它展示了一个操作过程并同时描述了源程序的层次结构。76.1.16.1.1图表示法图表示法语法

4、规则中包含的某些符号可能起标点符号标点符号作用作用,也可能起解释作用解释作用。回顾前述的赋值语句,其产生式规则是SV=e其中的赋值号“=”仅仅起标点符号作用,目的是把V和e分隔开而条件语句的产生式规则:SifBthenS1elseS2其中的关键字if、then、else起注释作用,说明当布尔表达式B为真时执行S1语句,否则执行S28抽象语法树抽象语法树赋值语句的本质部分是V和e条件语句的本质部分是B,S1和S2把语法规则中本质部分抽象出来而将非本质部分去掉后,便得到抽象语法规则这种去掉不必要信息的做法可以获得高效的源程序中间表示。上述语句的抽象语法规则为:(1)赋值语句:左部表达式(2)条件语

5、句:表达式语句1语句29抽象语法树抽象语法树根据这种方法得到两种语句的语法树如下:10抽象语法树抽象语法树assignmentvariableexpressionif-then-elseBS1S2赋值语句语法树赋值语句语法树条件语句语法树条件语句语法树在语法树中,运算符号和关键字都不在叶结点,而是在内部在语法树中,运算符号和关键字都不在叶结点,而是在内部结点中出现。结点中出现。赋值语句x=a+b*c的抽象语法树和分析树11抽象语法树抽象语法树assignmentx+a*bc抽象语法树SV=ExE+EaE*Ebc分析树分析树表达式的语法树构建方法(利用语法制导定义)辅助函数:1.mknode(o

6、p,left,right)建立一个运算符号结点,标号是op,两个域left和right指向运算分量结点的指针。2.mkleaf(id,entry)建立一个标识符结点,由标号id标识,一个域entry指向标识符符号表中相应的项。3.mkleaf(num,val)建立一个数结点,标号为num,域val用于存放数的值。返回新建立结点的指针。12抽象语法树抽象语法树建立表达式语法树的语法制导定义13抽象语法树抽象语法树 产生式产生式语义规则语义规则EE1+TE.nptr:=mknode(+,E1.nptr,T.nptr)EE1-TE.nptr:=mknode(-,E1.nptr,T.nptr)ETE.

7、nptr:=T.nptrT(E)T.nptr:=E.nptrTidT.nptr:=mkleaf(id,id.entry)TnumT.nptr:=mkleaf(num,num.val)表达式表达式a-4+c的语法树建立过程的语法树建立过程14ididto entry for ato entry for aididto entry for cto entry for cnum num 4 4idid1 1T T1 1.nptr.nptrE E2 2.nptr.nptrE E1 1.nptr.nptrT T2 2.nptr.nptrT T3 3.nptr.nptridid2 2E.nptrE.npt

8、rnumnum+表达式表达式a-4+c的语法树建立过程的语法树建立过程15ididto entry for ato entry for aididto entry for cto entry for cnum num 4 4建立赋值语句语法树的语法制导定义16抽象语法树抽象语法树 产生式产生式语义规则语义规则Sid:=ES.nptr:=mknode(:=,mkleaf(id,entry),E.nptr)EE1+E2E.nptr:=mknode(+,E1.nptr,E2.nptr)EE1E2E.nptr:=mknode(,E1.nptr,E2.nptr)EE1E.nptr:=mkunode(um

9、inus,E1.nptr)E(E1)E.nptr:=E1.nptrEidE.nptr:=mkleaf(id,id.entry)EnumE.nptr:=mkleaf(num,num.val)赋值语句赋值语句a:=b*c的语法树构建过程的语法树构建过程17id1S.nptrE1.nptr:=E2.nptr*E3.nptrid2E4.nptrid3ididto entry for bto entry for bididto entry for cto entry for cididto entry for ato entry for auminusuminus*:=赋值语句赋值语句a:=b*c的语法

10、树构建过程的语法树构建过程18ididto entry for bto entry for bididto entry for cto entry for cididto entry for ato entry for auminusuminus*:=表达式的有向非循环图表示(DAG,DirectedAcyclicGraphs)用途:提取表达式中的公共子表达式,以取得目标程序的局部优化。方法:执行mknode和mkleaf时,检查是否已有相同的结点,若有,则返回相应结点的指针。与语法树的区别:语法树中公共子表达式由重复的子树表示,而DAG中只用一个子树表示,因此代表公共子表达式的结点有多个父节

11、点196.1.16.1.1图表示法图表示法表达式a+a*(b-c)+(b-c)*d的语法树和DAG206.1.16.1.1图图表示法表示法ididto entry for ato entry for aididto entry for ato entry for aididto entry for bto entry for bididto entry for cto entry for c*ididididto entry for bto entry for bto entry for cto entry for c*ididto entry for dto entry for d表达式a+

12、a*(b-c)+(b-c)*d的语法树和DAG216.1.16.1.1图图表示法表示法p1:=mkleaf(id,entry-a);p2:=mkleaf(id,entry-a);p3:=mkleaf(id,entry-b);p4:=mkleaf(id,entry-c);P5:=mknode(-,p3,p4);P6:=mknode(*,p2,p5);P7:=mknode(+,p1,p6);P8:=mkleaf(id,entry-b);P9:=mkleaf(id,entry-c);P10:=mknode(-,p8,p9);p11:=mkleaf(id,entry-d);P12:=mknode(*,

13、p10,p11);P13:=mknode(+,p7,p12)修改建立表达式语法树的语法制导定义,产生表达式的DAG在构造结点前检查现有结点,若存在相同结点则返回该结点的指针表达式a+a*(b-c)+(b-c)*d的语法树和DAG226.1.16.1.1图图表示法表示法idtoentryforaidtoentryforbidtoentryforc*idtoentryford12345678910111213波兰逻辑学家卢卡西维奇(Lukasiewicz)发明的一种表示法。这种表示法把运算量(操作数)写在前面,把运算符写在后面,因而又称后缀表示法。例如,把a+b写成ab+,把a*(b+c)写成ab

14、c+*。一般,若e1,e2为任意的后缀表达式,为任意双目运算符,则用作用于e1和e2所代表的结果用后缀式e1e2表示。推而广之,为k目运算符,则作用于e1e2ek的结果用e1e2ek来表示。236.1.26.1.2逆波兰式表示法逆波兰式表示法中缀式:a*d+b*c+e24由抽象语法树生成后缀式由抽象语法树生成后缀式+*+ad*ebc抽象语法树抽象语法树后根遍历生成后缀式:ad*bc*+e+25由语法制导定义生成后缀式由语法制导定义生成后缀式产生式产生式语义规则语义规则Sid:=EPrint(id.name|E.code|“:=”)EE1+E2E.code:=E1.code|E2.code|“+

15、”EE1*E2E.code:=E1.code|E2.code|“*”E-E1E.code:=E1.code|“-”E(E1)E.code:=E1.codeEidE.code:=id.nameEnumE.code:=num.val;属性属性code表示生成的代码表示生成的代码后缀表示法的优点:易于计算机处理表达式。常用的算法:使用一个栈,自左至右扫描算术表达式(后缀表示):扫描到运算对象,就把它推进栈;扫描到运算符:p若该运算符是二目的,则对栈顶部的两个运算对象实施该运算,并将运算结果代替这两个运算对象而进栈;p若是一目运算符,则对栈顶元素执行该运算,并以运算结果代替该元素进栈。最后的结果留在栈

16、顶26后缀式的求值后缀式的求值ab+c*的求值(a=1,b=3,c=5)27后缀式的求值后缀式的求值13+5*13+41+3=45*4*5=2020计算完毕,结果为计算完毕,结果为20一般形式x:yopz一般含三个地址(名字、常数、临时变量):两个操作分量和一个结果的抽象地址为方便起见,通常用变量名代替抽象地址如,源语言表达式x+y*z可以被翻译为:t1:=y*zt2:=x+t1其中t1和t2是编译时产生的临时变量286.1.3 6.1.3 三地址代码三地址代码三地址代码与语法树、DAG的关系三地址代码是语法树或DAG的线性表示表达式a+a*(b-c)+(b-c)*d的语法树和DAG对应的三地

17、址代码296.1.3 6.1.3 三地址代码三地址代码t1:=bct2:=a*t1t3:=a+t2t4:=bct5:=t4*dt6:=t3+t5根据语法树根据语法树t1:=bct2:=a*t1t3:=a+t2t4:=t2*dt5:=t3+t4根据根据DAGDAG三地址代码的类型(1)赋值语句x:yopz,op为二目算术算符或逻辑算符(2)赋值语句x:opy,op为一目算符,如一目减uminus、逻辑非not、移位算符及转换算符(3)无条件转移语句gotoL(4)条件转移语句ifxrelopygotoL,关系运算符号relop(,=,=等等)(5)复制语句x:y306.1.3 6.1.3 三地址

18、代码三地址代码三地址代码的类型(6)过程调用语句paramx和callp,n。过程调用语句p(x1,x2,xn)产生如下三地址代码:paramx1paramx2paramxncallp,n过程返回语句returny316.1.3 6.1.3 三地址代码三地址代码三地址代码的类型(7)索引赋值语句:x:=yixi:=y(8)地址和指针赋值语句x:=&yx:=*y*x:=y在设计中间代码形式时,选择多少种算符需要平衡326.1.3 6.1.3 三地址代码三地址代码例子:doi:=i+1;while(aiv);的三地址翻译336.1.3 6.1.3 三地址代码三地址代码L:t1=i+1i=t1t2=

19、i*8t3=at2if(t3v)gotoL100:t1=i+1101:i=t1102:t2=i*8103:t3=at2104:if(t3v)goto100用标签形式用标签形式用标号形式用标号形式假设数组假设数组a中每个元素占用存储单元为中每个元素占用存储单元为8p语法制导翻译生成三地址代码定义几个属性:(1)E.place表示存放E值的名字。(2)E.code表示对E求值的三地址语句序列。(3)newtemp是个函数,对它的调用将产生一个新的临时变量。346.1.3 6.1.3 三地址代码三地址代码35语法制导翻译生成三地址代码语法制导翻译生成三地址代码 产生式产生式语义规则语义规则Sid:=

20、ES.code:=E.code|gen(id.place:=E.place)EE1+E2E.place:=newtemp;E.code:=E1.code|E2.code|gen(E.place:=E1.place+E2.place)EE1*E2 E.place:=newtemp;E.code:=E1.code|E2.code|gen(E.place:=E1.place*E2.place)EE1E.place:=newtemp;E.code:=E1.code|gen(E.place:=uminusE1.place)E(E1)E.place:=E1.place;E.code:=E1.codeEid

21、E.place:=id.place;E.code:=三地址语句序列是语法树的线性表示,用临时变量代替语法树中的结点。实际实现中,三地址语句序列往往是被存放到一个输出文件中,而不是将三地址语句序列置入code属性之中36语法制导翻译生成三地址代码语法制导翻译生成三地址代码 三地址代码的具体实现1.四元式op,arg1,arg2,result2.三元式op,arg1,arg23.间接三元式间接码表+三元式表376.1.3 6.1.3 三地址代码三地址代码三地址代码的具体实现四元式有四个字段,分别称为op,arg1,arg2,result。字段op包含一个运算符的内部编码,如对于三地址指令x=y+z

22、的相应四元式中,op字段存放+,arg1中为y,arg2中为z,result中为x。对于形如x=opy的单目运算符指令和赋值指令x=y,不使用arg2。像param这样的运算既不使用arg2也不使用result。条件或非条件转移指令将目标标号放入result字段386.1.3 6.1.3 三地址代码三地址代码对于语句a:=b*-c+b*-c的三种表示方法39三地址代码的具体三地址代码的具体实现实现t1=uminusct2=b*t1t3=uminusct4=b*t3t5=t2+t4a=t5三地址代码三地址代码oparg1arg2result0uminusct11*bt1t22uminusct33

23、*bt3t44+t2t4t55=t5a四元式四元式对于语句a:=b*-c+b*-c的三种表示方法40三地址代码的具体三地址代码的具体实现实现oparg1arg2 result0uminusct11*bt1t22uminusct33*bt3t44+t2t4t55=t5a四元式四元式oparg1arg20uminusc1*b(0)2uminusc3*b(2)4+(1)(3)5assigna(4)三元式三元式三元式中使用指向三元式语句的指针指向三元式语句的指针。对于语句a:=b*-c+b*-c的三种表示方法41三地址代码的具体三地址代码的具体实现实现oparg1arg20uminusc1*b(0)2

24、uminusc3*b(2)4+(1)(3)5assigna(4)间接三元式表示statement1001(0)1002(1)1003(2)1004(3)1005(4)1006(5)三地址代码三种实现形式的比较代码优化时,经常因调整计算次序而要移动三地址语句四元式调整顺序方便,但引入的临时变量多,需存储空间大三元式需存储空间最小,但调整顺序不便间接三元式优化方便,在有公共子表达式时,需存储空间比四元式小中间代码优化处理时,四元式比三元式方便的多,间接三元式与四元式同样方便,两种实现方式需要的存储空间大体相同。426.1.3 6.1.3 三地址代码三地址代码例:a+b*(c-d)+e/(c-d)n

25、求:1.后缀式2.四元式3.三元式4.间接三元式43中间语言练习中间语言练习例:a+b*(c-d)+e/(c-d)n后缀式abcd-*+ecdn/+三地址代码t1=cdt2=b*t1t3=a+t2t4=cdt5=t4nt6=e/t5t7=t3+t644中间语言练习中间语言练习例:a+b*(c-d)+e/(c-d)n四元式45中间语言练习中间语言练习oparg1arg2 result0-cdt11*bt1t22+at2t33-cdt44 t4nt55/et5a6+t3t6t7t1=cdt2=b*t1t3=a+t2t4=cdt5=t4nt6=e/t5t7=t3+t6例:a+b*(c-d)+e/(c

26、-d)n三元式46中间语言练习中间语言练习oparg1arg2result0-cdt11*bt1t22+at2t33-cdt44 t4nt55/et5a6+t3t6t7oparg1arg20-cd1*b(0)2+a(1)3-cd4(3)n5/e(4)6+(2)(5)例:a+b*(c-d)+e/(c-d)n间接三元式47中间语言练习中间语言练习oparg1arg20-cd1*b(0)2+a(1)3(0)n4/e(3)5+(2)(4)statement1001(0)1002(1)1003(2)1004(0)1005(3)1006(4)1007(5)中间语言语法树有向非循环图DAG三地址代码表示类型

27、检查常用语句的中间代码生成方法说明语句赋值语句布尔表达式与控制流语句回填48提纲提纲每个程序设计语言都有自己的类型机制,包括类型说明和使用。类型检查类型检查是编译器语义分析的重要组成部分。编译器首先根据类型说明,确定每一个变量和常量的类型,计算其使用存储空间的大小,从而建立其到存储空间的映射。进而,编译器要确定每个语言结构的类型,以完成下面的主要任务:(1)判定重载算符(函数)在程序中代表的是哪一个运算(2)进行类型转换(3)对语言结构进行类型检查。如:Pascal语言中对数据类型的使用要进行同一、相容和赋值相容检查496.2 6.2 类型检查类型检查类型表达式语言结构的类型由类型表达式表示。

28、类型表达式依赖于程序语言的类型体制。类型表达式:或者是简单类型表达式,或者是通过类型构造符作用于类型表达式而得到,具体定义如下:(1)类型名和基本类型是类型表达式类型名和基本类型是类型表达式。integer,char,real,boolean是(Pascal语言)基本类型,所以是类型表达式。void表示“无类型”,type_error表示“出错类型”,也是类型表达式。506.2 6.2 类型检查类型检查可以把这一条看作是类型表达式定义的核,然后通过下面的类型构造符来生成更复杂的类型表达式(2)类型构造符作用于类型表达式的结果仍然是类型表达式。类型构造符包括:a)数组构造符ARRAY。如果T是一

29、个类型表达式,则ARRAY(I,T)是类型表达式,指称一个数组类型,T为其成分类型,I是下标值集合b)笛卡尔乘积:若T1,T2是类型表达式,则T1T2也是类型表达式,其中是左结合的。c)记录类型构造符RECORD:若有标识符N1,N2,Nn和类型表达式T1,T2,Tn,则RECORD(N1T1)(N2T2)(NnTn)是类型表达式,指称了一个记录类型。51类型表达式类型表达式(2)类型构造符作用于类型表达式的结果仍然是类型表达式。类型构造符包括:d)指针类型构造符POINTER:若T是一个类型表达式,则POINTER(T)是类型表达式,指称一个指针类型。e)函数类型构造符:若D1,D2,Dn和

30、R是类型表达式,则D1D2DnR是类型表达式,其中的优先级高于,它指称了一个从定义域类型为D1D2Dn到值域类型为R的映射(函数)(3)类型表达式中可以出现类型变量,其值也是类型表达式52类型表达式类型表达式例153类型表达式类型表达式设有设有Pascal程序片段:程序片段:TYPEstype=RECORDname:ARRAY1.8OFchar;score:integerEND;VARtable:ARRAY1.50OFstype;p:stype;则则stype代表的类型表达式代表的类型表达式RECORD(name ARRAY(1.8,char)(score integer)和和table绑定的

31、类型表达式绑定的类型表达式ARRAY(1.50,stype)和和p绑定的类型表达式绑定的类型表达式POINTER(stype)p例例2设有下面的函数定义设有下面的函数定义FUNCTIONf(P1:T1;P2:T2;Pn:Tn):T;BEGINEND;和和f绑定的类型表达式绑定的类型表达式T1 T2 TnT如定义函数如定义函数FUNCTIONf(a,b:char):integer;BEGINEND;F绑定的类型表达式为绑定的类型表达式为charcharPOINTER(integer)54类型表达式类型表达式p例例3在函数式语言中可如下定义恒等函数在函数式语言中可如下定义恒等函数 funf(x)=

32、xx可以是任何类型的语言结构。因此可以是任何类型的语言结构。因此x可以是任可以是任何类型。何类型。f的类型表达式为的类型表达式为 为为类型变量类型变量,其值是任何类型表达式。,其值是任何类型表达式。55类型表达式类型表达式静态类型检查:由编译器完成的检查动态类型检查:目标程序运行时完成的检查如果目标代码把每个对象的类型和该对象的值一起保存,那么任何检查都可以动态完成。如果一种语言的编译器能够保证它所接受的程序不会有运行时的类型错误,则称这种语言是强强类类型语言型语言。有些检查只能动态完成table:array0.255ofchar;i:integer;计算tablei类型检查的内容包括:表达式

33、、语句、函数566.2 6.2 类型检查类型检查变量标识符类型的确定程序是由说明序列和语句序列组成语句序列是计算,说明部分建立计算环境,其中说明了每个变量标识符以及与之绑定的类型文法GP是一个简单的程序语言语法,该程序由一系列声明D和随后的表达式E组成,假设数组的下标从1开始,产生式如下:PD;EDD;D|id:TTchar|integer|ARRAYnumOFT|TEnum|id|EMODE|EE|E576.2 6.2 类型检查类型检查语义分析程序首先处理类型说明,建立类型表达式,然后处理变量说明,建立变量和类型表达式的绑定。具体实现是把变量标识符的类型信息记录在其符号表的表项中,过程add

34、type(id.entry,T.type)完成这个任务,引入综合属性T.type,记录类型表达式。其翻译模式如下:586.2 6.2 类型检查类型检查PD;EDD;DDid:Taddtype(id.entry,T.type)TcharT.type:=charTintegerT.type:=integerTT1T.type:=POINTER(T1.type)TARRAYnumOFT1T.type:=ARRAY(num.val,T1.type)表达式的类型检查检查运算对象之间类型是否满足相容条件。引入综合属性E.type来表示E的类型表达式。596.2 6.2 类型检查类型检查EnumE.type

35、:=integerEidE.type:=lookup(id.entry)函数lookup(e)取符号表中保存在条目e中的类型。表达式的类型检查检查运算对象之间类型是否满足相容条件。引入综合属性E.type来表示E的类型表达式。606.2 6.2 类型检查类型检查EnumE.type:=integerEidE.type:=lookup(id.entry)EE1MODE2E.type:=IF(E1.type=integer)AND(E2.type=integer)THENintegerELSEtype_error一致性检查,假设MOD的运算分量必须是integer,结果也是integer表达式的类

36、型检查检查运算对象之间类型是否满足相容条件。引入综合属性E.type来表示E的类型表达式。616.2 6.2 类型检查类型检查EnumE.type:=integerEidE.type:=lookup(id.entry)EE1MODE2E.type:=IF(E1.type=integer)AND(E2.type=integer)THENintegerELSEtype_errorEE1E2E.type:=IF(E2.type=integer)AND(E1.type=ARRAY(s,t)THENtELSEtype_errorEE1E.type:=IFE1.type=POINTER(t)THENtEL

37、SEtype_error语句的类型检查语句的类型检查主要包括:赋值语句类型的相容性,控制表达式的结果类型检查。指派给语句的类型是基本类型void,如果在语句中发现类型错误,指派给语句的类型是type_error。由于语句中嵌入了表达式,所以在语句的类型检查中总是需要对表达式进行类型检查626.2 6.2 类型检查类型检查检查语句类型的翻译模式636.2 6.2 类型检查类型检查Sid:=ES.type:=IFid.type=E.typeTHENvoidELSEtype_errorSIFETHENS1S.type:=IFE.type=booleanTHENS1.typeELSEtype_erro

38、rSWHILEEDOS1S.type:=IFE.type=booleanTHENS1.typeELSEtype_errorSS1;S2S.type:=IF(S1.type=void)AND(S2.type=void)THENvoidELSEtype_error函数引用的类型检查函数引用的两种情况:标准函数,或者在说明部分定义的函数对说明部分的分析,应该能知道被引用函数的类型,翻译模式为TT1T2T.type:=T1.typeT2.type函数引用可以看作是一个表达式作用于另一个表达式,其类型检查可表示为:EE1(E2)E.type:=IF(E2.type=s)AND(E1.type=st)TH

39、ENtELSEtype_error646.2 6.2 类型检查类型检查函数引用的类型检查函数引用的两种情况:标准函数,或者在说明部分定义的函数对说明部分的分析,应该能知道被引用函数的类型,翻译模式为TT1T2T.type:=T1.typeT2.type函数引用可以看作是一个表达式作用于另一个表达式,其类型检查可表示为:EE1(E2)E.type:=IF(E2.type=s)AND(E1.type=st)THENtELSEtype_error656.2 6.2 类型检查类型检查把单个参数推广到多个参数,类型为T1、T2、Tn的n个变元可以看成类型为T1T2Tn的一个变元。类型转换一般的程序设计语

40、言中都规定了某些类型之间的转换关系:比如说整数量可以被当作实数量参与运算,并且不需要程序员显式说明。不同类型的常数在计算机中有不同的表示。当一个值需要转换成为其它类型使用的时候,需要使用某些代码进行转换。因此,编译程序要识别需要进行类型转换的地方,并相应地生成代码。程序设计语言的设计者需要考虑什么情况下需要和可以进行转换。666.2 6.2 类型检查类型检查表达式:x+i,x为real,i为integer整型数和实型数在计算机中的表示不同,运算的机器指令也不同编译程序必须首先转换一个操作数,以保证类型相同语言定义指出什么转换是必需的赋值语句:把赋值号右边的对象转换成左边对象的类型表达式:把整数

41、转换成实数,然后在这一对实型对象上进行实数运算类型检查器在源程序的中间表示里插入这些转换操作x+i的后缀式可能是:xiinttorealreal+67类型类型转换转换如果从一种数据类型转换成另一种数据类型可以由编译器自动完成,则这种类型转换是隐式的,隐式转换也叫做强制转换。一般要求隐式转换原则上不丢失信息如果转换必须由程序员显式地写在源程序中,则这种转换叫做显式转换。显式的类型转换对类型检查器来说好象函数调用68类型类型转换转换69从整型到实型的类型检查规则从整型到实型的类型检查规则产生式产生式语义规则语义规则EnumE.type:=integerEnum.numE.type:=realEid

42、E.type:=lookup(id.entry)EE1opE2E.type:=IF(E1.type=integer)AND(E2.type=integer)THENintegerELSEIF(E1.type=integer)AND(E2.type=real)THENrealELSEIF(E1.type=real)AND(E2.type=integer)THENrealELSEIF(E1.type=real)AND(E2.type=real)THENrealELSEtype_error说明(声明)语句的翻译作用:说明语句(Declarations)用于对程序中规定范围内使用的各类变量、常数、过程

43、进行说明编译要做的工作 在符号表中建立相应的表项,填写有关的信息。如类型、嵌套深度、相对地址等。相对地址:相对静态数据区基址或活动记录中局部数据区基址的一个偏移值。706.3 6.3 常用语句的翻译常用语句的翻译过程中的说明语句一个过程中的说明语句作为一个类集来处理。用一个全程变量offset来记录下一个数据在符号表中的相对地址。71说明说明(声明声明)语句的语句的翻译翻译类型说明和数组说明的文法和翻译方案PDDD;DDid:TTintegerTrealTarraynumofTTTp引入:全局变量offset,记录下一个可用单元的相对地址T.width:记录名字的域宽T.type:记录名字的类

44、型enter(id.name,T.type,offset):为名字name建立一个符号表表项72说明说明(声明声明)语句的翻译语句的翻译PDDD;DDid:TTintegerTrealTarraynumofT1TT1offset:=0;enter(id.name,T.type,offset);offset:=offset+T.widthT.type:=integer;T.width:=4T.type:=real;T.width:=8T.type:=array(num.val,T1.type);T.width:=num.val T1.widthT.type:=pointer(T1.type);T

45、.width:=4PMDMoffset:=0M称为标记称为标记非终结符非终结符73处理说明语句处理说明语句id1:real;id2:integerPoffset:=0DD1;D2id1:T1realid2:T2T3integerT1.type:=real;T1.width:=8offset:=8namenametypetypeoffsetoffsetid1real0enter(id1,real,0)offset:=offset+874处理说明语句处理说明语句id1:real;id2:integerPoffset:=0DD1;D2id1:T1realid2:T2T3integerT1.type:

46、=real;T1.width:=8T3.type:=integer;T3.width:=4offset:=8offset:=12T2.type:=pointer(T3.type);T2.width:=4namenametypetypeoffsetoffsetid1real0id2pointer(integer)8enter(id2,pointer(integer),8)offset:=offset+4D Tt=T.type;w=T.widthidAid.type=A.type;id.width=A.widthTintT.type:=int;T.width:=4TdoubleT.type:=re

47、al;T.width:=8A A.type=t;A.width=w;A numA1A.type=array(num.value,A1.type;A.width:=num.value A1.widthTT1*T.type:=pointer(T1.type);T.width:=475C语言简单类型声明翻译语言简单类型声明翻译保留作用域信息一般的语言中,标识符的作用在程序正文中有一个确定的范围。因此,同一个标识符在不同的程序正文中可能标识不同的对象,具有不同的性质,要求分配不同的存储空间。提出问题:如何组织符号表,使得同一个标识符在不同的作用域中得到正确的引用而不产生混乱特别是在允许嵌套过程的语言,

48、如Pascal中。我们来考察一下具有嵌套过程说明的程序结构76说明说明(声明声明)语句的翻译语句的翻译77带嵌套过程的带嵌套过程的程序程序(1)programsort(input,output);(2)vara:array0.10ofinteger;(3)x:integer;(4)procedurereadarray;(5)vari:integer;(6)beginaendreadarray;(7)procedureexchange(i,j:integer);(8)begin(9)x:=ai;ai:=aj;aj:x(10)endexchange;(11)procedurequicksort(m

49、,n:integer);(12)vark,v:integer;(13)functionpartition(y,z:integer):integer;(14)vari,j:integer;(15)begina(16)v(17)exchange(i,j);(18)endpartition;(19)beginendquicksort;(20)beginend.sort(2)-(19)都是说明部分都是说明部分过程说明的层次关系过程说明的层次关系:sortreadarrayexchangequicksortpartition78嵌套说明的文法嵌套说明的文法文法PDDD;DDid:TDprocid;D;S

50、其中T用于产生类型,S用于产生语句嵌套说明的程序结构首先要解决的问题是局部数局部数据和非局部数据的访问据和非局部数据的访问解决方法:为每一个过程建立一张符号表所有正在翻译过程的符号表组成整个源程序的符号表。翻译语句部分时查找符号表,查找过程的符号表的路线相当于当前被 翻译过程的静态链。79保留作用域信息保留作用域信息具体翻译时,每当碰到过程说明Dprocid;D1;S时,便创建一张符号表,并且把D1中的所有说明都填入此符号表中新表中有一个指针,指向其直接外围过程符号表,用于解决非局部数据的访问过程名id 作为直接外围过程的局部名字记录在直接外围过程符号表中;同时还要在直接外围过程符号表中增加一

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 生活常识

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁