1 / 87

第 8 章 语法制导翻译和中间代码生成

语法分析 后的源程序. 语义处理. 中间代码. 第 8 章 语法制导翻译和中间代码生成. §8.1 概述 一、语义处理的任务:. 编译中的语义处理是指两个功能: 第一 静态语义分析或静态审查。. 静态语义分析通常包括: ① 类型检查。   ② 控制流检查。控制流语句必须使控制转移到合法 的地方。   ③ 一致性检查。   ④ 相关名字检查。有时,同一名字必须出现两次或 多次。例如, Ada 语言程序中,循环或程序块可 以有一个名字,出现在这些结构的开头和结尾,

lilith
Download Presentation

第 8 章 语法制导翻译和中间代码生成

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 语法分析 后的源程序 语义处理 中间代码 第8章 语法制导翻译和中间代码生成 §8.1概述 一、语义处理的任务:

  2. 编译中的语义处理是指两个功能: 第一 静态语义分析或静态审查。

  3. 静态语义分析通常包括: ① 类型检查。  ② 控制流检查。控制流语句必须使控制转移到合法 的地方。   ③ 一致性检查。   ④ 相关名字检查。有时,同一名字必须出现两次或 多次。例如,Ada 语言程序中,循环或程序块可 以有一个名字,出现在这些结构的开头和结尾, 编译程序必须检查这两个地方用 的名字是相同的。  ⑤ 名字的作用域分析

  4. 第二 动态语义处理:如果静态语义正确,语义处理则要执行真正的翻译,即,或者将源程序翻译成程序的一种中间表示形式(中间代码),或者将源程序翻译成目标代码。

  5. 二、属性文法: 1、属性: 所谓属性,其涉及的概念比较广泛,常用以描述事物或人的特征、性质,品质等等。比如,谈到一个 物体,可以用“颜色”描述它,谈起某人,可以使用“有幽默感“来形容他。对编译程序使用的语法树的结点,可以用"类型"、"值"或"存储位置"来描述它。

  6. 2、属性文法(也称属性翻译文法) 它是在上下文无关文法的基础上,为每个文法符号(终结符或非终结符)配备若干相关的"值"(称为属性)。这些属性代表与文法符号相关信息,例如它的类型、值、代码序列、符号表内容等等。 属性与变量一样,可以进行计算和传递。 属性加工的过程即是语义处理的过程。 对于文法的每个产生式都配备了一组属性的计算规则,称为语义规则。

  7. 假如语法分析方法是自下而上的。在用某一产生式进行归约的同时就执行相应的语义动作,在分析出一个句子时,这个句子的"值"也就同时产生了假如语法分析方法是自下而上的。在用某一产生式进行归约的同时就执行相应的语义动作,在分析出一个句子时,这个句子的"值"也就同时产生了

  8. 3、属性文法的定义: 一个属性文法是一个三元组: A=(G,V,F), G: 是一个上下文无关文法 V: 有穷的属性集,每个属性与文法的一终结符 或非终 结符相连。 F: 关于属性的属性断言或谓词集.每个断言与一个 产生式相 联。一个断言就是一个语义规则, 描 述各属性的关系。 用法: 针对语义:为每个符号设置一个属性,终结符号用单词属性。 为每个产生式设置语义规则——描述各属性的关系。

  9. 例如:定义表达式的文法如下:EE+E E(E)En 给出定义表达式值的属性文法。 我们为文法符号E引进属性符号val,用E.val表示E的值,属性计算规则以赋值语句的形式给出,附在每个产生式后,并用大括号括起来。为了明确E的不同出现位置,用上角标区别。终结符n的值是词法分析程序提供的,这里用n.lex表示。下面给出属性文法: EE1+E2 {E.val := E1.val +E2.val} E(E1) {E.val := E1.val } En {E.val := n.lex} 属性文法的主要思想有两点: 首先对于每个文法符号引进相关的属性符号; 其次对于每个产生式写出属性值计算的规则。

  10. 属性分为两种:继承属性和综合属性.综合属性:在语法树中,一个结点的综合属性由该结点 的子结点的属性值确定。它的计算规则由底 向上.继承属性:在语法树中,一个结点的继承属性由该结点的 父结点/兄弟结点的属性确定。即它 的计算规 则由顶向下。

  11. 例如定义表达式值的属性文法, E.val是一个综合属性的例子: EE1+E2 {E.val := E1.val +E2.val} E(E1) {E.val := E1.val } En {E.val := n.lex} 考虑句子2+(3+1)的求值顺序,将2+(3+1)的语法树结点改为有附加属性的结点(这样的树称为带注释的语法树): E.val=6 E.val=2 + E.val=4 n.lex=2 ( E.val=4 ) E.val=3 + E.val=1 n.lex=3 n.lex=1

  12. 又例:一个简单台式计算器的定义 综合属性val 产 生 式 语 义 规 则 Print(E.val) L E E.val:=E1.val+T.val E E1+T E T E.val:=T.val T T1 * F T.val:=T1.val  F.val T F T.val:=F.val F (E) F.val:=E.val F digit F.val:=digit.lexval

  13. 3*5+4的带注释的分析树 只使用综合属性. L E.val=19 E.val=15 T.val=4 + T.val=15 F.val=4 F.val=5 T.val=3 * digit.lexval=4 F.val=3 digit.lexval=5 digit.lexval=3 3*5+4的带注释的分析树

  14. 产生式 语 义 规 则 D TL L.in:=T.type T int T.type=integer T real T.type:=real L  L1,id addtype(id.entry,L.in) L id addtype(id.entry,L.in ) 继承属性 一个结点的继承属性值是由此结点的父结点和/或兄弟结点的某些属性来决定的。例,添加标识符类型的语义描述: 继承属性type L1.in:=L.in

  15. 与L产生式相联的语义规则中有一个过程调用addtype,过程addtype的功能是把每个标识符的类型信息登录在符号表的相关项中。与L产生式相联的语义规则中有一个过程调用addtype,过程addtype的功能是把每个标识符的类型信息登录在符号表的相关项中。

  16. 句子 int id1,id2的语法树,使用 表示属性的传递情况。

  17. 三、中间代码 • 是源程序的一种内部表示 • 复杂性介于源语言和目标机语言之间 中间代码的形式: 逆波兰式、四元式、三元式、间接三元式、 树

  18. 逆波兰表示 程序设计语言中的表示 逆波兰表示 a+ba+b*c(a+b)*ca:=b*c+b*d ab+abc*+ ab+c*abc*bd*+:= 1 逆波兰记号 逆波兰记号是最简单的一种中间代码表示形式。 这种表示法将运算对象写在前面,把运算符号写在后面,比如把a+b写成ab+,把a*b写成ab*,用这种表示法表示的表达式也称做后缀式。

  19. 后缀表示法表示表达式,其最大的优点是易于计算机处理表达式。常用的算法是使用一个栈,自左至右扫描算术表达式(后缀表示),每扫描到运算对象,就把它推进栈;扫描到运算符,若该运算符是二目的,则对栈顶部的两个运算对象实施该运算,并将运算结果代替这两个运算对象而进栈;若是一目运算符,则对栈顶元素执行该运算,并以运算结果代替该元素进栈,最后的结果留在栈顶。后缀表示法表示表达式,其最大的优点是易于计算机处理表达式。常用的算法是使用一个栈,自左至右扫描算术表达式(后缀表示),每扫描到运算对象,就把它推进栈;扫描到运算符,若该运算符是二目的,则对栈顶部的两个运算对象实施该运算,并将运算结果代替这两个运算对象而进栈;若是一目运算符,则对栈顶元素执行该运算,并以运算结果代替该元素进栈,最后的结果留在栈顶。

  20. 例如 B@CD*+(它的中缀表示为-B+C*D,使用@表示一目减)的计值过程为:1. B进栈;2. 对栈顶元素施行一目减运算,并将结果代替栈顶,即-B置于栈顶;3. C进栈; 4. D进栈;5. 栈顶两元素相乘,两元素退栈,相乘结果置栈顶;6. 栈顶两元素相加,两元素退栈,相加结果进栈,现在栈顶存放的是整个表达式的值。

  21. 逆波兰表示很容易扩充到表达式以外的范围。 只要遵守运算对象后直接紧跟它们的运算符的规 则即可。 比如把转语句GOTO L写为“L jump ", 运算对象L为语句标号,运算符jump表示转到 某个标号。再比如条件语句if E then S1 else S2 可表示为:ES1S2¥,把if then else看成三目运 算符,用¥来表示。

  22. 生成后缀式的属性文法 注释: || 表示代码序列的连接

  23. 例:给出下列表达式的逆波兰式: (1) a*(-b+c) (2) a+b*(c+d/e) 解 (1) ab@c+* (2) abcde/+*+ 练习:P188 1

  24. 2 三元式和树形表示  另一类中间代码形式是三元式。把表达式及各种语句表示成一组三元式。每个三元式由三个部分组成,分别是:算符op,第一运算对象ARG1和第二运算对象ARG2。运算对象可能是源程序中的变量,也可能是某个三元式的结果,用三元式的编号表示。 例如a∶ =b*c+b*d的表示为:(1)(*, b,c)(2)(*, b,d)(3)(+ (1), (2))(4)(∶= (3), a)

  25. 树形表示是三元式表示的翻版。 例:a∶ =b*c+b*d可表示成下面的树表示:

  26. 例 表达式 (A - 12) * B + 6 的语法结构树

  27. 将赋值语句变换为语法结构树 • 基本函数——结点构造 • Mknode(op,left,right) 建标记为op的算符结点,结点有两个域,分别为left和right. • Mkleaf(id,entry) 建标记为id的叶结点,有一个entry域,它是指向符号表的入口。 • Mkleaf(num,val)建标记为id的叶结点,有一个val域,是表示该数的值。

  28. - id 指向c的入口 id num 4 指向a 的入口 构造 a-4+c的语法树: (1) p1:=mkleaf(id,entry a); (2) p2:=mkleaf(num, 4); (3) p3:=mknode(‘-’,p1,p2) (4) p4:=mkleaf(id, entry c) (5) p5:=mknode(‘+’,p3,p4)

  29. 语法制导定义(属性文法) E.p 是语法结构树指针

  30. 四元式和三元式的主要不同在于,四元式对中间结果的引用必须通过给定的名字,而三元式是通过产生中间结果的三元式编号。也就是说,四元式之间的联系是通过临时变量实现的。四元式和三元式的主要不同在于,四元式对中间结果的引用必须通过给定的名字,而三元式是通过产生中间结果的三元式编号。也就是说,四元式之间的联系是通过临时变量实现的。 有时,为了更直观,也把四元式的形式写成简单赋值形式或更易理解的形式。比如把上述四元式序列写成: (1)t1∶=b*c (2)t2∶=b*d (3)t3∶=t1+t2 (4)a∶=t3  把(jump,-,-,L)写成goto L把(jrop,B,C,L)写成if B rop C goto L

  31. 请将表达式-(a+b)*(c+d)-(a+b)分别表示成三元式、间接三元式和四元式序列。请将表达式-(a+b)*(c+d)-(a+b)分别表示成三元式、间接三元式和四元式序列。 三元式 (1) (+ a, b) (2) (+ c, d) (3) (* (1), (2)) (4) (- (3), /)(5) (+ a, b)(6) (- (4), (5)) 间接三元式间接三元式序列   间接码表(1) (+ a, b)(1)(2) (+ c, d)(2) (3) (* (1), (2))(3) (4) (- (3), /) (4)(5) (- (4), (1))(1) (5) 四元式(1) (+, a, b, t1)(2) (+, c, d, t2)(3) (*, t1, t2, t3) (4) (-, t3, /, t4) (5) (+, a, b, t5)(6) (-, t4, t5, t6)

  32. 实际上,在一个表达式中可能出现各种不同 类型的变量,而不象前面假定为同一类型。 因此,上例应改为P163 图8.10 的形式。

  33. 采用语法制导翻译思想,表达式E的"值"的描述如下:   产生式       语义动作 (0) S′→E{print E.VAL}(1) E→E1+E2 {E.VAL∶=E1.VAL+E2.VAL} (2) E→E1*E2{E.VAL∶=E1.VAL*E2.VAL} (3) E→(E1) {E.VAL∶=E1.VAL}(4) E→n {E.VAL∶=n.LEXVAL} 假如终结符n可以是整数或实数,算符+和*的运算对象类型一致,语义处理增加"类型匹配检查",请给出相应的语义描述。

  34. (0) S′→E { if error≠1 then print E.VAL} • E→E1+E2 { if E1.TYPE=int AND E2.TYPE=int thenbeginE.VAL:=E1.VAL + E2.VAL;E.YTPE:=int;end else if E1.TYPE=real AND E2.TYPE=real • then begin E.VAL:=E1.VAL + E2.VAL;E.YTPE:=real; end else error=1 }

  35. (2) E→E1*E2 { if E1.TYPE=int AND E2.TYPE=int then beginE.VAL:=E1.VAL * E2.VAL;; E.YTPE:=int; end else if E1.TYPE=real AND E2.TYPE=real thenbeginE.VAL:=E1.VAL * E2.VAL;; E.YTPE:=real;end else error=1}

  36. (3) E→(E1) { E.VAL:=E1.VAL; E.TYPE:=E1.TYPE } (4) E→n { E.VAL:=n.LEXVAL;E.TYPE:=n.LEXTYPE }

  37. 8.3 布尔表达式的翻译 程序设计语言中的布尔表达式有两个作用。 一是计算逻辑值 更多的情况是二:用做改变控制流语句中的 条件表达式,如在if-then,if-then-else, 或是while-do语句中那样。

  38. 布尔表达式是由布尔算符and,or和not施于布尔变量或关系表达式而成。布尔表达式是由布尔算符and,or和not施于布尔变量或关系表达式而成。 即布尔表达式的形式为E1 rop E2,其中E1和E2都是算术表达式,rop是关系符,如<=,<,=,>=,≠等等。

  39. 布尔表达式的翻译方法 通常,计算布尔表达式的值有两种办法: 第一种办法,如同计算算术表达式一样,步步 计算出各部分的真假值,最后计算出整个表 达式的值。 用数值1表示true,用0表示false。 那么布尔表达式1 or(not 0 and 0)or 0的计算过程是: 1 or(not 0 and 0)or 0  =1 or(1 and 0)or 0  =1 or 0 or 0  =1 or 0  =1

  40. 另一种计算方法是采取某种优化措施,只计算部分表达式.另一种计算方法是采取某种优化措施,只计算部分表达式. 例如要计算A or B,若计算出A的值为1,那么B的值就无需再计算了,因为不管B的值为何结果,A or B的值都为1。

  41. 控制语句中布尔表达式的翻译 现在讨论出现在 if then;if then else和while do等语句中的布尔表达式E的翻译。 这三种语句的语法为: S→if E then S1|if E then S1 else S2| while E do S1

  42. E的代码 . 。 begin 真 E 的代码 . 。 E的代码 . 。 假 S1的代码 S1 的代码 S1的代码 Jump out Jump begin S2的代码 out 控制语句的代码结构 (a) if E then S1 (b)|if E then S1 else S2 (c)while E do S1

  43. 翻译的基本思路:对于E为a rop b,形成代码为: If a rop b goto E.true goto E.false 对于E为 E1 or E2 的形式: 1、E1为真,则E为真,即E的真出口为E1的真 出口。 2、E1为假,计算E2,即E1的假出口应 为E2的第一个四元式标号,E2的真、假出 口与E的真、假出口一样。

  44. 我们使用E.true和E.false分别表示整个表达式a<b or c<d and e<f的真、假出口,而E.true和E.false的值并不能在产生四元式的同时就知道。为了看清这一点,我们把该表达式放在条件语句中考虑,如语句 If ( a<b or c<d and e<f )then S1 else S2 的四元式序列见下页:

  45. If ( a<b or c<d and e<f )then S1 else S2 的四元式序列为  (1) ifa<bgoto (7)   /*(7)是整个布尔表达式的真出口*/  (2) goto (3)  (3) ifc<dgoto (5)  (4) goto(p+1) /*(p+1)是整个布尔表达式的假出口*/  (5) ife<fgoto (7)  (6) goto (p+1)  (7) (关于S1的四元式)   … (p) goto (q) (p+1) (关于S2的四元式)  … (q)

More Related