编译原理与技术 语法制导翻译 2019/1/17 《编译原理与技术》讲义.

Slides:



Advertisements
Similar presentations
小说三要素 人物 情节 环境 凹 ( ) 凼 ( ) 硌 ( ) 涎 ( ) 水 揩 ( ) 嘎 ( ) 筹 ( ) 划 黏 ( ) 撬 ( ) 尴尬 ( ) 过瘾 ( ) 唿 ( ) 嗒 熬 ( ) 住 憋 ( ) 住 门槛 ( ) 微不足道 : 大庭广众 : āo dàng gè xián.
Advertisements

說 劍 《莊子‧雜篇》─ 第 一 組 賴泊錞 謝孟儒 張維真 羅苡芸
第四章:长期股权投资 长期股权投资效果 1、控制:50%以上 有权决定对方财务和经营.
第六课 遗传与变异 第六课时 性别决定和伴性遗传.
台 阶 李森祥.
地方教育發展基金執行實務 王麗真、江明君、魏珮如 1.
编 译 原 理 指导教师:杨建国 二零一零年三月.
订单合并拆分功能详解 荷叶.
第五章 语法制导的翻译 赵建华 南京大学计算机系 2010年3月.
黔 驴 技 穷 黔 驴 之 技 小露一手 请说出和驴”相关的成语\俗语 非驴非马 借坡下驴 驴年马月 卸磨杀驴 驴唇不对马嘴 骑驴看唱本
任课老师:戴新宇 助教: 实验一 词法分析和语法分析 任课老师:戴新宇 助教: 2014年3月20日.
习题与试题 认真复习,重点是掌握基本概念。基本概念掌握了,相当一部分试题的解就有了
初中语文总复习 说明文 阅读专题 西安市第六十七中学 潘敏.
跳楼价 亏本大甩卖 清仓处理 买一送一 5折酬宾. 跳楼价 亏本大甩卖 清仓处理 买一送一 5折酬宾.
清仓处理 跳楼价 满200返160 5折酬宾.
2-7、函数的微分 教学要求 教学要点.
编译原理与技术 --文法和分析 2018/9/17 《编译原理与技术》讲义.
Part5语法分析 授课:胡静.
第七章 中间代码生成 静态 中间 分析 检查 代码 记号流 器 生成 本章内容 介绍几种常用的中间表示:后缀表示、图形表示和三地址代码
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
编译原理习题
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 《编译原理与技术》讲义.
如何寫工程計畫書 臺北市童軍會考驗委員會 高級考驗營 版.
第三章 词法分析.
管理信息结构SMI.
走进编程 程序的顺序结构(二).
辅导课程六.
Part5语法分析 授课:胡静.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
语义分析简介 编译程序的目标:将源程序翻译成为语义等价的目标程序。 语义分析的主流技术:
LL(1)分析方法 LL(1)是LL(k)的特例,其中的k则表示向前看k个符号. LL(1)方法和递归下降法属于同一级别的自顶向下分析法.
第六、七章属性文法、语法制导翻译和中间代码
第八章语法制导翻译和中间代码生成 8.1概述 8.2属性文法和语法制导翻译 8.3语义分析 8.4中间代码 8.5一些语句的翻译.
第二章 Java语言基础.
动态规划(Dynamic Programming)
语法制导的翻译 (Syntax-Directed Translation)
《编译原理与技术》 期末复习 计算机科学与技术学院 郑启龙 李 诚 25/12/2018.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
第三章 语法分析 自顶向下语法分析思想 语法分析方法的分类: 自顶向下语法分析方法(Top-Down) ,亦称面向目标的分析方法;
语法分析 本章内容 语法分析器:把词法分析生成的词法单元流翻译成语法分析树(parse tree)
第3,4次课 一个简单的语法制导翻译器 2.3~2.5.
编译原理与技术 第4章 语法制导的翻译 6学时.
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
编译原理总结-1 第3~5章.
编译原理实践 13.语法分析程序的自动生成工具YACC.
文法等价变换 文法的等价 对文法G1和G2,若有:L(G1)=L(G2),则称文法G1和G2等价, 记作:G1=G2. 文法等价变换
第六章 语法制导的翻译 本章内容 介绍一种语义描述方法:语法制导的翻译,介绍语法制导的翻译的实现方法。
自底向上的语法分析 4.5.
第4章 Excel电子表格制作软件 4.4 函数(一).
第九节 赋值运算符和赋值表达式.
iSIGHT 基本培训 使用 Excel的栅栏问题
编译原理与技术 -- 自顶向下分析 2019/5/5 《编译原理与技术》讲义.
3.16 枚举算法及其程序实现 ——数组的作用.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
第十七讲 密码执行(1).
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
编译原理实践 6.程序设计语言PL/0.
第二次课后作业答案 函数式编程和逻辑式编程
第8章 语法制导翻译与中间代码生成.
Presentation transcript:

