编译原理与技术 第4章 语法制导的翻译 6学时.

Slides:



Advertisements
Similar presentations
林園高中適性入學 高雄區免試入學 及 特色招生介紹 1. 國中學生 國中教育會考 1 ( 每年五月 ) 特色招生 術科考試 五專 免試入學 ( 每年六月 ) 特色招生 甄選入學 高中高職 免試入學 擇一報到 林園高中適性入學  入學管道流程 2.
Advertisements

第四章:长期股权投资 长期股权投资效果 1、控制:50%以上 有权决定对方财务和经营.
编 译 原 理 指导教师:杨建国 二零一零年三月.
订单合并拆分功能详解 荷叶.
第五章 语法制导的翻译 赵建华 南京大学计算机系 2010年3月.
编译原理第二次习题课 王静.
跳楼价 亏本大甩卖 清仓处理 买一送一 5折酬宾. 跳楼价 亏本大甩卖 清仓处理 买一送一 5折酬宾.
清仓处理 跳楼价 满200返160 5折酬宾.
LR与LL分析 编译原理习题课二 胡云斌 PB

第四章 网络营销战略 战略计划是企业的生命线,是企业一切工作都必须遵循的总纲。我们经常说,做对的事情比把事情做对更重要,就是这个道理。美国一位总裁曾说:每天我总要花部分时间来思考的事情是企业未来10年的事情。在日本的一次调研中,90%的企业家认为:最占 时间、最为重要、最为困难的事情就是制定战略计划。可见,企业需要战略,没有战略计划指导的企业是很容易迷路的,迷了路的企业很难不误入歧途,误入歧途的企业,失败则是必然的。
北师大版七年级数学 5.5 应用一元一次方程 ——“希望工程”义演 枣庄市第三十四中学 曹馨.
C语言实验 第一课 标题:学号+姓名.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
全国计算机等级考试 二级基础知识 第二章 程序设计基础.
XX信托 ·天鑫 9号集合资金信托计划 扬州广陵
编译原理与技术 --文法和分析 2018/9/17 《编译原理与技术》讲义.
第七章 中间代码生成 静态 中间 分析 检查 代码 记号流 器 生成 本章内容 介绍几种常用的中间表示:后缀表示、图形表示和三地址代码
學校教職員退休條例修正草案重點報告 報告人:徐創晃.
7 Intermediate Representation
编译原理习题
2.2 语法分析器生成器YACC 分析器的构造步骤: 产生式→识别活前缀的DFA→分析表(+驱动器) YACC概述
CH6.属性文法语法制导翻译 《程序设计语言编译原理》 陈火旺等编著 2000年第3版
自上而下分析 4.4.
编译原理与技术 第7章 中间代码生成 3学时.
属性文法和语法制导翻译 授课:胡静.
第六章 属性文法和语法制导翻译 网上教学系统: : 编译原理
第四章 语法制导的翻译 本章内容 1、介绍语义描述的一种形式方法:语法制导的翻译,它包括两种具体形式 语法制导的定义 翻译方案
编译原理与技术 词法分析(1) 2018/11/28 《编译原理与技术》讲义.
编译原理与技术 2018/11/30 《编译原理与技术》讲义.
第三章 词法分析.
管理信息结构SMI.
走进编程 程序的顺序结构(二).
辅导课程六.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
语义分析简介 编译程序的目标:将源程序翻译成为语义等价的目标程序。 语义分析的主流技术:
第六、七章属性文法、语法制导翻译和中间代码
第八章语法制导翻译和中间代码生成 8.1概述 8.2属性文法和语法制导翻译 8.3语义分析 8.4中间代码 8.5一些语句的翻译.
编译原理与技术 语法制导翻译 2019/1/17 《编译原理与技术》讲义.
第二章 Java语言基础.
中间代码生成.
语法制导的翻译 (Syntax-Directed Translation)
《编译原理与技术》 期末复习 计算机科学与技术学院 郑启龙 李 诚 25/12/2018.
第3,4次课 一个简单的语法制导翻译器 2.3~2.5.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
第七章 语义分析和中间代码生成 本章内容 介绍几种常用的中间表示:后缀表示、图形表示和三地址代码
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
编译原理总结-1 第3~5章.
编译原理实践 13.语法分析程序的自动生成工具YACC.
第六章 语法制导的翻译 本章内容 介绍一种语义描述方法:语法制导的翻译,介绍语法制导的翻译的实现方法。
自底向上的语法分析 4.5.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
第4章 Excel电子表格制作软件 4.4 函数(一).
实验三 16位算术逻辑运算实验 不带进位控制的算术运算 置AR=1: 设置开关CN 1 不带进位 0 带进位运算;
正切函数的图象和性质 周期函数定义: 一般地,对于函数 (x),如果存在一个非零常数T,使得当x取定义域内的每一个值时,都有
定理21.9(可满足性定理)设A是P(Y)的协调子集,则存在P(Y)的解释域U和项解释,使得赋值函数v(A){1}。
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
第二节 函数的极限 一、函数极限的定义 二、函数极限的性质 三、小结 思考题.
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
鸡兔同笼(续) ——选择结构.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
编译原理实践 6.程序设计语言PL/0.
本节内容 this指针 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
第8章 语法制导翻译与中间代码生成.
Presentation transcript:

