语法制导的翻译 (Syntax-Directed Translation)

Slides:



Advertisements
Similar presentations
XX啤酒营销及广告策略.
Advertisements

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

第四章 网络营销战略 战略计划是企业的生命线,是企业一切工作都必须遵循的总纲。我们经常说,做对的事情比把事情做对更重要,就是这个道理。美国一位总裁曾说:每天我总要花部分时间来思考的事情是企业未来10年的事情。在日本的一次调研中,90%的企业家认为:最占 时间、最为重要、最为困难的事情就是制定战略计划。可见,企业需要战略,没有战略计划指导的企业是很容易迷路的,迷了路的企业很难不误入歧途,误入歧途的企业,失败则是必然的。
北师大版七年级数学 5.5 应用一元一次方程 ——“希望工程”义演 枣庄市第三十四中学 曹馨.
全国计算机等级考试 二级基础知识 第二章 程序设计基础.
海洋存亡 匹夫有责 ——让我们都来做环保小卫士 XX小学三(3)班.
XX信托 ·天鑫 9号集合资金信托计划 扬州广陵
编译原理与技术 --文法和分析 2018/9/17 《编译原理与技术》讲义.
第七章 中间代码生成 静态 中间 分析 检查 代码 记号流 器 生成 本章内容 介绍几种常用的中间表示:后缀表示、图形表示和三地址代码
學校教職員退休條例修正草案重點報告 報告人:徐創晃.
7 Intermediate Representation
编译原理习题
2.2 语法分析器生成器YACC 分析器的构造步骤: 产生式→识别活前缀的DFA→分析表(+驱动器) YACC概述
CH6.属性文法语法制导翻译 《程序设计语言编译原理》 陈火旺等编著 2000年第3版
编译原理与技术 第7章 中间代码生成 3学时.
EBNF 请用扩展的 BNF 描述 C语言里语句的结构; 请用扩展的 BNF 描述 C++语言里类声明的结构;
属性文法和语法制导翻译 授课:胡静.
第六章 属性文法和语法制导翻译 网上教学系统: : 编译原理
强连通分量 无向图 1、任意两顶点连通称该图为连通图 2、否则将其中的极大连通子图称为连通分量 A D C B E 有向图
第四章 语法制导的翻译 本章内容 1、介绍语义描述的一种形式方法:语法制导的翻译,它包括两种具体形式 语法制导的定义 翻译方案
编译原理与技术 词法分析(1) 2018/11/28 《编译原理与技术》讲义.
编译原理与技术 2018/11/30 《编译原理与技术》讲义.
第三章 词法分析.
管理信息结构SMI.
走进编程 程序的顺序结构(二).
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
语义分析简介 编译程序的目标:将源程序翻译成为语义等价的目标程序。 语义分析的主流技术:
LL(1)分析方法 LL(1)是LL(k)的特例,其中的k则表示向前看k个符号. LL(1)方法和递归下降法属于同一级别的自顶向下分析法.
第六、七章属性文法、语法制导翻译和中间代码
第八章语法制导翻译和中间代码生成 8.1概述 8.2属性文法和语法制导翻译 8.3语义分析 8.4中间代码 8.5一些语句的翻译.
编译原理与技术 语法制导翻译 2019/1/17 《编译原理与技术》讲义.
第二章 Java语言基础.
《编译原理与技术》 期末复习 计算机科学与技术学院 郑启龙 李 诚 25/12/2018.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
28.1 锐角三角函数(2) ——余弦、正切.
第3,4次课 一个简单的语法制导翻译器 2.3~2.5.
解决变化问题的自底向上 流程建模方法 严志民 徐玮.
编译原理与技术 第4章 语法制导的翻译 6学时.
第七章 语义分析和中间代码生成 本章内容 介绍几种常用的中间表示:后缀表示、图形表示和三地址代码
C语言程序设计 主讲教师:陆幼利.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
$9 泛型基础.
编译原理总结-1 第3~5章.
编译原理实践 13.语法分析程序的自动生成工具YACC.
第六章 语法制导的翻译 本章内容 介绍一种语义描述方法:语法制导的翻译,介绍语法制导的翻译的实现方法。
自底向上的语法分析 4.5.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
第4章 Excel电子表格制作软件 4.4 函数(一).
定理21.9(可满足性定理)设A是P(Y)的协调子集,则存在P(Y)的解释域U和项解释,使得赋值函数v(A){1}。
第九节 赋值运算符和赋值表达式.
3.16 枚举算法及其程序实现 ——数组的作用.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
業務員 傷害險通報作業 新光人壽內網-產險傷害險通報P2~P4 【個人】傷害險通報作業P5~P10 【團體】傷害險通報作業P11~P16
第二章 Java基本语法 讲师:复凡.
基于规则抽取的时间表达式识别 -英文Ⅲ 高冠吉.
第二节 函数的极限 一、函数极限的定义 二、函数极限的性质 三、小结 思考题.
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
第十七讲 密码执行(1).
编译原理实践 6.程序设计语言PL/0.
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
第8章 语法制导翻译与中间代码生成.
Presentation transcript:

语法制导的翻译 (Syntax-Directed Translation)

语法制导的翻译:一种由语法分析器驱动的翻译方法 How? 词 法 分析器 token getNextToken 源程序 分析树 语义分析、 中间代码生成 语 法分析器 中间表示 符号表 用语法分析的过程和分析树引导语义分析和中间代码生成 两种方法:语法制导的定义、语法制导的翻译方案

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

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

S属性的语法制导定义 仅使用综合属性的语法制导定义 产 生 式 语 义 规 则 L  E n L.val = E.val 产 生 式 语 义 规 则 L  E n L.val = 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

S属性的语法制导定义 注释分析树:结点的属性值都标注出来的分析树 digit.lexval = 2 L.val = 18 8+5*2 n 的注释分析树 digit.lexval = 2 L.val = 18 E.val = 18 n T.val = 10 E.val = 8 T.val = 8 F.val = 8 digit.lexval = 8 T.val = 5 +  F.val = 5 F.val = 2 digit.lexval = 5

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

继承属性 产 生 式 语 义 规 则 D  TL L.in = T.type T int T. type = integer 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的标注了部分属性的分析树 D T.type = integer L.in = integer 不可能像综合属性那样自下而上标注属性 D int T.type = integer , id3 L.in = integer id2 id1

属性依赖图 例 int id1, id2, id3的分析树(虚线)的依赖图 (实线) D  TL L.in = T.type D int 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4 type

属性依赖图 例 int id1, id2, id3的分析树(虚线)的依赖图 (实线) L L1, id L1.in = L.in; 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

属性依赖图 例 int id1, id2, id3的分析树(虚线)的依赖图 (实线) 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

属性计算次序 拓扑排序:结点的一种排序,使得边只会从该次 序中先出现的结点到后出现的结点 例 1,2,3,4,5,6,7,8,9,10 D 例 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

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

语义规则的计算方法 (1)构造输入的分析树;(2)构造属性依赖图; (3)对结点进行拓扑排序;(4)按拓扑排序的 次序计算属性 digit.lexval = 2 L.val = 18 E.val = 18 n T.val = 10 E.val = 8 T.val = 8 F.val = 8 digit.lexval = 8 T.val = 5 +  F.val = 5 F.val = 2 digit.lexval = 5

具有受控副作用的语义规则 按照依赖图的任何拓扑顺序进行属性计算都可以 产生同样的副作用 D int T , id3 L id2 id1 L L1, id L1.in = L.in; 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 L id addType(id.entry, L.in)

具有受控副作用的语义规则 按照依赖图的任何拓扑顺序进行属性计算都可以 产生同样的副作用 产 生 式 语 义 规 则 L  E n 产 生 式 语 义 规 则 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

语义规则的计算方法 分析树方法:刚才介绍的方法,在编译过程中确 定计算次序,效率低 概念上的一般方法 分析树方法:刚才介绍的方法,在编译过程中确 定计算次序,效率低 概念上的一般方法 考虑在编译前(在构造编译器时)决定计算次序, 不在编译时显式构造依赖图 (编译器实现者)对(编译器设计者提供的)语义规 则进行分析,静态确定计算次序 适用于手工构造编译器。属性依赖关系复杂的语法制导定义很难 事先确定属性计算次序 (编译器实现者)事先确定属性的计算策略(如边分 析边计算),(编译器设计者提供的)语义规则必须 符合所选分析方法的限制 适用于编译器的自动生成。限制语法制导定义的种类

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