编译原理与技术 语法制导翻译 2019/1/17 《编译原理与技术》讲义

语法制导翻译 属性文法 自底向上翻译 自顶向下翻译 S-属性定义 L-属性定义 语法制导定义与翻译方案 S-属性定义自底向上计算 自底向上计算继承属性 自顶向下翻译 2019/1/17 《编译原理与技术》讲义

属性文法 属性文法(Attributed Grammar) 上下文无关文法+属性+属性计算规则 属性-用来描述文法符号的语义特征,如 常量的“值”、变量的类型和存储位置等。 e.g. 二义性表达式文法G,非终结符E有属性E.val(表达式的值) EE ‘+’ E | E ‘*’ E | ‘(‘ E ‘)’ | number 属性计算规则(语义规则) 与产生式相关联的反映文法符号属性之间关系的“规则” 2019/1/17 《编译原理与技术》讲义

语义规则仅表明属性间“抽象”关系,不涉及具体翻译实现细节,如计算次序等。 属性文法 语法制导定义(文法+属性+语义规则) 语义规则仅表明属性间“抽象”关系,不涉及具体翻译实现细节,如计算次序等。 翻译方案(文法+属性+语义动作) 语义规则-即语义动作,可体现若干实现的细节。 2019/1/17 《编译原理与技术》讲义

e.g.1算术表达式的计算器 产生式 语法制导定义 EE1 ‘+’ E2 E.val := E1.val + E2.val 产生式 语法制导定义 EE1 ‘+’ E2 E.val := E1.val + E2.val EE1 ‘*’ E2 E.val := E1.val * E2.val E’(‘ E1 ‘)’ E.val := E1.val Enumber E.val := number.lex_val 2019/1/17 《编译原理与技术》讲义

e.g.1算术表达式的计算器 产生式 翻译方案 EE1 ‘+’ E2 { E.val := E1 .val + E2.val } 产生式 翻译方案 EE1 ‘+’ E2 { E.val := E1 .val + E2.val } EE1 ‘*’ E2 { E.val := E1.val * E2.val } E’(‘ E1 ‘)’ { E.val := E1.val } Enumber { E.val := number.lex_val } 2019/1/17 《编译原理与技术》讲义

属性文法 属性的分类 若产生式AX1X2…Xn,与之相关的属性计算规则 b := f ( c1, c2, … ) -如果属性b是产生式左部符号A的属性则称其为A的综合属性; -如果属性b是产生式右部符号Xi的属性则称其为Xi的继承属性; -c1, c2, … 一般是产生式右部其它符号的(综合)属性或A的继承属性; - 固有属性:终结符仅有的属性。如number.lex_val。通常由词法程序提供。 2019/1/17 《编译原理与技术》讲义

属性依赖图 A.b A X1.c1 X2.c2 … Xn.cn X1.c1 X2.c2 Xk.b … Xn.cn 继承属性Xk.b的计算 2019/1/17 《编译原理与技术》讲义

e.g. 2 属性依赖图: 3+4×5 + E. val = 23 E. val = 3 E. val = 20 number. lex_val = 3 E. val = 4 × E. val = 5 number. lex_val = 4 number. lex_val = 5 2019/1/17 《编译原理与技术》讲义

语义规则的计算方法 分析树方法 基于规则的方法 忽略规则的方法 - 为输入串建立分析树 - 由语义规则建立属性依赖图(没有属性循环依赖的) - 对依赖图进行拓扑排序,得到属性计算次序 - 依次计算属性,得到“翻译”结果 基于规则的方法 - 构造编译器时,事先对产生式的语义规则进行分析,得到属性计算次序 忽略规则的方法 - 属性计算次序仅由分析方法限定。如S-属性定义可以在自下而上分析时,在归约前计算。如YACC中的语义动作。 2019/1/17 《编译原理与技术》讲义