编译原理与技术 第4章 语法制导的翻译 6学时

介绍语义描述的一种形式方法:语法制导的翻译,它包括两 种具体形式 4 语法制导的翻译 内容提要 介绍语义描述的一种形式方法:语法制导的翻译,它包括两 种具体形式 语法制导的定义 翻译方案 介绍语法制导翻译的实现方法

第4章 语法制导的翻译 4.1 语法制导的定义 1学时

例:简单计算器的语法制导定义 产 生 式 语 义 规 则 L  E n print (E.val) E  E1 + T 4.1 语法制导的定义 例:简单计算器的语法制导定义 产 生 式 语 义 规 则 L  E n print (E.val) E  E1 + T E.val = E1 .val + T.val 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

一组形式为b=f(c1 , c2 , …, ck )的语义规则,其中 b和c1 , c2 , …, ck 是该产生式文法符号的属性, 4.1 语法制导的定义 4.1.1 语法制导定义的形式 基础文法 每个文法符号有一组属性 每个文法产生式 Aα 有 一组形式为b=f(c1 , c2 , …, ck )的语义规则,其中 b和c1 , c2 , …, ck 是该产生式文法符号的属性, f 是函数 综合属性:如果b是A的属性,c1 , c2 , …, ck 是产生式右部文 法符号的属性或A的其它属性 继承属性:如果b是右部某文法符号X的属性

S属性定义:仅使用综合属性的语法制导定义 产 生 式 语 义 规 则 4.1 语法制导的定义 4.1.2 综合属性 S属性定义:仅使用综合属性的语法制导定义 产 生 式 语 义 规 则 L  E n print (E.val) E  E1 + T E.val = E1 .val + T.val 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

注释分析树:结点的属性值都标注出来的分析树 8+52 n的注释分析树 各结点属性的计算可以自下而上地完成 4.1 语法制导的定义 注释分析树:结点的属性值都标注出来的分析树 8+52 n的注释分析树 各结点属性的计算可以自下而上地完成 L n +  E.val = 18 T.val = 10 E.val = 8 T.val = 5 T.val = 8 F.val = 2 F.val = 5 digit.lexval = 2 F.val = 8 digit.lexval = 8 digit.lexval = 5

4.1.3 继承属性 例:int id1, id2, id3 产 生 式 语 义 规 则 D  TL L.in = T.type 4.1 语法制导的定义 4.1.3 继承属性 例:int id1, id2, id3 产 生 式 语 义 规 则 D  TL L.in = T.type T  int T. type = integer T  real T. type = real L  L1, id L1.in = L.in; addType(id.entry, L.in) L  id

int id1, id2, id3的标注了部分属性的分析树 不可能像综合属性那样自下而上标注属性 4.1 语法制导的定义 int id1, id2, id3的标注了部分属性的分析树 不可能像综合属性那样自下而上标注属性 D int T.type = integer , id3 L.in = integer id2 id1

D int T , id3 L id2 id1 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4.1 语法制导的定义 4.1.4 属性依赖图 int id1, id2, id3的分析树(虚线)的依赖图(实线) D  TL L.in = T.type L  L1, id L1.in = L.in; addType (id.entry, L.in) L  id addType (id.entry, L.in) D int T , id3 L id2 id1 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4 type

D int T , id3 L id2 id1 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4.1 语法制导的定义 4.1.5 属性计算次序 (1)拓扑排序:结点的一种排序,使得依赖图中边只会从该 次序中先出现的结点到后出现的结点 例 1,2,3,4,5,6,7,8,9,10 D int T , id3 L id2 id1 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4 type

