编译原理:第7章 语义分析与中间代码生成_第1页
编译原理:第7章 语义分析与中间代码生成_第2页
编译原理:第7章 语义分析与中间代码生成_第3页
编译原理:第7章 语义分析与中间代码生成_第4页
编译原理:第7章 语义分析与中间代码生成_第5页
已阅读5页,还剩121页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第7章 语义分析与中间代码生成School of Computer Science & Technology Harbin Institute of Technology重点:三地址码,各种语句的目标代码结构、 语法制导定义与翻译模式。 难点:布尔表达式的翻译,对各种语句的目标 代码结构、语法制导定义与翻译模式的 理解。2022/7/172第7章语义分析与中间代码生成 7.1 中间代码的形式7.2 声明语句的翻译7.3 赋值语句的翻译7.4 类型检查7.5 控制结构的翻译7.6 回填7.7 switch语句的翻译7.8 过程调用和返回语句的翻译7.9 输入输出语句的翻译7.10 本章小结202

2、2/7/1737.1 中间代码的形式中间代码的作用过渡:经过语义分析被译成中间代码序列中间代码的形式中间语言的语句中间代码的优点形式简单、语义明确、独立于目标语言便于编译系统的实现、移植、代码优化常用的中间代码语法树(6.3.5节)逆波兰表示、三地址码(三元式和四元式)、DAG图表示2022/7/1747.1.1 逆波兰表示 中缀表达式的计算顺序不是运算符出现的自然顺序,而是根据运算符间的优先关系来确定的,因此,从中缀表达式直接生成目标代码一般比较麻烦。 波兰逻辑学家J. Lukasiewicz于1929年提出了后缀表示法,其优点为:表达式的运算顺序就是运算符出现的顺序,它不需要使用括号来指示

3、运算顺序。2022/7/1757.1.1 逆波兰表示 例7.1 下面给出的是一些表达式的中缀、前缀和后缀表示。中缀表示前缀表示后缀表示a+b+abab+a*(b+c) *a+bcabc+*(a+b)*(c+d) *+ab+cd ab+cd+*a:=a*b+c*d :=a+*ab*cd abc*bd*+:=2022/7/1767.1.2 三地址码 所谓三地址码,是指这种代码的每条指令最多只能包含三个地址,即两个操作数地址和一个结果地址。 如x+y*z三地址码为:t1 := y*z t2 := x+t1三地址码中地址的形式:名字、常量、编译器生成的临时变量。2022/7/1777.1.2 三地址码

4、 例7.2 赋值语句a:=(-b)*(c+d)-(c+d)的三地址码如图7.1所示 t1 := minus bt2 := c+dt3 := t1*t2t4 := c+dt5 := t3-t4a := t5图7.1 a:=(-b)*(c+d)-(c+d)的三地址码2022/7/1787.1.2 三地址码 1形如x:=y op z的赋值指令;2形如x:= op y的赋值指令;3形如 x := y的复制指令;4无条件跳转指令goto L;5形如 if x goto L (或if false x goto L)的条件跳转指令;6形如if x relop y goto L的条件跳转指令;7过程调用和返回

5、使用如下的指令来实现:param x用来指明参数;call p, n和y=call p, n用来表示过程调用和函数调用;return y表示过程返回;8形如x := yi和xi := y的变址复制指令;9形如x := &y、x := *y和*x := y的地址和指针赋值指令。2022/7/179四元式 四元式是一种比较常用的中间代码形式,它由四个域组成,分别称为op、arg1、arg2和result。op是一个一元或二元运算符,arg1和arg2分别是op的两个运算对象,它们可以是变量、常量或编译器生成的临时变量,运算结果则放入result中。 图7.2(a) 图7.1中三地址码的四元式表示2

6、022/7/1710三元式 为了节省临时变量的开销,有时也可以使用只有三个域的三元式来表示三地址码。三元式的三个域分别称为op,arg1和arg2,op,arg1和arg2的含义与四元式类似,区别只是arg1和arg2可以是某个三元式的编号(图7.2(b)中用圆括号括起来的数字),表示用该三元式的运算结果作为运算对象。 图7.2(b) 图7.1中三地址码的三元式表示2022/7/1711生成三地址码的语法制导定义2022/7/17127.1.3 图表示 类似于表达式的抽象语法树一样,在dag(directed acyclic graph)中,每个节点对应一个运算符,代表表达式的一个子表达式,其