构造语法树的语法制导定义 产 生 式 语 义 规 则 E  E1 + T 产 生 式 语 义 规 则 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的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

a+5b的语法树的构造 指向符号表中a的入口 指向符号表中b的入口 E.nptr + T.nptr  F.nptr num id

S属性定义的自底向上计算:借助LR分析器 若产生式A →XYZ的语义规则是 A.a = f (X.x, Y.y, Z.z), 那么归约后: . . . Z Z. z Y Y. y X X.x top . . . A A.a top 栈 state val

简单计算器的语法制导定义改成栈操作代码 产 生 式 语 义 规 则 L  E n print (E.val) E  E1 + T 产 生 式 语 义 规 则 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 . . . Z Z. z Y Y. y X X.x top 栈 state val

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (E.val) E  E1 + T 产 生 式 代 码 段 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 . . . Z Z. z Y Y. y X X.x top 栈 state val

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (val [ top1] ) 产 生 式 代 码 段 L  E n print (val [ top1] ) 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 . . . Z Z. z Y Y. y X X.x top 栈 state val 省略top指针的移动

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (val [ top1] ) 产 生 式 代 码 段 L  E n print (val [ top1] ) E  E1 + T val [top 2 ] = val [top 2]+val [top] 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 . . . Z Z. z Y Y. y X X.x top 栈 state val 省略top指针的移动

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (val [ top1] ) 产 生 式 代 码 段 L  E n print (val [ top1] ) E  E1 + T val [top 2 ] = val [top 2]+val [top] E  T 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 . . . Z Z. z Y Y. y X X.x top 栈 state val 省略top指针的移动

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (val [ top1] ) 产 生 式 代 码 段 L  E n print (val [ top1] ) E  E1 + T val [top 2 ] = val [top 2]+val [top] E  T T  T1  F val [top 2]val [top] T  F T.val = F.val F (E) F.val = E.val F  digit F.val = digit.lexval . . . Z Z. z Y Y. y X X.x top 栈 state val 省略top指针的移动

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (val [ top1] ) 产 生 式 代 码 段 L  E n print (val [ top1] ) E  E1 + T val [top 2 ] = val [top 2]+val [top] E  T T  T1  F val [top 2]val [top] T  F F (E) F.val = E.val F  digit F.val = digit.lexval . . . Z Z. z Y Y. y X X.x top 栈 state val 省略top指针的移动

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (val [ top1] ) 产 生 式 代 码 段 L  E n print (val [ top1] ) E  E1 + T val [top 2 ] = val [top 2]+val [top] E  T T  T1  F val [top 2]val [top] T  F F (E) val [top 1] F  digit F.val = digit.lexval . . . Z Z. z Y Y. y X X.x top 栈 state val

简单计算器的语法制导定义改成栈操作代码 产 生 式 代 码 段 L  E n print (val [ top1] ) 产 生 式 代 码 段 L  E n print (val [ top1] ) E  E1 + T val [top 2 ] = val [top 2]+val [top] E  T T  T1  F val [top 2]val [top] T  F F (E) val [top 1] F  digit . . . Z Z. z Y Y. y X X.x top 栈 state val

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

L属性定义 每个产生式AX1…Xj-1Xj…Xn的每条语义规则计算 的属性要么是A的综合属性;要么是Xj 的继承属 性,但它仅依赖: 该产生式中Xj左边符号X1, X2, …, Xj-1的属性; A的继承属性 S属性定义属于L属性定义 依赖A的综合属性? 综合属性可能需要把产生式的右部全看完才计算

变量类型声明的语法制导定义是一个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

变量类型声明的语法制导定义是一个L属性定义 属性信息自左向右流动 D int T , id3 L id2 id1 1 entry 10 2 entry 3 entry in 9 8 in 7 6 in 5 4 type

变量类型声明的语法制导定义是一个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

怎么办? 需要考虑语义规则的执行时机 语法制导的翻译方案:反映语义规则执行时机的 描述方法 在产生式右部中嵌入了语义动作 A   {…} ,{…}中语义动作的执行在的推导(或向 的归约)结束以后,在的推导(或向的归约)开 始以前