D int T , id3 L id2 id1 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4.1 语法制导的定义 (2)属性计算次序: 1)构造输入的分析树 2)构造属性依赖图 3)对结点进行拓扑排序 4)按拓扑排序的次序计算属性 D int T , id3 L id2 id1 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4 type

分析树方法:刚才介绍的方法,动态确定计算次序,效率低。 概念上的一般方法 4.1 语法制导的定义 语义规则的计算方法 分析树方法:刚才介绍的方法,动态确定计算次序,效率低。  概念上的一般方法 基于规则的方法:(编译器实现者)静态确定(编译器设计 者提供的)语义规则的计算次序。 适用于手工构造的方法 忽略规则的方法:(编译器实现者)事先确定属性的计算策 略(如边分析边计算),(编译器设计者提供的)语义规则必 须符合所选分析方法的限制。 适用于自动生成的方法

第4章 语法制导的翻译 4.2 S属性定义的自下而上计算 1学时

语法树是分析树的浓缩表示:算符和关键字是作为内部结点 语法制导定义可以基于分析树,也可以基于语法树 语法树的例子: 4.2 S属性定义的自下而上计算 4.2.1 语法树 语法树是分析树的浓缩表示:算符和关键字是作为内部结点 语法制导定义可以基于分析树,也可以基于语法树 语法树的例子: if B then S1 else S2 8 + 5  2 if-then-else B S1 S2 + * 2 5 8

E.nptr = mkNode( '+', E1.nptr, T.nptr) 4.2 S属性定义的自下而上计算 4.2.2 构造语法树的语法制导定义 产 生 式 语 义 规 则 E  E1 + T E.nptr = mkNode( '+', E1.nptr, T.nptr) E  T E.nptr = T.nptr T  T1  F T.nptr = mkNode( '', T1.nptr, F.nptr) T  F T.nptr = F.nptr F  (E) F.nptr = E.nptr F  id F.nptr = mkLeaf (id, id.entry) F  num F.nptr = mkLeaf (num, num.val)

例:a+5b的语法树的构造 E.nptr T.nptr F.nptr id +  num num 5 指向符号表中a的入口 4.2 S属性定义的自下而上计算 例:a+5b的语法树的构造 E.nptr T.nptr F.nptr id +  num num 5 指向符号表中a的入口 指向符号表中b的入口 +  id 指向符号表中a的入口 num 5 id 指向符号表中b的入口

LR分析器的栈增加一个域来保存综合属性值 4.2 S属性定义的自下而上计算 4.2.3 S属性的自下而上计算 LR分析器的栈增加一个域来保存综合属性值 若产生式 AXYZ 的语义规则是 A.a = f (X.x, Y.y, Z.z), 那么归约后: top Z Z.z Y Y.y X X.x . . . 栈 state val top A A.a . . .

例:简单计算器的语法制导定义改成栈操作代码 产 生 式 语 义 规 则 代 码 段 4.2 S属性定义的自下而上计算 例:简单计算器的语法制导定义改成栈操作代码 产 生 式 语 义 规 则 代 码 段 L  E n print (E.val) E  E1 + T E.val =E1 .val +T.val 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 print (val [ top1] ) val [top 2 ] = val [top 2]+val [top] —— val [top 2 ] = val [top 2]val [top] val [top 2 ] = val [top 1] ——

例:下面是产生字母表Σ = {0, 1, 2}上数字串的一个文法: S  D S D | 2 D  0 | 1 例题1 例:下面是产生字母表Σ = {0, 1, 2}上数字串的一个文法: S  D S D | 2 D  0 | 1 写一个语法制导定义,判断它接受的句子是否为回文数 S'  S print(S.val) S  D1 S1 D2 S.val = (D1.val == D2.val) and S1.val S  2 S.val = true D  0 D.val = 0 D  1 D.val = 1

若按22+0+20+2-1+0+2-3来计算,对小数点左边部分的计 算不利:需要继承属性来确定每个B离开小数点的距离 4.2 S属性定义的自下而上计算 例题2 例:为下面文法写一个语法制导的定义,用S的综合属性val给 出下面文法中S产生的二进制数的值。例如,输入 101.101时,S.val = 5.625(可以修改文法) S  L . L | L L  L B | B B  0 | 1 若按22+0+20+2-1+0+2-3来计算,对小数点左边部分的计 算不利:需要继承属性来确定每个B离开小数点的距离 若按(12+0)2+1计算,不能直接用于小数点右边,需改成 ((12+0)2+1)/23,这时需要综合属性来统计B的个数 S . L B