7、子节点则与该运算符的运算对象相对应,叶节点对应的是变量或者常量,可以看成是原子运算。利用dag可以很容易地消除公共子表达式例7.3 表达式a+a*(b-c)-(b-c)/d的dag如图7.5所示。 图7.5 a+a*(b-c)-(b-c)/d的dag图2022/7/1713生成dag的语法制导定义产生式语义规则 E E1 + TE.node := mknode(+, E1.node, T.node) E E1 - TE.node := mknode(-, E1.node, T.node) E TE.node := T.node T T1 * FT.node := mknode(*, T1.no

8、de, F.node) T T1 / FT.node := mknode(/, T1.node, F.node) T FT.node := F.node F (E ) F.node:= E.node F idF.node := mkleaf(id, id.entry) F numF.node := mkleaf(num, num.val)2022/7/17147.2 声明语句的翻译声明语句的作用为程序中用到的变量或常量名指定类型 类型的作用 类型检查:类型检查的任务是验证程序运行时的行为是否遵守语言的类型的规定,也就是是否符合该语言关于类型的相关规则。辅助翻译:编译器从名字的类型可以确定该名字

9、在运行时所需要的存储空间。在计算数组引用的地址、加入显式的类型转换、选择正确版本的算术运算符以及其它一些翻译工作时同样需要用到类型信息。编译的任务在符号表中记录被说明对象的属性(种别、类型、相对地址、作用域等) ,为执行做准备2022/7/17157.2.1 类型表达式 类型可以具有一定的层次结构,因此用类型表达式来表示。类型表达式的定义如下:1基本类型是类型表达式。典型的基本类型包括boolean、char、integer、real及void等。2类型名是类型表达式。3将类型构造符array应用于数字和类型表达式所形成的表达式是类型表达式。如果T是类型表达式,那么array(I, T)就是元

