收藏 分享(赏)

第7章语义分析.ppt

上传人:jinchen 文档编号:9863130 上传时间:2019-09-12 格式:PPT 页数:72 大小:589.50KB
下载 相关 举报
第7章语义分析.ppt_第1页
第1页 / 共72页
第7章语义分析.ppt_第2页
第2页 / 共72页
第7章语义分析.ppt_第3页
第3页 / 共72页
第7章语义分析.ppt_第4页
第4页 / 共72页
第7章语义分析.ppt_第5页
第5页 / 共72页
点击查看更多>>
资源描述

1、1,第七章 语义分析,语法制导翻译技术应用于语义分析 语义处理的工作,2,7.1 中间代码,源程序经过语义分析被译成中间代码序列 用中间语言过渡的好处: 与目标机无关 便于编译系统的实现、移植、代码优化,3,常用的中间代码(语言),三地址代码(三元式、四元式) 语法(结构)树 后缀式逆波兰表示 特点 形式简单、语义明确、便于翻译 独立于目标语言,4,7.1.1后缀式(逆波兰表示),操作数 1 操作数 2 运算符 操作数 运算符 定义: E(常、变量)的后缀式为E自身 E1 op E2 的后缀式为E1E2op (E)的后缀式为E的后缀式 例 : a := b *(- c)+ b *(- 34)的

2、后缀式 a b c - * b 34 - * + :=,5,生成后缀式的属性文法,6,生成后缀式的算法,自顶向下方法:递归下降识别程序.当输入符是常、变量或运算符时,输出到后缀式区,E TE1 E 1+ TE1 | T FT1 T1*FT1 | F (E) | i,Procedure E1; if ch=+then getchar;T;E; Write(+) ,Procedure F; if ch=ithen getchar;write(i) Else if ch=(then getchar;E;if ch=)then getchar else error Else error,7,自底向上方