4.2 S属性定义的自下而上计算 例题2 例:为下面文法写一个语法制导的定义,用S的综合属性val给 出下面文法中S产生的二进制数的值。例如,输入 101.101时,S.val = 5.625(可以修改文法) S  L . L | L L  L B | B B  0 | 1 更好的办法是修改文法: S  L . R | L R  B R | B S . L B R S  L . R S. val = L. val + R. val S  L S. val = L. val L  L1 B L. val = L1. val  2 + B. val L  B L. val = B. val R  B R1 R. val = R1. val / 2 + B. val / 2 R  B R. val = B. val / 2 B  0 B. val = 0 B  1 B. val = 1

第4章 语法制导的翻译 4.3 L属性定义的自上而下计算 2学时

属性的计算次序一定受分析方法所限定的分析树结点建立次 序的限制 分析树的结点是自左向右生成 4.3 L属性定义的自上而下计算 边分析边翻译的方式能否用于继承属性? 属性的计算次序一定受分析方法所限定的分析树结点建立次 序的限制 分析树的结点是自左向右生成 如果属性信息是自左向右流动,那么就有可能在分析的同时 完成属性计算

如果每个产生式 AX1…Xj-1Xj…Xn 的每条语义规则计算的属 性是A的综合属性;或者是 Xj 的继承属性,但它仅依赖: 4.3 L属性定义的自上而下计算 4.3.1 L属性定义 如果每个产生式 AX1…Xj-1Xj…Xn 的每条语义规则计算的属 性是A的综合属性;或者是 Xj 的继承属性,但它仅依赖: 该产生式中Xj左边符号X1, X2, …, Xj-1的属性; A的继承属性 S属性定义属于L属性定义

例:变量类型声明的语法制导定义是一个L属性定义 产 生 式 语 义 规 则 产 生 式 语 义 规 则 D  TL L.in = T.type T int T. type = integer T real T. type = real L L1, id L1.in = L.in; addType(id.entry, L.in) L id

例:把有加和减的中缀表达式翻译成后缀表达式 如果输入是8+5-2,则输出是8 5 + 2 - E  T R 4.3 L属性定义的自上而下计算 4.3.2 翻译方案 例:把有加和减的中缀表达式翻译成后缀表达式 如果输入是8+5-2,则输出是8 5 + 2 - E  T R R  addop T {print (addop.lexeme)} R1 | ε T  num {print (num.val)} E  T R  num {print (8)} R  num{print (8)}addop T{print (+)}R  num{print(8)}addop num{print(5)}{print (+)}R … {print(8)}{print(5)}{print(+)}addop T{print(-)}R … {print(8)}{print(5)}{print(+)}{print(2)}{print(-)}

E .val 例 例:数学排版语言EQN(语法制导定义) S  B B  B1 B2 B  B1 sub B2 B  text 1 E sub 1 .val 产 生 式 语 义 规 则 S  B B.ps = 10; S.ht = B.ht B  B1 B2 B1.ps = B.ps; B2.ps = B.ps; B.ht = max(B1.ht, B2.ht ) B  B1 sub B2 B1.ps =B.ps; B2.ps = shrink(B.ps); B.ht = disp (B1.ht, B2.ht ) B  text B.ht = text.h  B.ps

S  {B.ps = 10 } //B继承属性的计算位于B的左边 B {S.ht = B.ht } //S综合属性的计算放在右部末端 4.3 L属性定义的自上而下计算 例 例:数学排版语言EQN(翻译方案) S  {B.ps = 10 } //B继承属性的计算位于B的左边 B {S.ht = B.ht } //S综合属性的计算放在右部末端 B  {B1.ps = B.ps } B1 {B2.ps = B.ps } B2 {B.ht = max(B1.ht, B2.ht ) } B  { B1.ps =B.ps } B1 sub { B2.ps = shrink(B.ps) } B2 {B.ht = disp (B1.ht, B2.ht ) } B  text {B.ht = text.h  B.ps }