e.g. 3 属性计算次序: 3+4×5 + E. val = 23 E. val = 3 E. val = 20 8 E. val = 23 2 7 E. val = 3 + E. val = 20 6 1 4 number. lex_val = 3 E. val = 4 × E. val = 5 3 5 number. lex_val = 4 number. lex_val = 5 2019/1/17 《编译原理与技术》讲义

S-属性定义 -语义规则仅包含综合属性计算(可以有固有属性出现)。 -适合自底向上计算 e.g. 语法树 -语法树与分析树 语法树可看作分析树的浓缩。也称抽象语法树。而分析树可看成具体语法树。 2019/1/17 《编译原理与技术》讲义

语法树 vs. 分析树 S  if B-expr then S1 else S2 语法树 分析树 S if-then-else 语法树 分析树 S if-then-else B-expr S1 S2 if B-expr then S1 else S2 2019/1/17 《编译原理与技术》讲义

语法树 vs. 分析树 a := b* -c + b * -c 语法树 分析树 赋值语句 assign 算符 E assign E a + 语法树 分析树 赋值语句 assign 算符 E assign E a + a E + E * * E * E E * E b @ b @ @ E @ b b E c c c c 2019/1/17 《编译原理与技术》讲义

语法树 vs. DAG DAG(去除了公共子表达式的无环有向图) a := b* -c + b * -c assign assign a + @ b @ b @ c c c 语法树 DAG 2019/1/17 《编译原理与技术》讲义

e.g.4 构造表达式的语法树(DAG) 产生式 语义规则 产生式 语义规则 EE1 + E2 E.nptr := mknode(‘+’,E1.nptr, E2.nptr) EE1 - E2 E.nptr := mknode(‘-’,E1.nptr, E2.nptr) EE1 * E2 E.nptr := mknode(‘*’,E1.nptr, E2.nptr) EE1 / E2 E.nptr := mknode(‘/’,E1.nptr, E2.nptr) E( E1 ) E.nptr := E1.nptr E - E1 E.nptr := mknode(‘@’,E1.nptr, -) Enumber E.nptr := mkleaf(‘NUM’,number.lex_val) Eid E.nptr := mkleaf(‘ID’,id.entry) 2019/1/17 《编译原理与技术》讲义

e.g.4 构造表达式的语法树(DAG) E.nptr - E的语法树(根结点指针) mknode(op, left, right)-建立一个表达式语法树结点,它的运算符为op,左、右运算对象是left和right所指的语法树。如果建成DAG,则需要检查是否已存在相应内部结点op,其左右运算对象分别是left和right。若没有则新建一个。 mkleaf(‘NUM’,number.lex_val)- mkleaf(‘ID’,id.entry)- 建立表达式语法树的叶结点。建DAG也需检查是否已有相应结点。 2019/1/17 《编译原理与技术》讲义

e.g.4 构造表达式a+b*-4的属性结构树 + * @ - ID a ID b NUM 4 E.nptr E.nptr + E.nptr 2019/1/17 《编译原理与技术》讲义

e.g.4 构造表达式a+b*-4的语法树(DAG) ID a * ID b @ - NUM 4 2019/1/17 《编译原理与技术》讲义

L-属性定义 -如果产生式AX1X2…Xn 的语义规则只计算 1)A的综合属性,或者 2)Xi的继承属性,且该属性仅依赖于产生式右部Xi的左边符号Xj(j<i)的(综合)属性或A的继承属性; -S-属性定义均为L-属性定义 -可按深度优先次序计算 - 一种自然的属性计算次序 - 在分析期间完成翻译。属性计算与结点建立有联系;适合于自顶向下和自底向上分析方法。 2019/1/17 《编译原理与技术》讲义

深度优先次序 procedure dfvisit( n : node ) begin for each child m of n, from left to right do begin evaluate inherited attributes of m; dfvisit( m ) ; end; evaluate synthesized attributes of n; end 2019/1/17 《编译原理与技术》讲义