3、法:算符优先方法 数据结构:运算符栈;后缀式栈 ;输入流Tj,算法:1、若Tj=运算对象,则Tj入栈,j:=j+1; 2、若Tj=运算符,则比较 (i)和Tj的优先关系: (1)若 (i)Tj则Tj入栈,j:=j+1;(2)若(i)Tj则(i)出栈,入栈; 3、若Tj=(,则Tj入 栈,j:=j+1; 4、若Tj=),则 (1)若(i)=(则(i)出栈, j:=j+1;(去括弧); (2)否则, (i)出栈,入栈 5、若Tj=#且(i)=#,OK,8,将规则式中操作符作为分支(父)结点,将操作数作为叶结点。,7.1.2抽象语法树,例 :表达式 (A - 12) * B + 6 的语法结构树,9

4、,建立抽象语法树,属性设置: E.p, T.p, F.p是语法结构树指针 id.entry 是名字的表项入口 num.val 是数值 基本函数结点构造 mknode 建中间结点 mkleaf 建叶结点,10,语法制导定义(属性文法),11,例 X := i1+i2*i3 的语法结构树,root,生成抽象语法树的中间代码: P1:=mkleaf( i1 , i1.entry); P2:=mkleaf( i2 , i2.entry); P3:=mkleaf( i3 , i3.entry); P4:=mknode(*,p2,p3); P5:=mknode(+,p1,p4); P6:= mknode(

5、:=,mkleaf(x,x.entry),p5),12,7.1.3三地址代码,一般形式 x := y op z 其中 x, y, z 为变量名、常数或编译产生的临时变量 四元式(op, y, z, x) 三元式(op, y, z),种类:x := y op z 双目运算x := op y 单目运算x := y 复制语句,13,其它语句的三地址代码,if x relop y goto l 条件转移语句goto l 无条件转移param x 实在参数call p, n 过程调用return x 过程返回x := yi 数组运算 xi := yx := &y 指针运算x := *y*x = y,14

6、,表达式的四元式表示,算符 操作数 操作数临时变量,a := b * (- c) + b * (- 34),15,地址 算符 操作数 操作数 (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10),表达式的三元式表示,a := b * (- c) + b * (- 34),16,生成三地址代码的属性文法,17,7.2 说明语句翻译,高级语言中的说明语句(Declarations)用于对程序中规定范围内使用的各类变量、常数、过程进行说明 类型 基本类型/内部类型(built-in) 用户定义类型结构描述 作用域 一般:说明所在的分程序、过程,18,文法描述,P

7、D D D ; D D id : T T integer T real T arraynum of T1 T T1,例如: a:integer; b:real; c:array10of real,7.2.1变量说明的翻译,定义整型数据占4 BYTE; 实型数据占8BYTE;,19,变量说明的翻译,在符号表中填写变量的属性 种别、类型、相对地址、作用域等 相对地址 全局变量表示为静态数据区的相对于基址偏移值(offset) 局部变量表示为局部数据域的偏移值,20,例 7-1:相对地址举例,名字 相对地址 x 0 i 64 j 68,0 856 64 68,Begin real x8; integ

8、er i, j; end,21,属性、过程、与全局量,类型T的属性 type 类型 width 占用的字节数 基本子程序 insert:设置变量的类型和地址,填表 array:数组类型处理 全局量 offset:已分配空间字节数,22,P D D D ; D D id : TT integer T real T array num of T1 T T1,说明语句的翻译模式, offset := 0 ,insert( id.entry, T.type, offset ); offset := offset + T.width,T.type := integer; T.width := 4,T.t

9、ype := real; T.width := 8,T.type := array( num.val, T1.type); T.width := num.val * T1.width,T.type := pointer( T1.type); T.width := 4,23,例 7-2:x:real; i:integer 的翻译,insert(x,real,0),offset=0,offset=8,T.type=real T.width=8,offset=12,T.type=integer T.width=4,insert(i,integer,8),24,为了使所有的语义动作都在规则式末尾,从而

10、实现自底向上的计算属性值,在文法中引进标记非终极符,说明语句的翻译模式,P D D D ; D, offset := 0 ,P MD M D D ; D, offset := 0 ,25,7.2.2 过程说明的翻译,文法描述,P D D D ; D D id : T D proc id;D;S T integer T real T arraynum of T1 T T1,当碰到过程说明 D proc id;D;S时,创建一张新符号表,26,数据结构: 符号表指针栈 tblptr 相对地址栈 offset 基本子程序 Mktable(previous):创建一张新符号表,返回指针 Enter(t

11、able,name,type,offset):建立新项。 Addwidth(table,width):将table 所指表中所有名字占用的总宽度记录在表头。 Enterpro(table,name,newtable):为过程名name 建立表项。,27,P MDM D id : T D proc id;ND;S N , addwidth(top(tblptr), top(offset); Pop(tblptr); pop(offset),t:=mktable(nil); push(t, tblptr); push(0,offset),enter(top(tblptr), id.name, T.

12、type, top(offset) ); top(offset) := top(offset) + T.width,t:= top(tblptr);addwidth(t, top(offset); Pop(tblptr) ;pop(offset);Enterproc(top(tblptr), id.name,t),t:=mktable(top(tblptr); push(t, tblptr); push(0,offset),28,7.3.1简单赋值语句的翻译,基本子程序 产生一条中间代码 gen(code) 产生新的临时变量 newtemp 属性设置 中间代码序列 code 存储位置 plac

13、e,7.3赋值语句的翻译,29,赋值语句的四元式翻译,S id := E S.code := E.code | gen( id.place:=E.place ) E E1 + E2 E.place := newtemp; E.code := E1.code | E2.code | gen(E.place:=E1.place+E2.place) E E1 * E2 E.place := newtemp; E.code := E1.code | E2.code | gen(E.place:=E1.place*E2.place),注释: | 表示代码序列的连接,30,E - E1 E.place :

14、= newtemp; E.code := E1.code | gen(E.place:=-E1.place) E ( E1 ) E.place:= E1.place; E.code:= E1.code E id E.place:= id.place; E.code:= E num E.place:= num.val;E.code:= ,31,例 : 翻译 a:= -c+b*34,32,a:= -c+b*34的中间代码的生成过程,S.code = E.code | gen( a:=E.place )/* a id.place */ = E1.code | E2.code | gen( t1:=E

15、1.place+E2.place ) | gen( a:=t1 )/* newtemp t1 E.place */ = E11.code | gen( t2:= - E11.place ) /* newtemp t2 E1.place */,33,| E21.code | E22.code | gen( t3:= E21.place*E22.place )/* newtemp t3 E2.place */| gen( t1:=t2+t3 ) | gen( a:=t1 ) = gen( t2:= - c ) | gen( t3:=b*34 ) /* c E11.place */* b E21.p

16、lace */* 34 E22.place */| gen( t1:=t2+t3 ) | gen( a:=t1 )/* E21.code E22.code */,34,7.3.2数组元素的引用,数组元素的翻译 完成上下界检查 生成代码完成相对地址的计算 目标 x := yi 和 yi := x y为数组地址的固定部分,i是相对地址,不是数组下标,35,数组元素地址计算-按行存放,一维数组Alow1:up1 (nk=upk-lowk) Addr(Ai)=base+(i- low1)*w=(base- low1*w)+i*w=c+i*w 二维数组Alow1:up1 , low2:up2Ai1,i2

17、 Addr(Ai1,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)*w,36,文法: SL:=E EL EE+E E(E) Lid LElist ElistidE ElistElist1,E,属性设置: E.place是存放E的值的名字; L.place 是数组地址的固定部分: (1)若L是简单名字,则L.pl

18、ace: =id.place ,且L.offset =null; (2)若L是数组引用,则数组地址为L.placeL.offset ; Elist.ndim 是下标表达式个数; Elist.place是存放下标表达式值的名字; Elist.array是数组名在符号表中的地址; 函数limit(array,j)返回数组第j维的长度。,37,SL:=E EL EE1+E 2E(E1) Lid,if L.offset=null then gen(L.place:=E.place) else gen(L.placeL.offset:=E.place,if L.offset=null then E.pl

19、ace:=L.place else E.place:=newtemp;gen(E.place:=L.placeL.offset),E.place:=newtemp; gen(E.place:=E1.place+ E2.place),E.place:= E1.place ,翻译模式,L.place:=id.place; L.offset:=null,38,ElistidEElistElist1,ELElist,Elist.place:=E.place;Elist.ndim:=1;Elist.array:=id.place,t:=newtemp;m:=Elist1.ndim+1; gen(t:=E

20、list1.place*limit(Elist.array,m); gen(t:=t+E.place); Elist.array:=Elist1.array; Elist.place:=t;Elist.ndim:=m,L.place:=newtemp;L.offset:=newtemp; gen(L.place:= Elist.array-c); gen(L.offset:=Elist.place*w),39,例:已知有数组定义 A:array16of integer; B: array12,13of integer; 写出赋值语句Ai:=Bj,j+k和Ai+j:=Bi,j的三地址代码,通过对

21、语法树的深度优先遍历,可得到中间代码。,40,7.4简单布尔表达式的翻译,布尔表达式的作用: (1)计算逻辑值 (2)用在控制语句中,如:a or b and c 的三地址代码: T1:=b and c T2:=a or T1,如:ab 的三地址代码: 1: if ab goto 4 2: T:=0 3: goto 5 4: T:=1 5:,41,E E1 and E2 E E1 or E2 E not E1E (E) E id1 relop id2,下一条语句的地址,翻译模式, E.place:=newtemp; Gen(E.place:= E1.place and E2.place ,E.

22、place:=newtemp; Gen(E.place:= notE1.place ,E.place:=E1.place, E.place:=newtemp; gen( if id1.place relop.op id2.place gotonext+3 ) ; Gen(E.place := 0); Gen(goto next+2 ); Gen(E.place := 1),42,例:表达式 ab and cd 的三地址代码,1: if ab goto 4 2: T1:=0 3: goto 5 4: T1:=1 5: if cd goto 8 6: T2:=0 7: goto 9 8: T2:=

23、1 9:T3:=T1 and T2,43,布尔表达式出现在条件语句中,要确定转向的语句标号,If E then S1 else S2,若E为 a relop b ,E.code:= If a relop b goto E.true Goto E.false,若E为 E1 or E2,E.code:=E1.code E1.false:E2.code,若E为 E1 and E2,E.code:=E1.code E1.true:E2.code,44,E id1 relop id2 E E1 and E2E E1or E2,E1.true:=E.true; E1.false:=newlable; E2

24、.true:=E.true; E2.false:=E.false; E.code := E1.code | gen(E1.false :) | E2.code,属性文法,E.code := gen( if id1.place relop.op id2.place gotoE.true ) | gen( gotoE.false ),E1.false:=E.false; E1.true:=newlable; E2.true:=E.true; E2.false:=E.false; E.code := E1.code | gen(E1.true :) | E2.code,45,7.5 控制语句的翻译,

25、高级语言的控制结构 顺序 begin 语句; 语句; end 条件 if_then_else if_thenswitch case 循环 while_do do_while for repeat_util 三地址代码的控制结构 goto l if x relop y goto l,46,S if C then S1 else S2 的翻译,属性设置 布尔式 C 代码段真出口 true 代码段假出口 false 语句 S 代码段的入口 begin 后续段入口 next 属性关系 S1.begin = C.true S2.begin = C.false S1.next = S2.next = S.

26、next,47,条件语句的属性文法,S if C then S1 C.true := newlabel; else S2 C.false := newlabel;S1.next := S2.next := S.next;S.code := C.code | gen( C.true: ) |S1.code | gen( goto S.next ) |gen( C.false: ) | S2.code 语义过程 新标号的产生 newlabel,48,S while C do S1 的翻译,语句等价于: If C then Begin S1 Goto C标号 end,49,循环语句的属性文法,S w

27、hile C do S1 C.false := S.next; S.begin := newlabel;C.true := newlabel;S1.next:=s.beginS.code := gen( S.begin: ) | C.code |gen( C.true: ) | S1.code |gen( gotoS.begin ),50,例 :翻译下列语句,while a y do z := x + 1;elseS12 x := y,S1,51,生成的三地址代码序列,L1: if a y goto L5goto L6 L5: t1 := x + 1z := t1goto L3 L4: x :

28、= y L6: goto L1 Lnext:,C.code,C1.code,S11.code,S12.code,S1.code,52,表示为四元式,If a goto p 表示为(j,a, ,p) If xy goto p 表示为(j,x,y ,p) Goto p表示为(j, ,p),53,L1: if a y goto L5goto L6 L5: t1 := x + 1z := t1goto L3 L4: x := y L6: goto L1 Lnext:,1: (j ,x ,y , ) 6: (j , , , ) 7: (+,x1,1,T1) 8: (:=,T1, ,z) 9:(j , ,

29、 , ) 10: (:=,y, ,x) 11: (j , , , ),3,12,5,10,7,11,5,1,54,拉链与回填 实施时需要解决两个问题:在一次遍历中 如何实现表达式的真、假出口; 如何在语法分析的同时正确生成三地址码序列,即所有的转向均可确定。,55,基本思想:当三地址码中的转向不确定时,将所有转向同一地址的三地址码拉成一个链,一旦所转向的地址被确定,则沿此链将所有的三地址码中回填入此地址。,新增两个属性:属性.tc:真出口链,链接所有转向真出口的三地址码; 属性.fc:假出口链,链接所有转向假出口的三地址码。,56,引入下述的过程来实现三地址码上的拉链与回填操作:函数mkcha

30、in(i):为序号为i的三地址码构造一个新链,且返回指向该链的指针;函数merge(P1,P2):将两个链P1和P2合并,且P2成为合并后的链头,并返回链头指针;过程backpatch(P,i):将P链中相应域中的所有链域均回填为i值。,57,例:假设有两个序号分别为i和j的三地址码(i)goto和(j)goto。操作p1:=mkchain(i)和p2:=mkchain(j)之后所生成的链如图 (a)所示;操作p2:=merge(P1, P2)之后的链如图 (b)所示;操作backpatch(P2, k)之后的三地址码如图 (c)所示。,图:三地址码链上的操作 (a) 链的建立;(b) 链的合

31、并;(c) 地址的回填,58,将文法改写为:E E or M E | E and M E | not E | (E) | id relop id | id | true | false M 同时,为M引入一个新的属性.stat,它记录当前第一个可用三地址码的序号。 引入变量nextstat,下一条将要产生的三地址码的序号,初值为1。每执行一次emit后自动加1,59,语义规则可设计如下: (1) M M.stat := nextstat; (2) E E1 or M E2 backpatch(E1.fc, M.stat); E.tc := merge(E1.tc, E2.tc); E.fc :

32、= E2.fc; (3) | E1 and M E2 backpatch(E1.tc, M.stat); E.fc := merge(E1.fc, E2.fc); E.tc := E2.tc; (4) | not E1 E.tc := E1.fc; E.fc := E1.tc; (5) | (E1) E.tc := E1.tc; E.fc := E1.fc; ,60,| id1 relop id2 E.tc := mkchain(nextstat); E.fc := mkchain(nextstat+1); emit(if id1.place relop.op id2.place goto )

33、; emit(goto ); | id E.tc := mkchain(nextstat); E.fc := mkchain(nextstat+1); emit(if id.place goto );emit(goto ); (8) | true E.tc := mkchain(nextstat); E.fc:=mkchain( ); emit( goto );(9) | false E.fc := mkchain(nextstat); E.tc:=mkchain( ); emit( goto );,61,考虑布尔表达式ab or cd and ef。设nextstat初值为1,由于分析树中E

34、5的真、假值链分别是(5, 1)和(6, 4),所以在后继的分析中,一旦E5的真、假出口被确定,就可以沿这两个链正确回填。,62,ab or cd and ef,63,拉链/回填技术处理控制语句 需要引入两个新的属性:属性.nc:记录语句结束后的转向,如果若干个语句结束后转向同一地方,则用此属性将它们链在一起,从而记录下完整语句结构中结束的所有出口。属性.begin:某三地址码序号,如while语句三地址码序列的首地址。,64,条件转移的语法制导翻译如下:,(1) M M.stat := nextstat; (2) S if E then M S1 backpatch(E.tc, M.stat

35、); S.nc := merge(E.fc, S1.nc); (3) N N.nc := mkchain(nextstat); emit(goto ); (4) S if E then M1 S1 N else M2 S2 backpatch(E.tc, M1.stat); backpatch(E.fc, M2.stat);S.nc := merge(S1.nc, merge(N.nc, S2.nc); (5) S while M1 E do M2 S1 backpatch(S1.nc, M1.stat); backpatch(E.tc, M2.stat);S.nc := E.fc; emit

36、(goto M1.stat); (6) SA S.nc := mklist( ); ,65,例:将语句if ab then while ab do a := a+b翻译成三地址码。整个语句的出口由S3.nc指示,它包括(2)和(4)。简化的注释分析树如图所示。,66,67,7.6类型检查,类型系统(类型表达式) 基本类型是类型表达式;type_error 、void 类型名是类型表达式; 类型构造符作用于类型表达式。,68,类型表达式举例,数组 Var A: array1100 of real; A 可表示为类型表达式:array(1100,real) 函数 function F (a,b:c

37、har):integer; F 可表示为类型表达式: char char pointer(integer),69,记录 TYPE person=RECORDname:array18 of char;sex: boolean;age:integer;END; VAR table: array150 of person; person 可表示为类型表达式: record ( (name array(18,char) (sex boolean) (age integer) ) table可表示为类型表达式:array(150,person),类型表达式举例,70,类型检查 1、表达式 E num E

38、 num.num E id E E1 op E2, E.type:=int E.type:=real E.type:=gettype(id.entry) , If E1.type=int and E2.type=int then E.type:=int Else if E1.type=int and E2.type=realthen E.type=:real Elae if Else E.type:=type_error ,71,类型检查 1、表达式E E1 E2E E1E E1( E2), if E2.type=s and E1.type=s t then E.type:=t else E.

39、type=:type_error , if E2.type=int and E1.type=array(s,t) then E.type:=t else E.type=:type_error , if E1.type=pointer(t) then E.type:=t else E.type:=type_error ,72,类型检查 2、语句 S id:=E if E.type=id.type then S.type:=voidelse S.type:=type_error 或类型相容 S if E then S1 if E.type=boolean then S.type:=S1.typeelse S.type:=type_error S while E then S1 if E.type=boolean then S.type:=S1.typeelse S.type:=type_error,

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

当前位置:首页 > 企业管理 > 管理学资料

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


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

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

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