E.nptr = mkNode( '+', E1.nptr, T.nptr) 4.3 L属性定义的自上而下计算 例:左递归的消除引起继承属性 产 生 式 语 义 规 则 E  E1 + T E.nptr = mkNode( '+', E1.nptr, T.nptr) E  T E.nptr = T.nptr T  T1F T.nptr = mkNode( '', T1.nptr, F.nptr) T  F T.nptr = F.nptr F  (E) F.nptr = E.nptr F  id F.nptr = mkLeaf (id, id.entry) F  num F.nptr = mkLeaf (num, num.val)

E  T {R.i = T.nptr} T + T + T + … R {E.nptr = R.s} R  + 4.3 L属性定义的自上而下计算 例 例:左递归的消除引起继承属性 E  T {R.i = T.nptr} T + T + T + … R {E.nptr = R.s} R  + T {R1.i = mkNode ( '+', R.i, T.nptr)} R1 {R.s = R1.s} R  ε {R.s = R.i } T  F {W.i = F.nptr} W {T.nptr = W.s} W   F {W1.i = mkNode ( '', W.i, F.nptr)} W1 {W.s = W1.s} W  ε {W.s = W.i } F 产生式部分不再给出

例 例:左递归的消除引起继承属性 T F.nptr id i W  num num 5 指向符号表中a的入口 i W s i W  4.3 L属性定义的自上而下计算 例 例:左递归的消除引起继承属性 T F.nptr id i W  num num 5 指向符号表中a的入口 i W s i W  略去了E  TR  T 部分 指向符号表中b的入口