L属性定义的翻译方案 例 把有加和减的中缀表达式翻译成后缀表达式 如果输入是8+5 2,则输出是8 5 + 2  E  T R 例 把有加和减的中缀表达式翻译成后缀表达式 如果输入是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()} 如果移到别处会导致结果不正确

设计翻译方案时,语义动作放哪? 必须保证动作在引用属性时其值已经计算出来了 只有综合属性:为每条语义规则建立一个赋值动作,放 在产生式右部末端 有继承属性时: 产生式右部符号的继承属性必须在先于这个符号的动作中计算 一个动作不能引用该动作右边符号的综合属性 左部非终结符的综合属性只能在它所引用的所有属性都计算完 后才能计算。通常放在产生式右部末端 对L属性定义,总是可能构造满足这三个条件的翻译方案

L属性定义 E .val 例 数学排版语言EQN E sub 1 .val S  B B  B1 B2 B  B1 sub B2 B  text E 1 .val

L属性定义 例 数学排版语言EQN(语法制导定义) 产 生 式 语 义 规 则 S  B B.ps = 10; S.ht = B.ht 产 生 式 语 义 规 则 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 B1和B2继承B的字体大小 B2字体缩小 计算B的高度时把B2向下偏置 实际高度:文本的正常高度 * 字体大小

L属性定义的翻译方案 例 数学排版语言EQN(翻译方案) S  {B.ps = 10 } B的继承属性的计算 B {S.ht = B.ht } 位于B的左边

L属性定义的翻译方案 例 数学排版语言EQN(翻译方案) S  {B.ps = 10 } B的综合属性的计算 B {S.ht = B.ht } 放在右部末端

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 } 52

L属性定义的自顶向下计算 例 左递归的消除引起继承属性 产 生 式 语 义 规 则 E  E1 + T 例 左递归的消除引起继承属性 产 生 式 语 义 规 则 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)

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的信息传给R 每个产生式结束时把属性向上传

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

a * 5 * b的语法树构造 略去了E  TR  T 部分 T i W F.nptr id  i W num i W s 

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

L属性的自底向上计算 前面介绍了S属性定义的自底向上计算 修改文法,使得L属性定义中所有的嵌入动作都 变换成只出现在产生式右端 产 生 式 产 生 式 代 码 段 L  E n print (val [ top1] ) E  E1 + T val [top 2 ] = val [top 2]+val [top] E  T T  T1  F val [top 2 ] = val [top 2]val [top] T  F F (E) val [top 2 ] = val [top 1] F  digit

L属性的自底向上计算 删除翻译方案中嵌入的动作 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 (‘’)} 这些动作的一个重要特点: 没有引用原来产生式文法符号的属性 所以可以如此变换

L属性的自底向上计算 A   {a} ,若动作a引用A或中符号的属性呢? 考虑A  X Y的移进-归约分析栈 若X有综合属性X.s,则会放在分析栈中X对应的地方 那么在Y以下的任何子树归约前,X.s的值已经在分析 栈中 如果Y的继承属性Y.i由 Y.i = X.s 定义,那么在需要使用 Y.i的地方可以用X.s来代替 如果能静态预测X.s在栈中的位置,那么对Y.i的使用很 容易换成栈操作代码

L属性的自底向上计算 分析栈上的继承属性 例 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 )}

L属性的自底向上计算 D T L , r q p int  type in 分析栈上的继承属性 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 )}

L属性的自底向上计算 D T L , r q p int  type in 分析栈上的继承属性 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 )} L.in = T.type ,而T.type此时位于栈顶 – 1 L.in = T.type ,而T.type此时位于栈顶 – 3

L属性的自底向上计算 D T L , r q p int  type in 分析栈上的继承属性 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 )} L.in = T.type ,而T.type此时位于栈顶 – 1 L.in = T.type ,而T.type此时位于栈顶 – 3 T.type ,栈顶 – 3 T.type ,栈顶 – 1

L属性的自底向上计算 D T L , r q p int  type in 分析栈上的继承属性 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 )} 继承属性的计算可 以删去,引用继承属 性的地方改成引用其 他符号的综合属性