e.g.5 非L-属性定义的语法制导定义 产生式 语义规则 ALM L.i := l(A.i) M.i := m(L.s) 产生式 语义规则 ALM L.i := l(A.i) M.i := m(L.s) A.s := f(M.s) AQR R.i := r(A.i) Q.i := q(R.s) A.s := f(Q.s) 2019/1/17 《编译原理与技术》讲义

翻译方案中的动作 -语义动作可放在产生式右端任何位置;这也就显式地给出了动作的执行时刻。(可认为是在深度优先遍历中的执行时刻) e.g. 6将含有+和-运算的中缀表达式翻译为后缀形式: ET R R addop T { print( addop.lex_val) } R |  T number { print( number.lex_val) } 2019/1/17 《编译原理与技术》讲义

e.g. 6 中缀翻译为后缀 :9-4+5 E T R - T print(‘-’) R 9 print(9) 4 print(4) + T 3 1 4 print(4) + T print(‘+’) R 5 2  5 print(5) 4 2019/1/17 《编译原理与技术》讲义

翻译方案中的动作 -设计翻译方案时,必须保证动作所引用的属性值是可用的。 -只有综合综合属性时(S-属性定义),动作放在产生式末尾; - 若有继承属性时,动作的放置须保证: - (产生式右部)符号的继承属性必须在 此符号前计算; - 动作不要引用其右边符号的综合属性; - 左部非终结符的综合属性一般放在产生式末 尾(确保它引用的属性均已计算完且可用) 2019/1/17 《编译原理与技术》讲义

e.g.7 翻译方案的书写 S  A1 A2 { A1.in := 1 ; A2.in := 2 } A  a { print( A.in ) } 改写为: S  { A1.in := 1 } A1 { A2.in := 2 } A2 2019/1/17 《编译原理与技术》讲义

e.g.8 类型说明的语法制导定义(0) 产生式 语义规则 DT L L.in := T.type 产生式 语义规则 DT L 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 addtype(id.entry, L.in) 2019/1/17 《编译原理与技术》讲义

e.g.8 类型说明的语法制导定义(0)- 属性传递 D T L L , k int L , j i 2019/1/17 《编译原理与技术》讲义

e.g.8类型说明的语法制导定义(1) 改写上述类型声明文法,使得其中的T成为L的子结点(即产生式右部),可以避免继承属性的使用。修改后文法如下: DL Tint Treal LL1 , id LT id 2019/1/17 《编译原理与技术》讲义

e.g.8类型说明的语法制导定义(2) 产生式 语义规则 D L Tint T.type := integer 产生式 语义规则 D L Tint T.type := integer Treal T.type := real LL1 , id L.in := L1.in addtype(id.entry, L1.in) LT id addtype(id.entry, T.type); L.in := T.type 2019/1/17 《编译原理与技术》讲义

D e.g.8类型说明的语法制导定义(2) 属性传递 L L , k L , j T i int 2019/1/17 《编译原理与技术》讲义

e.g.8 类型说明的语法制导定义(3) Pascal语言类型声明文法如下: DL : T Tint Treal LL1 , id 该声明文法的“问题”在于,L中声明的变量的类型T处于产生式中L的右边!若用继承属性L.in来传递类型信息T.type形成非L-属性定义。从而无法在完成L分析同时将有关类型信息填入符号表!可以考虑将T作为L的子结点(通过修改文法)来改变这种情况 2019/1/17 《编译原理与技术》讲义

e.g.8 类型说明的语法制导定义(4) 产生式 语义规则 D id L addtype(id.entry,L.in) 产生式 语义规则 D id L addtype(id.entry,L.in) Tint T.type := integer Treal T.type := real L, id L1 L.in := L1.in addtype(id.entry, L1.in) L : T L.in := T.type 2019/1/17 《编译原理与技术》讲义

e.g.9 翻译方案的计算次序 EE+T { print( “1” ) } ET { print( “2” ) } TT*F { print( “3” ) } TF { print( “4” ) } F(E) { print( “5” ) } Fid { print( “6” ) } 输入串是id*(id+id)时,该翻译方案输出什么? 2019/1/17 《编译原理与技术》讲义