把预测分析器的构造方法推广到翻译方案的实现 产生式R  +TR | ε 的分析过程 void R( ) { 4.3 L属性定义的自上而下计算 4.3.3 预测翻译器的设计 把预测分析器的构造方法推广到翻译方案的实现 产生式R  +TR | ε 的分析过程 void R( ) { if (lookahead == '+' ) { match ( '+' ); T( ); R( ); } else / 什么也不做 /

4.3 L属性定义的自上而下计算 syntaxTreeNode R (syntaxTreeNode i) { syntaxTreeNode nptr, i1, s1, s; char addoplexeme; if (lookahead == '+' ) { / 产生式 R  +T R / addoplexeme = lexval; match( '+' ); nptr = T(); i1 = mkNode(addoplexeme, i , nptr); s1 = R (i1); s = s1; } else s = i; / 产生式 R  ε / return s; R : i, s T : nptr + : addoplexeme

例:Pascal的声明,如m, n : integer D  L : T (非L属性定义) T  integer | char 4.3.4 用综合属性代替继承属性 例:Pascal的声明,如m, n : integer D  L : T (非L属性定义) T  integer | char L  L, id | id 信息从右向左流,归约从左向右,两者不一致 等所需信息获得后再归约 改成从右向左归约 D  id L L  , id L | : T D : L , id integer T

D  id L { addtype (id. entry, L. type) } 翻译方案 D  id L { addtype (id. entry, L. type) } L  , id L1 { L. type = L1. Type; addtype (id. entry, L1. type) } L  : T { L. type = T. type } T  integer { T. type = integer } T  real { T. type = real } D : L , id integer T

第4章 语法制导的翻译 4.4 L属性定义的自下而上计算 2学时

在自下而上分析的框架中实现L属性定义的方法 归约时进行属性计算 它能实现任何基于LL(1)文法的L属性定义 也能实现许多(但不是所有的)基于LR(1) 的L属性定义

R  + T {print ('+')} R1 | - T {print ('-')} R1 | ε 4.4 L属性定义的自下而上计算 4.4.1 删除翻译方案中嵌入的动作 E  T R R  + T {print ('+')} R1 | - T {print ('-')} R1 | ε T  num {print (num.val)} 在文法中加入产生ε的标记非终结符,让每个嵌入动作由不 同标记非终结符M代表,并把该动作放在产生式Mε的右 端 R  + T M R1 | - T N R1 | ε M  ε {print ('+')} N  ε {print ('-')} 这些动作的一个重要特点: 没有引用原来产生式文法符号的属性

T  int {T. type = integer} T  real {T. type = real} 4.4.2 分析栈上的继承属性 1、属性位置能预测 例:int p, q, r D  T {L.in = T.type} L T  int {T. type = integer} T  real {T. type = real} L  {L1.in = L.in } L1, id {addtype (id.entry, L.in )} L  id {addtype (id.entry, L.in )} D T L , r q p int  type in 继承属性的计算可 以略去,引用继承属 性的地方改成引用其 他符号的综合属性

addType(val[top], val[top3]) 4.4.2 分析栈上的继承属性 D T L , r q p int  type in 产 生 式 代 码 段 D  TL T int val[top] = integer T real val[top] = real L L1, id L id id T integer id , L T integer addType(val[top], val[top3]) addType(val[top], val[top1])

S  bABMC {M.i = A.s; C.i = M.s} M  ε {M.s = M.i} 4.4 L属性定义的自下而上计算 2、属性的位置不能预测 例: S  aAC {C.i = A.s} S  bABC {C.i = A.s} C  c {C.s = g(C.i)} 增加标记非终结符,使得位置可以预测 S  bABMC {M.i = A.s; C.i = M.s} M  ε {M.s = M.i}

增加标记非终结符,把f(A.s)的计算移到对标记非终结符归 约时进行 S  aANC {N.i = A.s; C.i = N.s} 4.4 L属性定义的自下而上计算 4.4.3 模拟继承属性的计算 继承属性是某个/些综合属性的一个函数 S  aAC {C.i = f(A.s)} C  c {C.s = g(C.i)} 增加标记非终结符,把f(A.s)的计算移到对标记非终结符归 约时进行 S  aANC {N.i = A.s; C.i = N.s} N  ε {N.s = f (N.i)}

sub {B2.ps = shrink(B.ps) } B2 {B.ht = disp (B1.ht, B2.ht ) } 4.4 L属性定义的自下而上计算 例 例 数学排版语言EQN S  {B.ps = 10 } B {S.ht = B.ht }  B  {B1.ps = B.ps } B1 {B2.ps = B.ps } B2 {B.ht = max(B1.ht, B2.ht ) }  B  {B1.ps =B.ps } B1 sub {B2.ps = shrink(B.ps) } B2 {B.ht = disp (B1.ht, B2.ht ) }  B  text {B.ht = text.h  B.ps }

B2.ps = M.s; B.ht = max(B1.ht, B2.ht ); 4.4 L属性定义的自下而上计算 例 产 生 式 语 义 规 则 S  LB B.ps = L.s; S.ht = B.ht; L  ε L.s = 10; 将B.ps存入栈中,便于引用 B  B1 MB2 B1.ps = B.ps; M.i = B.ps; B2.ps = M.s; B.ht = max(B1.ht, B2.ht ); M  ε M.s = M.i; 单纯为了属性位置可预测 B  B1 sub NB2 B1.ps =B.ps; N.i = B.ps; B2.ps = N.s; B.ht = disp (B1.ht, B2.ht ); N  ε N.s = shrink(N.i); 兼有计算功能 B  text B.ht = text.h  B.ps;

举例说明:在text归约成B时,B的ps属性都在次栈顶位置 4.4 L属性定义的自下而上计算 例 举例说明:在text归约成B时,B的ps属性都在次栈顶位置 S M s B  L s text sub N s

例 4.4 L属性定义的自下而上计算 产 生 式 语 义 规 则 代 码 段 S  LB B.ps = L.s; S.ht = B.ht; 产 生 式 语 义 规 则 代 码 段 S  LB B.ps = L.s; S.ht = B.ht; L  ε L.s = 10; B  B1 MB2 B1.ps = B.ps; M.i = B.ps; B2.ps = M.s; B.ht = max(B1.ht, B2.ht ); M  ε M.s = M.i; B  B1 sub NB2 B1.ps =B.ps; N.i = B.ps; B2.ps = N.s; B.ht = disp (B1.ht, B2.ht ); N  ε N.s = shrink(N.i); B  text B.ht = text.h  B.ps; val[top1] = val[top] val[top+1] = 10 val[top2] = max(val[top2], val[top]) val[top+1] = val[top1] val[top3] = disp (val[top3], val[top] ) val[top+1] = shrink(val[top2]) val[top] = val[top]  val[top1]

E .val 例 E sub 1 .val shrink(x)=0.8x; text.h=16 1 4.4 L属性定义的自下而上计算 L 10 E 16 L 10 B 160 L 10 N 8 sub B 160 L 10 1 16 N 8 sub B 160 L 10 E sub 1 .val E sub 1 .val E sub 1 .val E sub 1 .val E sub 1 .val B 128 N 8 sub 160 L 10 M 10 B 160 L .val 16 M 10 B 160 L B 160 M 10 L B 160 L 10 E sub 1 .val E sub 1 .val E sub 1 .val E sub 1 .val E sub 1 .val

例:给出把中缀表达式翻译成没有冗余括号的中缀表达式的 语法制导定义。例如,因为 + 和  是左结合, 4.4 L属性定义的自下而上计算 例题 例:给出把中缀表达式翻译成没有冗余括号的中缀表达式的 语法制导定义。例如,因为 + 和  是左结合, (( a  ( b + c ))  ( d ))可以重写成 a  (b + c )  d 两种方法: 先把表达式的括号都去掉,然后在必要的地方再加括号 去掉表达式中的冗余括号,保留必要的括号

E.code = E1.code || "+" || "(" || T.code || ")"; else 例题 第一种方法 S'  E { print ( E.code );} E  E1 + T { if T.op == plus then E.code = E1.code || "+" || "(" || T.code || ")"; else E.code = E1.code || "+" || T.code; E.op = plus;} E  T { E.code = T.code; E.op = T.op;}

if (F.op == plus) or (F.op == times) then if T1. op == plus then 例题 T  T1  F { if (F.op == plus) or (F.op == times) then if T1. op == plus then T.code = "(" || T1.code || ")" || "" || "(" || F.code || ")"; else T.code = T1.code || "" || "(" || F.code || ")"; else if T1.op = plus then T.code = "(" || T1.code || ")" || "" || F.code; T.code = T1.code || "" || F.code; T.op = times;}

T.code = F.code; T.op = F.op;} F  id { 4.4 L属性定义的自下而上计算 例题 T  F { T.code = F.code; T.op = F.op;} F  id { F.code = id.lexeme; F.op = id;} F  ( E ) { F.code = E.code; F.op = E.op;}

给E,T和F两个继承属性 left_op 和 right_op 分别表示左右 两侧算符的优先级 例题 第二种方法 给E,T和F两个继承属性 left_op 和 right_op 分别表示左右 两侧算符的优先级 给它们一个综合属性 self_op 表示自身主算符的优先级 再给一个综合属性 code 表示没有冗余括号的代码 分别用1和2表示加和乘的优先级,用3表示 id 和 (E) 的优先 级,用0表示左侧或右侧没有运算对象的情况

E.left_op = 0; E.right_op = 0; print ( E.code ); E  E1 + T { 例题 S'  E { E.left_op = 0; E.right_op = 0; print ( E.code ); E  E1 + T { E1.left_op = E.left_op; E1.right_op = 1; T.left_op = 1; T.right_op = E.right_op; E.code =E1.code || "+" || T.code; E.self_op = 1;} E  T { T.left_op = E.left_op; T.right_op = E.right_op; E.code = T.code; E.self_op = T.self_op;}

T1.left_op = T.left_op; T1.right_op = 2; 例题 T  T1  F { T1.left_op = T.left_op; T1.right_op = 2; F.left_op = 2; F.right_op = T.right_op; T.code =T1.code || "+" || F.code; T.self_op = 2;} T  F { F.left_op = T.left_op; F.right_op = T.right_op; T.code = F.code; T.self_op = F.self_op;} F  id { F.code = id.lexeme; F.self_op = 3;}

E.left_op = 0; E.right_op = 0; F.self_op = 例题 F  ( E ) { E.left_op = 0; E.right_op = 0; F.self_op = if (F.left_op < E.self_op) and (E.self_op >= F.right_op) then E.self_op else 3; F.code = then E.code else "(" || E.code || ")";}

本章要点 注释分析树、语法树、综合属性、继承属性 语法制导定义和翻译方案的实现 S属性的自下而上计算(边分析边计算) 4 语法制导的翻译 本章要点 注释分析树、语法树、综合属性、继承属性 语法制导定义和翻译方案的实现 S属性的自下而上计算(边分析边计算) L属性的自上而下计算(边分析边计算) L属性的自下而上计算(边分析边计算) 构造语法树的语法制导定义 用栈代码实现属性计算

习题 注释分析树 4.1 语法制导定义 4.3 4.7(第二版4.5) 语法制导翻译 4.12(第二版4.10) 4.16(第二版4.14) 4 语法制导的翻译 习题 注释分析树 4.1 语法制导定义 4.3 4.7(第二版4.5) 语法制导翻译 4.12(第二版4.10) 4.16(第二版4.14)