L属性的自底向上计算 D T L , r q p int  type in 产 生 式 代 码 段 D  TL T int 代 码 段 D  TL T int val[top] = integer T real val[top] = real L L1, id addType(val[top], val[top3]) L id addType(val[top], val[top1])

L属性的自底向上计算 2、属性的位置不能预测 S  aAC C.i = A.s S  bABC C.i = A.s C  c C.s = g(C.i) 在用C  c归约时,C.i的值(也就是A.s的值)可能在val[top – 2],也可能在val[top – 1]

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 在用C  c归约时,C.i的值总是在val[top – 1]

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 还得考虑M.i 计算的可预测 在用M  归约时,M.i的值总是在val[top – 1]

L属性的自底向上计算 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) 在用N  归约时,N.i的值总是在val[top] 在用C  c归约时,C.i的值总是在val[top – 1]

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 } 77

L属性的自底向上计算 产 生 式 语 义 规 则 S  LB B.ps = L.s; S.ht = B.ht 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

L属性的自底向上计算 产 生 式 语 义 规 则 S  LB B.ps = L.s; S.ht = B.ht 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

L属性的自底向上计算 产 生 式 语 义 规 则 S  LB B.ps = L.s; S.ht = B.ht 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

L属性的自底向上计算 举例说明 S M s B  L s text sub N s 在text归约成B时,B的 ps属性都在次栈顶位置 在归约成M时,M.i也 在次栈顶位置 在归约成N时,N.i在 栈顶 – 2的位置

L属性的自底向上计算 产 生 式 语 义 规 则 S  LB B.ps = L.s; S.ht = B.ht L   L.s = 10 产 生 式 语 义 规 则 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

L属性的自底向上计算 产 生 式 代 码 段 S  LB val[top1] = val[top] L   L.s = 10 产 生 式 代 码 段 S  LB val[top1] = val[top] 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

L属性的自底向上计算 产 生 式 代 码 段 S  LB val[top1] = val[top] L   产 生 式 代 码 段 S  LB val[top1] = val[top] L   val[top+1] = 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

L属性的自底向上计算 产 生 式 代 码 段 S  LB val[top1] = val[top] L   产 生 式 代 码 段 S  LB val[top1] = val[top] L   val[top+1] = 10 B  B1 MB2 val[top2] = max(val[top2], val[top]) 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

L属性的自底向上计算 产 生 式 代 码 段 S  LB val[top1] = val[top] L   产 生 式 代 码 段 S  LB val[top1] = val[top] L   val[top+1] = 10 B  B1 MB2 val[top2] = max(val[top2], val[top]) M   val[top+1] = val[top1] 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

L属性的自底向上计算 产 生 式 代 码 段 S  LB val[top1] = val[top] L   产 生 式 代 码 段 S  LB val[top1] = val[top] L   val[top+1] = 10 B  B1 MB2 val[top2] = max(val[top2], val[top]) M   val[top+1] = val[top1] B  B1 sub NB2 val[top3] = disp (val[top3], val[top] ) N   N.s = shrink(N.i) B  text B.ht = text.h  B.ps

L属性的自底向上计算 产 生 式 代 码 段 S  LB val[top1] = val[top] L   产 生 式 代 码 段 S  LB val[top1] = val[top] L   val[top+1] = 10 B  B1 MB2 val[top2] = max(val[top2], val[top]) M   val[top+1] = val[top1] B  B1 sub NB2 val[top3] = disp (val[top3], val[top] ) N   val[top+1] = shrink(val[top2]) B  text B.ht = text.h  B.ps

L属性的自底向上计算 产 生 式 代 码 段 S  LB val[top1] = val[top] L   产 生 式 代 码 段 S  LB val[top1] = val[top] L   val[top+1] = 10 B  B1 MB2 val[top2] = max(val[top2], val[top]) M   val[top+1] = val[top1] B  B1 sub NB2 val[top3] = disp (val[top3], val[top] ) N   val[top+1] = shrink(val[top2]) B  text val[top] = val[top]  val[top1]

本章小结 语法制导的定义和翻译方案 语法制导定义和翻译方案的实现 S属性的自底向上计算(边分析边计算) L属性的自顶向下计算(边分析边计算)