S-属性定义的自底向上计算 拓广分析栈,即添加属性栈,包含文法符号的综合属性。在归约实施前,右部各符号的综合属性(若有的话)已放在与符号位置对应的属性栈上,因此,可以先计算获得左部非终结符的综合属性。然后再归约,这时从分析栈中弹出句柄,(注意,此时改变栈顶top即可)最后,将左部符号连同其属性放入由top指示的分析栈及属性栈的位置中。 这种属性栈只能存放综合属性。 回想YACC中如何做的? 2019/1/17 《编译原理与技术》讲义

属性栈与分析栈 如果AXYZ,相关 语义规则如下: A.a := f(X.x,Y.y,Z.z) 显然, X.x在Val[top-2] Y.y在Val[top-1] Z.z在Val[top] A.a在Val[ntop] ,ntop = top – |句柄长度|+1 Val[ ntop ] := f( val[top-2], Val[top-1], Val[top] ) Z Z.z Y Y.y X X.x … 分析栈 属性栈 Val top bottom 2019/1/17 《编译原理与技术》讲义

属性栈与分析栈 如果AB ,相关 语义规则如下: A.a := B.b 显然, B.b在Val[top] A.a在Val[ntop] , ntop = top – 1+1 = top ,即归约前后栈顶top不变, 也即Val[ ntop ] 和 Val[top]对应属性栈同一个单元, 所以,可以省略原语义规则对应的属性栈操作: Val[ntop] := Val[top] top B B.b … … bottom … … 分析栈 属性栈Val 2019/1/17 《编译原理与技术》讲义

e.g.10 计算表达式的(栈)代码 产生式 语义规则 代码段 Print( Val[top-1] ) LE ‘\n’ Print( E.val ) Print( Val[top-1] ) EE1+T E.val := E1.val + T.val Val[ntop]:=Val[top-2]+Val[top] ET E.val := T.val TT1*F T.val := T1.val * F.val Val[ntop]:=Val[top-2]*Val[top] TF T.val := F.val F(E) F.val := E.val Val[ntop]:=Val[top-1] Fdigit F.val := digit.lex_val 2019/1/17 《编译原理与技术》讲义

自底向上计算继承属性 如何在自底向上分析中计算继承属性? - 属性栈上仅能存放综合属性 - 能否将继承属性的引用转换成综合属性? 分析栈中符号的继承属性 - 属性copy规则 如果,AXY,有语义规则Y.i := X.s, 翻译方案可写为: A  X { Y.i := X.s } Y 2019/1/17 《编译原理与技术》讲义

自底向上计算继承属性 - 由属性copy规则可知,Y的继承属性Y.i和X.s在属性栈上同一位置。这样对属性Y.i的引用可以转化为对X.s的引用。若计算Y的综合属性Y.s时需要引用 Y.i,则此时Y.i(即X.s)就紧邻在句柄下面; 如果Y的句柄形成前, 它的某个右部符号 需使用Y.i,这时, 也可以直接使用Y.i。 (How to use?) bottom … X X.s(Y.i) 分析栈 属性栈 Val top 句柄 (归约为Y) top-句柄长 2019/1/17 《编译原理与技术》讲义

e.g.11 C声明的翻译方案 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) } 对于输入串:int p,q,r 分析过程如下: 2019/1/17 《编译原理与技术》讲义

输入串 分析栈 产生式 int p,q,r p,q,r int p,q,r T Tint ,q,r Tp ,q,r TL Lid 输入串 分析栈 产生式 int p,q,r p,q,r int p,q,r T Tint ,q,r Tp ,q,r TL Lid q,r TL, ,r TL,q ,r TL LL , id r TL, TL,r TL LL , id D DTL 注意:每次归约成L时,T与L的位置关系--T就在句柄的下面! 2019/1/17 《编译原理与技术》讲义

e.g.11 C声明的“代码段” 产生式 代码段(只含综合属性) DT L Tint val[ntop]:=integer 产生式 代码段(只含综合属性) DT L Tint val[ntop]:=integer Treal val[ntop]:=real L L1 , id addtype(val[top],val[top-3]) Lid addtype(val[top],val[top-1]) L的继承属性L.in 2019/1/17 《编译原理与技术》讲义