10、素类型为T、下标集为I的数组类型表达式。4如果T1和T2是类型表达式,则其笛卡尔乘积T1T2也是类型表达式。 2022/7/17167.2.1 类型表达式 5类型构造符record作用于由域名和域类型所形成的表达式也是类型表达式。记录record是一种带有命名域的数据结构,可以用来构成类型表达式。例如,下面是一段Pascal程序段:type row = recordaddress: integer;lexeme: array1.15 of charend;var table : array 1.10 of row;该程序段声明了表示下列类型表达式的类型名row:record (addressi

11、nteger)(lexemearray (1.15, char)2022/7/17177.2.1 类型表达式 6如果T是类型表达式,那么pointer(T)也是类型表达式,表示“指向类型为T的对象的指针”。函数的类型可以用类型表达式DR来表示。考虑如下的Pascal声明:function f(a,b: char): integer;其定义域类型为charchar,值域类型为pointer(integer)。所以函数f的类型可以表示为如下的类型表达式:charcharpointer(integer)7类型表达式可以包含其值为类型表达式的变量。 2022/7/17187.2.2 类型等价 许多类型

12、检查的规则都具有如下的形式:if两个类型表达式等价then返回一种特定类型else返回type_error。 如果用图来表示类型表达式,当且仅当下列条件之一成立时,称两个类型T1和T2是结构等价的:T1和T2是相同的基本类型;T1和T2是将同一类型构造符应用于结构等价的类型上形成的;T1是表示T2的类型名。如果将类型名看作只代表它们自己的话,则上述条件中的前两个将导致类型表达式的名字等价两个类型表达式名字等价当且仅当它们完全相同 2022/7/17197.2.3 声明语句的文法 P prog id (input, output) D ; SD D ; D | List : T | proc i

13、d D ; SList List1, id | idT integer | real | array C of T1 | T1 | record DC num C | D 程序说明部分的抽象S 程序体部分的抽象T 类型的抽象,需要表示成类型表达式C 数组下标的抽象2022/7/1720语义属性、辅助过程与全局变量的设置文法变量T(类型)的语义属性type: 类型(表达式)width:类型所占用的字节数辅助子程序enter:将变量的类型和地址填入符号表中array:数组类型处理子程序全局变量offset:已分配空间字节数,用于计算相对地址2022/7/17217.2.4 过程内声明语句的翻译P

14、offset := 0 DDD ; DDid : T enter( , T.type, offset ); offset := offset + T.widthTinteger T.type := integer; T.width := 4Treal T.type := real; T.width := 8Tarray num of T1 T.type := array( num.val, T1.type); T.width := num.val * T1.widthTT1 T.type := pointer( T1.type); T.width := 4PMDM offset

15、:= 0 2022/7/1722例 x:real; i:integer 的翻译enter(x,real,0)offset=0offset=8T.type=realT.width=8offset=12T.type=integerT.width=4enter(i,integer,8)Did : T enter( , T.type, offset ); offset := offset + T.width2022/7/1723例 x:real; i:integer 的翻译Poffset:=0Doffset:=0D;Doffset:=0 x:Tenter(x,T.type,offset)

16、; offset:=offset+T.width;Doffset:=0 x:realT.type:=real;T.width:=8 enter(x,T.type,offset);offset:=offset+T.width;Dx:real(x,real,0);offset:=8;Dx:real(x,real,0);offset:=8;i:T enter(,T.type,offset); offset:=offset+T.widthx:real(x,real,0);offset:=8;i:integerT.type:=integer;T.width:=4enter(i,T.type

17、,offset);offset:=offset+T.widthx:real(x,real,0);i:integer(i,integer,8);offset:=122022/7/17247.2.5 嵌套过程中声明语句的翻译所讨论语言的文法P prog id (input, output) D ; S D D ; D | id : T | proc id D ; S 语义动作用到的函数mktable(previous):创建一个新的符号表;enter(table, name, type, offset) addwidth(table, width):符号表的大小;enterproc(table,

18、name, newtable) 在table指向的符号表中为name建立一个新表项;2022/7/1725P prog id (input,output) M D; S addwidth (top(tblptr), top(offset); pop(tblptr); pop(offset) M t := mktable(nil);push(t,tblptr); push(0,offset) D D1 ; D2D proc id ;N D1; S t := top(tblptr); addwidth(t,top(offset);pop(tblptr);pop(offset); enterproc

19、(top(tblptr),,t) Did:T enter(top(tblptr),,T.type,top(offset); top(offset):=top(offset)+ T.widthN t := mktable(top(tblptr) ); push(t,tblptr); push(0,offset) 7.2.5 嵌套过程中声明语句的翻译2022/7/1726program sort(input,output);var a:array0.10 of integer; x:integer; procedure readarray;var i:integer;

20、begin aend;procedure exchange(i,j:integer);begin x:=ai;ai:=aj;aj:=x;end;procedure quicksort(m,n:integer);var k,v:integer;function partition(y,z:integer):integer;var i,j:integer;begin a v exchange(i,j)end;begin end;begin end;例 一个带有嵌套的pascal程序(图7.11)2022/7/1727表 头空sortoffsettblptrtoptop02022/7/1728表 头

21、空sortoffsettblptrtoptop40a array 02022/7/1729x integer 40a array 0表 头空sortoffsettblptrtoptop442022/7/1730表 头空sortreadarrary表 头offsettblptrtoptop440a array 0 x integer 402022/7/1731表 头空sortreadarrary表 头 offsettblptrtoptop444a array 0 x integer 40i integer 02022/7/1732表 头空sortreadarrary表 头 4 offsettbl

22、ptrtoptop44a array 0 x integer 40i integer 0readarray指向readarray2022/7/1733表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头toptop02022/7/1734表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0t

23、optopexchange指向exchange2022/7/1735表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0toptopexchange指向exchange表 头quicksort02022/7/1736表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0toptopexch

24、ange指向exchange表 头quicksort4k integer 02022/7/1737表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0toptopexchange指向exchange表 头quicksort8k integer 0v integer 42022/7/1738表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readar

25、ray指向readarrayexchange表 头 0toptopexchange指向exchange表 头quicksort8k integer 0v integer 4表 头partition02022/7/1739表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0toptopexchange指向exchange表 头quicksort8k integer 0v integer 4表 头partition4i integer 0202

26、2/7/1740表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0toptopexchange指向exchange表 头quicksort8k integer 0v integer 4表 头partition8i integer 0j integer 42022/7/1741表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向r

27、eadarrayexchange表 头 0toptopexchange指向exchange表 头quicksort8k integer 0v integer 4表 头 8partitioni integer 0j integer 4partition2022/7/1742表 头空sortreadarrary表 头 4 offsettblptr44a array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0toptopexchange指向exchange表 头 8quicksortk integer 0v integer 4

28、表 头 8partitioni integer 0j integer 4partitionquicksort2022/7/1743表 头 44空sortreadarrary表 头 4 offsettblptra array 0 x integer 40i integer 0readarray指向readarrayexchange表 头 0toptopexchange指向exchange表 头 8quicksortk integer 0v integer 4表 头 8partitioni integer 0j integer 4partitionquicksort2022/7/17447.2.6

29、 记录的翻译空间分配设置首地址和各元素的相对地址大于所需的空间 (对齐)例:struct Node float x, y; struct node *next; node; 0482022/7/17457.2.6 记录的翻译符号表及有关表格处理为每个记录类型单独构造一张符号表将域名id的信息(名字、类型、字节数)填入到该记录的符号表中所有域都处理完后,offset将保存记录中所有数据对象的宽度总和T.type通过将类型构造器record应用于指向该记录符号表的指针获得2022/7/17467.2.6 记录的翻译T record D endT record L D endT.type := re

30、cord(top(tblptr);T.width := top(offset);pop(tblptr); pop(offset) L t := mktable(nil);push(t,tblprt);push(0,offset)2022/7/17477.3 赋值语句的翻译翻译的需求充分了解各种语言现象的语义包括:控制结构、数据结构、单词充分了解它们的实现方法目标语言的语义了解中间代码的语义了解运行环境2022/7/1748辅助子程序与语义属性设置辅助子程序gencode(code),emit(code):产生一条中间代码newtemp:产生新的临时变量lookup:检查符号表中是否出现某名字语

31、义属性设置中间代码序列:code地址:addr下一条四元式序号:nextquad2022/7/17497.3.1 简单赋值语句的翻译S id := E p := lookup();if p nil thengencode( p, :=, E.addr)else error E E1 + E2E.addr := newtemp; emit(E.addr,:=,E1.addr,+,E2.addr)E E1 E.addr := newtemp; emit(E.addr,:=,uminus,E1.addr) E (E1) E.addr := E1.addr E id p := looku

32、p();if p nil then E.addr := p else error 2022/7/1750临时名字的重用大量临时变量的使用对优化有利大量临时变量会增加符号表管理的负担也会增加运行时临时数据占的空间E E1 + E2的动作产生的代码的一般形式为计算E1到t1计算E2到t2t3 := t1 + t2( )( )( )( )临时变量的生存期像配对括号那样嵌套或并列2022/7/1751基于临时变量生存期特征的三地址代码x := a b + c d e f语 句 计数器c的值 0 $0 := a b 1 $1 := c d 2 $0 := $0 + $1 1 $1 := e

33、 f 2 $0 := $0 $1 1 x := $0 0引入一个计数器c,它的初值为0。每当临时变量仅作为运算对象使用时,c减去1;每当要求产生新的临时名字时,使用$c并把c增加1。2022/7/17527.3.2 数组元素的寻址数组元素引用的翻译完成上下界检查生成完成相对地址计算的代码目标x := yi 和 yi := xy为数组地址的固定部分相当于第1个元素的地址,i是相对地址,不是数组下标数组说明的翻译符号表及有关表格(内情向量)的处理维数、下标上界、下标下界、类型等首地址、需用空间计算按行存放、按列存放影响具体元素地址的计算2022/7/1753数组元素地址计算行优先一维数组Alow1

34、:up1 (nk=upk-lowk+1)addr(Ai)=base+(i-low1)*w=(base-low1*w)+i*w=c+i*w二维数组Alow1:up1 ,low2:up2;Ai1,i2addr(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)*wA1, 1, A1, 2, A1, 3 A2,

35、1, A2, 2, A2, 32022/7/1754数组元素地址计算的翻译方案设计下标变量访问的产生式L idElist | idElist Elist, E | E为了使数组各维的长度n在我们将下标表达式合并到Elist时是可用的,需将产生式改写为:L Elist | idElist Elist, E | idE2022/7/1755数组元素地址计算的翻译方案设计 L Elist | id Elist Elist, E | idE目的使我们在整个下标表达式列表Elist的翻译过程中随时都能知道符号表中相应于数组名id的表项,从而能够了解登记在符号表中的有关数组id的全部信息。于是我们就可以为

36、非终结符Elist引进一个综合属性Elist.array,用来记录指向符号表中相应数组名字表项的指针。2022/7/1756数组元素地址计算的翻译方案设计属性Elist.array,用来记录指向符号表中相应数组名字表项的指针。Elist.ndim,用来记录Elist中下标表达式的个数,即数组的维数。Elist.addr,用来临时存放Elist的下标表达式计算出来的值。函数limit(array, j),返回nj2022/7/17577.3.3 带有数组引用的赋值语句的翻译S Left := EE E + EE (E)E LeftLeft ElistLeft idElist Elist,EEli

37、st idE2022/7/1758赋值语句的翻译模式Leftid Left.addr :=id.addr; Left.offset:=null ElistidE Elist.addr:=E.addr; Elist.ndim := 1; Elist.array := id.addr ElistElist1,E t:=newtemp; m:=Elist1.ndim+1; gencode(t,:=,Elist1.addr, limit(Elist1.array,m); gencode(t,:=,t,+,E.addr); Elist.array := Elist1.array; Elist.addr

38、:= t; Elist.ndim := mLeft Elist Left.addr := newtemp; Left.offset := newtemp;gencode(Left.addr,:=,base(Elist.array),invariant(Elist.array); gencode(Left.offset,:=,Elist.addr,w)i1*n2(i1*n2)+i2(i1*n2)+i2)*wbase-(low1* n2 -low2)*w2022/7/1759赋值语句的翻译模式E Left if Left.offset = null then / Left是简单变量 / E.add

39、r := Left.addr else begin E.addr := newtemp; gencode(E.addr,:=,Left.addr,Left.offset,)endE E1 + E2 E.addr := newtemp;gencode(E.addr,:=,E1.place,+,E2.addr)E (E1) E.addr := E1.addr S Left := E if Left.offset=null then /Left是简单变量/ gencode(Left.addr, := , E.addr)else gencode(Left.addr,Left.offset,:=,E.a

40、ddr) (i1*n2)+i2)*w+(base-(low1* n2 -low2)*w)(i1*n2)+i2)*w+(base-(low1* n2 -low2)*w)2022/7/1760例:设A是一个1020的整型数组 w=4 S:=Left.place := xLeft.offset := nullxE.addr := t4Left.addr := t2Left.offset := t3Elist.addr := t1Elist.ndim := 2Elist.array := A,Elist.addr := yElist.ndim := 1Elist.array := AE.addr :=

41、 zLeft.addr := zLeft.offset := nullE.addr := yLeft.addr := yLeft.offset := nullAzy x := A y, z 的注释分析树2022/7/1761例S:=Left.addr := xLeft.offset := nullxE.addr := t4Left.addr := t2Left.offset := t3Elist.addr := t1Elist.ndim := 2Elist.array := A,Elist.addr := yElist.ndim := 1Elist.array := AE.addr := zL

42、eft.addr := zLeft.offset := nullE.addr := yLeft.addr := yLeft.offset := nullAzy x := A y, z 的注释分析树t1 := y 20 t1 := t1 + z 2022/7/1762例S:=Left.addr := xLeft.offset := nullxE.addr := t4Left.addr := t2Left.offset := t3Elist.addr := t1Elist.ndim := 2Elist.array := A,Elist.addr := yElist.ndim := 1Elist.a

43、rray := AE.addr := zLeft.addr := zLeft.offset := nullE.addr := yLeft.addr := yLeft.offset := nullAzy x := A y, z 的注释分析树t1 := y 20 t1 := t1 + z t2 :=baseA 84 t3 := 4 t1 2022/7/1763例S:=Left.addr := xLeft.offset := nullxE.addr := t4Left.addr := t2Left.offset := t3Elist.addr := t1Elist.ndim := 2Elist.ar

44、ray := A,Elist.addr := yElist.ndim := 1Elist.array := AE.addr := zLeft.addr := zLeft.offset := nullE.addr := yLeft.addr := yLeft.offset := nullAzy x := A y, z 的注释分析树t1 := y 20 t1 := t1 + z t4 := t2 t3 t2 :=baseA 84 t3 := 4 t1 2022/7/1764例S:=Left.addr := xLeft.offset := nullxE.addr := t4Left.addr :=

45、t2Left.offset := t3Elist.addr := t1Elist.ndim := 2Elist.array := A,Elist.addr := yElist.ndim := 1Elist.array := AE.addr := zLeft.addr := zLeft.offset := nullE.addr := yLeft.addr := yLeft.offset := nullAzy x := A y, z 的注释分析树t1 := y 20 t1 := t1 + z t4 := t2 t3 x := t4 t2 :=baseA 84 t3 := 4 t1 2022/7/1

46、7657.4 类型检查类型检查具有发现程序错误的能力,为了进行类型检查,编译程序需要为源程序的每个语法成分赋予一个类型表达式,名字的类型表达式保存在符号表中,其他语法成分(如表达式E或语句S)的类型表达式则作为文法符号的属性保存在语义栈中。 类型检查的任务就是确定这些类型表达式是否符合一定的规则,这些规则的集合通常称为源程序的类型系统2022/7/17667.4.1 类型检查的规则类型综合从子表达式的类型确定表达式的类型要求名字在引用之前必须先进行声明 if f的类型为st and x的类型为s then 表达式f(x)的类型为t 类型推断根据语言结构的使用方式来确定其类型 经常被用于从函数体

47、推断函数类型 if f(x)是一个表达式then 对某两个类型变量和,f具有类型 and x具有类型 2022/7/17677.4.2 类型转换x := y + i j(x和y的类型是real,i和j的类型是integer)中间代码t1 := i int jt2 := inttoreal t1 t3 := y real+ t2 x := t32022/7/17687.4.2 类型转换E E1 + E2的语义子程序E.addr := newtempif E1.type = integer and E2.type = integer then begin gencode(E.addr,:=,E1.

48、addr,int+,E2.addr);E.type = integerendelse if E1.type = integer and E2.type = real then beginu := newtemp;gencode(u,:=,inttoreal,E1.addr);gencode(E.addr,:=,u,real+,E2.addr);E.type := realend . . .2022/7/17697.5 控制结构的翻译高级语言的控制结构顺序结构 begin 语句; ;语句end分支结构 if_then_else、if_thenswitch、case循环结构 while_do、do

49、_while for、repeat_untilgoto语句三地址码goto n (j, _, _, n)if x relop y goto n (jrelop, x, y, n)2022/7/17707.5.1 布尔表达式的翻译基本文法B B1 or B2 | B1 and B2 | not B1 | (B1) | E1 relop E2 | true | false处理方式数值表示法(与算术表达式的处理类似)真:B.addr = 1假:B.addr = 0真假出口表示法(作为其他语句的条件改变控制流程,隐含着程序中的位置)真出口:B.true假出口:B.false2022/7/17717.5

50、.1 布尔表达式的翻译a or b and not ct1:=not ct2:=b and t1t3:=a or t2ab100: if ab goto 103101: t:=0102: goto 104103: t:=11042022/7/1772用数值表示布尔值的翻译nextquad是下一条三地址码指令的序号,每生成一条三地址码指令gencode便会将nextquad加1 B B1 or B2 B.addr := newtemp; gencode(B.addr:=B1.addrorB2.addr)B B1 and B2 B.addr := newtemp; gencode(B.addr:=

51、B1.addrandB2.addr)B not B1 B.addr := newtemp; gencode(B.addr:= notB1.addr) 2022/7/1773用数值表示布尔值的翻译B ( B1 ) B.addr:= B1.addr B E1 relop E2 B.addr := newtemp;gencode(ifE1.addr relop.op E2.addrgotonextquad+3);gencode(B.addr := 0) ; gencode(gotonextquad+2);gencode(B.addr := 1)B true B.addr:= newtemp; gen

52、code(B.addr := 1)B false B.addr:= newtemp; gencode(B.addr := 0)2022/7/1774例7.8 对ab or cd and ef的翻译 100: if ab goto 103 107: t2 := 1101: t1:= 0 108: if ef goto 111102: goto 104 109: t3 := 0103: t1 := 1 110: goto 112104: if cd goto 107 111: t3 := 1105: t2 := 0 112: t4 := t2 and t3106: goto 108 113: t5

53、 := t1 or t4 2022/7/17757.5.2 常见控制结构的翻译 文法S if B then S1S if B then S1 else S2S while B do S1S begin Slist endSlist Slist; S | SB是控制结构中的布尔表达式函数newlabel返回一个新的语句标号属性B.true和B.false分别用于保存B为真和假时控制流要转向的语句标号2022/7/17767.5.2 常见控制结构的翻译 翻译S时允许控制从S.code中跳转到紧接在S.code之后的那条三地址码指令,但在某些情况下,紧跟S.code的指令是跳转到某个标号L的跳转指令

54、,用继承属性S.next可以避免从S.code中跳转到一条跳转指令这样的连续跳转。S.next的值是一个语句标号,它是S的代码执行后应执行的第一个三地址码指令的标号。while语句中用S.begin保存语句的开始位置 2022/7/17777.5.2 常见控制结构的翻译B.codeS1.codeB.true:. . .指向B.true指向B.false(a) if-thenB.codeS1.codeB.true:. . .指向B.true指向B.falseB.false:goto S.nextS2.code(b) if-then-elseB.codeS1.codeB.true:. . .指向B

55、.true指向B.falsegoto S.beginS.begin:(c) while-doS1.codeS2.codeS1.next:. . .(d) S1; S2图7.25 if-then、if-then-else和while-do语句的目标代码结构 2022/7/17787.5.2 常见控制结构的翻译S if B then S1B.true := newlabel; B.false := S.next; S1.next := S.next; S.code:=B.code|gencode(B.true,:)|S1.code B.codeS1.codeB.true:. . .指向B.true

56、指向B.false(a) if-then2022/7/17797.5.2 常见控制结构的翻译S if B then S1 else S2B.true := newlabel; B.false := newlabel; S1.next := S.next; S2.next := S.next; S.code :=B.code|gencode(B.true,:)|S1.code | gencode(goto,S.next)|gen(B.false,:)|S2.code B.codeS1.codeB.true:. . .指向B.true指向B.falseB.false:goto S.nextS2.c

57、ode(b) if-then-else2022/7/17807.5.2 常见控制结构的翻译S while B do S1 S.begin:= newlabel; B.true := newlabel; B.false := S.next; S1.next := S.begin; S.code:=gencode(S.begin,:)|B.code| gencode(B.true,:)|S1.code| gencode(goto,S.begin)B.codeS1.codeB.true:. . .指向B.true指向B.falsegoto S.beginS.begin:(c) while-do202

58、2/7/17817.5.2 常见控制结构的翻译S S1; S2S1.next:=newlabel;S2.next:=S.next; S.code:=S1.code|gencode(S1.next,:)|S2.code S1.codeS2.codeS1.next:. . .(d) S1; S22022/7/17827.5.3 布尔表达式的控制流翻译属性 (继承属性)B.true,B为真时控制到达的位置;B.false,B为假时控制到达的位置。abif ab goto B.truegoto B.falseBB1 or B2如果B1为真,则立即可知B为真,即B1.true与B.true相同;如果B1

59、为假,则必须计算B2的值,令B1.false为B2的开始B2的真假出口分别与B的真假出口相同2022/7/1783简单布尔表达式的翻译示例 例7.9 ab or cd and ef if ab goto Ltrue goto L1L1:if cd goto L2 goto LfalseL2:if ef goto Ltrue goto Lfalse2022/7/17847.5.3 布尔表达式的控制流翻译B B1 or B2 B1.true:=B.true; B1.false:=newlabel; B2.true=B.true; B2.false:=B.false; B.code := B1.co

60、de|gencode(B1.false:)|B2.code B B1 and B2 B1.true:= newlabel; B1.false:= B.false; B2.true=B.true; B2.false:=B.false; B.code := B1.code|gencode(B1.true:)|B2.code B not B1 B1.true:=B.false; B1.false:=B.true; B.code :=B1.code2022/7/17857.5.3 布尔表达式的控制流翻译B ( B1 ) B1.true:=B. true; B1.false:=B.false; B.co

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论