当前位置:
文档之家› 编译原理(4)语义_2(表达式及赋值语句的翻译)
编译原理(4)语义_2(表达式及赋值语句的翻译)
本讲目标
第四章《语义分析和中间代码生成》
4.4
表达式及赋值语句的翻译
简单算术表达式和赋值语句的翻译 布尔表达式的翻译(难点)
重点掌握
算术表达式语义子程序 布尔表达式的真假出口
布尔表达式的语义子程序
根据翻译图得到布尔表达式的四元式
4.4
表达式及赋值语句的翻译
4.4.1 简单算术表达式和赋值语句的翻译
{ E.place=newtemp( ); emit(*,E(1).place, E(2).place,E.place); }
(2) E→ E(1)+E(2)
(3) E→ E(1)*E(2)
(4) E→−E(1)
{ E.place=newtemp( ); emit(uminus, E(1).place,_, E.place); }
4.4
表达式及赋值语句的翻译
(2) 回填算法:把链首p所链接的每个四元式的第四区段(result) 都改写为地址t。 (r) (_ , _ , _ , 0)
Backpatch(p, int t){ Q=p; while(Q!=0) { q=四元式Q的第四区段内容; 把t填进四元式Q的第四区段; Q=q; } // while } //Backpatch
(j) ( _ , _ , _ , 0)
(k) ( _ , _ , _ , 0)
注意:(k)为链首,(i)为链尾,链尾result=0
4.4
表达式及赋值语句的翻译
(1) 拉链算法: p1 ,p2各自是两个链首,将它们合并成一个以p2为链首的新链
merge(p1 ,p2){ if(p2==0) return(p1); else { p=p2; while(四元式p的第四区段内容不为0) p=四元式p的第四区段内容; 把p1填进四元式p的第四区段; return(p2); } // else } // merge
2、∧和∨服从左结合
3、运算符的优先级:算术 ⋗关系⋗布尔⋗“=”
4.4
表达式及赋值语句的翻译
(2)运算对象(三种):
布尔变量 布尔常量(false、true) 关系表达式
1、运算符rop : <、<=、==、!=、>=、> 2、运算对象:算术表达式
3、返回值类型:bool类型
例:bool a,b,c; int x,y,z a = b ∨ c ∧ true ∨ (x+y >= z) a = b ∨ c ∧ true ∨ x+y >= z 思考:运算顺序??
4.4
表达式及赋值语句的翻译
布尔表达式中,每个布尔分量一般至少对应两个四元式。
例如:E = E(1)∨E(2) = a∨b
对应: (1)(jnz, a,_,真出口) (2)(j,_,_,3) (3)(jnz, b,_,真出口) (4)(j,_,_,假出口)
if(a || b) c=1;
(5)(=,c,_,1)
(2) 优化的布尔表达式文法: G[E]: E→EAE | EBE | ┐E | (E) | i | i rop i EA→E∧ EB→E∨ 好处:在句子中,如果出现 “a∨b”或“a ∧ b”之类的
表达式,当扫描到“a∨”或“a ∧”之后就立即可以进行规约, 不用去关系b的取值。
4.4
表达式及赋值语句的翻译
规约的时候,再次扩充语义栈,添加tc栈和fc栈;
2、nxq:这是一个int变量,翻译工作开始之前,初始值 是1,翻译工作开始之后,每执行一次emit(),nxq自增1, 即: nxq = 四元式个数+1;
4.4
表达式及赋值语句的翻译
5、布尔表达式的翻译
1、文法:
G[E]: E→EAE | EBE | ┐E | (E) | i | i rop i EA→E∧ EB→E∨
计算布尔表达式的值有两种方法:
1、按照优先级和各变量的值,一步步求出结果;
2、优化计算:
b = true; a = b ∨ c ; (不计算c, a=true) b = false; a = b ∧ c ; (不计算c, a=false)
4.4
表达式及赋值语句的翻译
2、布尔表达式的计算
i = i, 使用E →i规约,得到:
i = E(符号栈) _ _ b(语义栈) 所以,E.Place中必须保存b在符 号表中的入口地址; x=b 翻译为( =, b, _ , x)
4.4
表达式及赋值语句的翻译
1.设计6个产生式的语义子程序 (1) A→ i=E { p=lookup(); if(p==NULL) error( ); else emit(=,E.place,_,p);
4.4
表达式及赋值语句的翻译
2、布尔表达式的计算
了解1:对布尔运算、关系运算、算术运算的运算对象的类型
可不区分布尔型或算术型,假定不同类型的变换工作将在需 要时强制执行。 思考:C语言的强制转换?? 了解2:布尔表达式在程序语言中不仅用作计算布尔值,还作 为控制语句(如if-else、while等)的条件表达式,用以确定程序 的控制流向。无论布尔表达式的作用如何,按照程序执行的 顺序,都必须先计算出布尔表达式的值。
(r1) ( _ , _ , _ , 0)
(q1) ( _ , _ , _ , r1) (p1) ( _ , _ , _ , q1) (r2) ( _ , _ , _ , 0) (q2) ( _ , _ , _ , r2)
(p2) ( _ , _ , _ , q2)
算法执行完,其实就是将(r2) 中的result变为p1,最终形成一个链
2、语义子程序: (1) E→i (布尔值) { E.tc=nxq; E.fc=nxq+1; emit(jnz,entry(i),_,0);
表4.2(2) 赋值语句X=−B*(C+D)的翻译过程
4.4
表达式及赋值语句的翻译
4.4.2 布尔表达式的翻译
1、布尔表达式的组成
布尔表达式:由运算符与运算对象组成。
定义布尔变量
A、B、C、D
A = bop1 B bop2 C bop3 D
(1)运算符:非┐(单目)、与∧ (双目)、或∨ (双目) 注意:1、优先级: ┐ ⋗ ∧ ⋗ ∨
(q) (_ , _ , _ , r) (p) (_ , _ , _ , q)
(r) (_ , _ , _ , t) (q) (_ , _ , _ , t)
(p) (_ , _ , _ , t)
4.4
表达式及赋值语句的翻译
(3) 其它需要说明的问题: 1、对于每个非终结符E,我们需要为它赋予两个语义值 E.tc和E.fc,分别用来记录E所对应的四元式的真链和假链。 也就是说,为每个非终结符E添加两个属性:tc和fc;因此,
(d) 定义语义函数newtemp( ),即每次调用newtemp( )时都将回 送一个代表新临时变量的整数码;临时变量名按产生的顺序可 设为T1、T2……
4.4
表达式及赋值语句的翻译 { E.place= E(1).place ;}
(5) E→(E(1))
(6) E→i
{ p=lookup(); if(p!=NULL) E.place=p; else error ( ); }
4.4
表达式及赋值语句的翻译
1.设计6个产生式的语义子程序 (1) A→ i=E { p=lookup(); if(p==NULL) error( ); else emit(=,E.place,_,p);
}
(a)对非终结符E定义语义变量E.place,即用E.place表示存放E 值的变量名在符号表中的入口地址或临时变量名的整数码 例如,赋值语句 x = b 刚开始读入到符号栈中,显示为
4.4
表达式及赋值语句的翻译
非终结符A代表“赋值句” 非终结符E代表“表达式”
考虑以下文法G[A]: A→ i = E
E→ E+E | E*E | −E | (E) | i
显然,文法G[A] 是一个二义文法,但通过确定运算符的结合 性及规定运算符的优先级就可避免二义性的发生。 用该文法作为示例的目的:为了更简要地说明语义子程序的 设计过程以及赋值语句的语法制导翻译过程。 如,对于赋值语句x=-b*(c+d),已经预先规定运算顺序
4、解决“真”、“假”出口问题的方法:拉链和回填
(1) 拉链:在同一个表达式内,每个四元式产生的时候,强制 其出口为0,若后面一个四元式和它出口相同,用前面产生式 的序号去填充后面产生式的跳转位置(result),从而将不同
的四元式链接起来,俗称“拉链”。
假如下面三个四元式都是真出口: (i) ( _ , _ , _ , 0) (i) (_ , _ , _ , 0) (j) (_ , _ , _ , i) (k) (_ , _ , _ , j)
(6){if语句后面的四元式}
在这个例子中,真出口和假出口不能在生成四元式的当时产 生;假如a和b并不是简单的布尔变量,或者条件语句后执行 的语句并不是仅仅一句,所有的真假出口都无法给定。
4.4
表达式及赋值语句的翻译
3、布尔表达式的文法:
(1) 普通布尔表达式文法:
G[E]: E→E∧E | E∨E | ┐E | (E) | i | i rop i
4.4
表达式及赋值语句的翻译
2、布尔表达式的计算
(1) 假出口:
若E(1)为假,则E为假; 若E(2)为假,则E为假; 所以E的假出口有两个: E(1)的假出口和E(2)的假出口。