模拟继承属性的计算 问题1:继承属性的位置在构造编译器时不可预知(或不固定),如e.g.12 产生式 语义规则 产生式 语义规则 S  a A C C.i := A.s S  b A B C C.i := A.s C  c C.s := g(C.i) … 用C  c归约时,C.i的值可能在val[top-1]或者在val[top-2]的位置上。解决办法是考虑将其统一。 引入标记非终结符 M和产生式M  。 top c c A B a A b … … bottom 分析栈1 分析栈2 2019/1/17 《编译原理与技术》讲义

e.g.12 引入标记非终结符 产生式 语义规则 S  a A C C.i := A.s S  b A B M C C.i := M.s 产生式 语义规则 S  a A C C.i := A.s S  b A B M C C.i := M.s M.i := A.s C  c C.s := g(C.i) M  M.s := M.i … 引入M后,C.i 可从句柄c的下面(val[top-1])取得!属性传递: A.s  M.i  M.s  C.i  C.s top c c A M a B … A … b … … bottom 分析栈1 分析栈2 2019/1/17 《编译原理与技术》讲义

C  c val[ntop]:= g(val[top-1]) M  val[ntop] := val[top-1] … 产生式 代码段 S  a A C S  b A B M C C  c val[ntop]:= g(val[top-1]) M  val[ntop] := val[top-1] … 可否将M放在S a A C产生式中? M.i 2019/1/17 《编译原理与技术》讲义

模拟继承属性的计算 问题2:语义规则不是简单的属性复写拷贝。 e.g.13 : 将例12中的S  a A C语义规则换为: 产生式 语义规则 S  a A C C.i := f( A.s ) 虽然在例12中引入了M使得“A.s”可在val[top-1] 处找到,但在S的两个产生式中C.i的取值方式 不同,导致C.s的计算嘛… 这次可以考虑引入标记非终结符N和N 2019/1/17 《编译原理与技术》讲义

e.g.13 引入标记非终结符N 产生式 语义规则 S  a A N C C.i := N.s N.i := A.s 产生式 语义规则 S  a A N C C.i := N.s N.i := A.s N N.s := f(N.i) (其他产生式和语义规则不变) (代码段略) 2019/1/17 《编译原理与技术》讲义

e.g.14 文字排版的语法制导定义 产生式 语义规则 SB B.ps := 10 S.ht := B.ht 产生式 语义规则 SB B.ps := 10 S.ht := B.ht BB1B2 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 2019/1/17 《编译原理与技术》讲义

文字排版中的符号属性 S : S.ht,综合属性;待排公式的整体高度 B : B.ps,继承属性; 公式(文本)中字体“点”的大小 B.ht,综合属性;公式排版高度 text :text.h,文本高度 max :求两个排版公式的最大高度 shrink(B) :将点大小缩小为B的30% disp(B1.ht,B2.ht):向下调整B2的位置 E Val 1 2019/1/17 《编译原理与技术》讲义

文字排版的翻译方案(0) S { B.ps := 10 } B { S.ht := B.ht } B { B1.ps := B.ps } B2 { B.ht := max(B1.ht,B2.ht) } B1 sub { B2.ps := shrink(B.ps) } B2 { B.ht := disp(B1.ht,B2.ht) } B text { B.ht := text.h × B.ps } 2019/1/17 《编译原理与技术》讲义

文字排版中引入标记符号 为了自底向上计算: B text { B.ht := text.h × B.ps } 入标记非终结符L、M和N及其属性,包括相应的空产 生式和有关属性规则。这样B.ps即可在紧靠“句柄”text 下方的位置上找到。(L的综合属性置为B.ps的初值) SL B BB1M B2 BB1 sub N B2 top text text.h L L.s=10 bottom 分析栈 属性栈 2019/1/17 《编译原理与技术》讲义

文字排版的翻译方案(1) S L { B.ps := L.s } L { L.s := 10 } B { S.ht := B.ht } B { B1.ps := B.ps } M { M.s := M.i } B1 { M.i := B.ps } M { B2.ps := M.s } B2 { B.ht := max(B1.ht,B2.ht) } B { B1.ps := B.ps } B1 sub { N.i := B.ps } N { N.s :=shrink(N.i) } N { B2.ps := N.s } B2 { B.ht := disp(B1.ht,B2.ht) } B text { B.ht := text.h × B.ps } 2019/1/17 《编译原理与技术》讲义

S L B val[ntop] := val[top] 产生式 代码段 S L B val[ntop] := val[top] BB1 M B2 val[ntop] := max(val[top-2],val[top]) BB1 sub N B2 val[ntop] := disp(val[top-3],val[top]) B text val[ntop] := val[top]×val[top-1] L val[ntop] := 10 M val[ntop] := val[top-1] N val[ntop] := shrink( val[top-2] ) 2019/1/17 《编译原理与技术》讲义

(L-属性定义)自顶向下翻译 删除翻译方案中的左递归 A  A1Y { A.a := g(A1.a, Y.y) } A  X { A.a := f( X.x) } 消除左递归: A  X { R.i := f( X.x) }//传递“左”运算量 R { A.a := R.s } R  Y { R1.i := g(R.i, Y.y) } R1 { R.s := R1.s } R   { R.s := R.i }//返回结果 2019/1/17 《编译原理与技术》讲义

输入串XY1Y2的翻译 A.a X R.i := f(X.x) R.s y2 Y1 R.i := g(f(X.x),Y1.y) R.s y1 A.a := g(g(f( X.x), y1.y), y2.y) y2 Y1 A.a := g(f( X.x), y1.y) R.i := g(f(X.x),Y1.y) R.s y1 A.a := f( X.x) Y2 R.i := g(g(f(X.x),Y1.y), Y2.y) X R.s  2019/1/17 《编译原理与技术》讲义

e.g.15 删除翻译方案中左递归 EE1 + T { E.nptr := mknode(‘+’,E1.nptr, T.nptr)} ET { E.nptr := T.nptr } T( E ) { T.nptr := E.nptr } Tnum { T.nptr := mkleaf(‘NUM’,num.val) } Tid { T.nptr := mkleaf(‘ID’,id.entry) } 2019/1/17 《编译原理与技术》讲义

T { R1.i := mknode(‘+’, R.i, T.nptr) } //”建树“ R1 { R.s := R1.s } R - E T { R.i := T.nptr } R { E.nptr := R.s } R + T { R1.i := mknode(‘+’, R.i, T.nptr) } //”建树“ R1 { R.s := R1.s } R - T { R1.i := mknode(‘-’, R.i, T.nptr) } R  { R.s := R.i } //返回最终语法树 (其余略) 2019/1/17 《编译原理与技术》讲义

(递归下降)预测翻译器的设计 为每个非终结符A构造用于分析和属性计算的函数(注意,在递归下降的语法分析中构造的仅是过程),这样的函数构成如下: - 参数:符号A的继承属性 - 返回值:符号A的综合属性(记录) - 局部变量:A的产生式中每个符号的属性均有对应的局部量(A的继承属性除外) - 函数体形式为:(类似递归分析过程) -根据输入符号决定产生式的选择; - 对每个可能选择的产生式从左自右分析并计算属性(执行语义动作) 2019/1/17 《编译原理与技术》讲义

- 对每个可能选择的产生式从左自右分析并计算属性(执行语义动作): (1)终结符X,将X.x保存在相应的局部量中(如果有的话),调用match(X); (2)非终结符B,产生赋值 c := B(b1,b2,…bn),c和bi分别是B的综合属性和继承属性对应的局部变量; (3)语义动作,将代码直接拷贝到函数体中,而其中属性出现改为局部量的引用; (4)函数结尾:return A的综合属性。 2019/1/17 《编译原理与技术》讲义

e.g.16 递归翻译函数 R + T { R1.i := mknode(‘+’, R.i, T.nptr) } R1 { R.s := R1.s } R - T { R1.i := mknode(‘-’, R.i, T.nptr) } R  { R.s := R.i } 2019/1/17 《编译原理与技术》讲义

node_ptr R ( node_ptr i ) { node_ptr nptr, i1, s1, s ; //符号属性对应的局部量 if (lookhead == ‘+’) { // R  + T R match(‘+’); nptr = T(); i1 = mknode( ‘+’, i, nptr ); //语义动作 s1 = R ( i1 ); s = s1 ; // 语义动作 } else if … // R  - T R else s = i ; // R   语义动作 return s; 非终结符R的递归翻译函数 2019/1/17 《编译原理与技术》讲义