Download presentation
Presentation is loading. Please wait.
1
编译原理与技术 第4章 语法制导的翻译 6学时
2
介绍语义描述的一种形式方法:语法制导的翻译,它包括两 种具体形式
4 语法制导的翻译 内容提要 介绍语义描述的一种形式方法:语法制导的翻译,它包括两 种具体形式 语法制导的定义 翻译方案 介绍语法制导翻译的实现方法
3
第4章 语法制导的翻译 4.1 语法制导的定义 1学时
4
例:简单计算器的语法制导定义 产 生 式 语 义 规 则 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
5
一组形式为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的属性
6
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
7
注释分析树:结点的属性值都标注出来的分析树 8+52 n的注释分析树 各结点属性的计算可以自下而上地完成
4.1 语法制导的定义 注释分析树:结点的属性值都标注出来的分析树 8+52 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
8
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
9
int id1, id2, id3的标注了部分属性的分析树 不可能像综合属性那样自下而上标注属性
4.1 语法制导的定义 int id1, id2, id3的标注了部分属性的分析树 不可能像综合属性那样自下而上标注属性 D int T.type = integer , id3 L.in = integer id2 id1
10
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
11
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
12
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
13
分析树方法:刚才介绍的方法,动态确定计算次序,效率低。 概念上的一般方法
4.1 语法制导的定义 语义规则的计算方法 分析树方法:刚才介绍的方法,动态确定计算次序,效率低。 概念上的一般方法 基于规则的方法:(编译器实现者)静态确定(编译器设计 者提供的)语义规则的计算次序。 适用于手工构造的方法 忽略规则的方法:(编译器实现者)事先确定属性的计算策 略(如边分析边计算),(编译器设计者提供的)语义规则必 须符合所选分析方法的限制。 适用于自动生成的方法
14
第4章 语法制导的翻译 4.2 S属性定义的自下而上计算 1学时
15
语法树是分析树的浓缩表示:算符和关键字是作为内部结点 语法制导定义可以基于分析树,也可以基于语法树 语法树的例子:
4.2 S属性定义的自下而上计算 4.2.1 语法树 语法树是分析树的浓缩表示:算符和关键字是作为内部结点 语法制导定义可以基于分析树,也可以基于语法树 语法树的例子: if B then S1 else S 2 if-then-else B S1 S2 + * 2 5 8
16
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)
17
例:a+5b的语法树的构造 E.nptr T.nptr F.nptr id + num num 5 指向符号表中a的入口
4.2 S属性定义的自下而上计算 例:a+5b的语法树的构造 E.nptr T.nptr F.nptr id + num num 5 指向符号表中a的入口 指向符号表中b的入口 + id 指向符号表中a的入口 num 5 id 指向符号表中b的入口
18
LR分析器的栈增加一个域来保存综合属性值
4.2 S属性定义的自下而上计算 4.2.3 S属性的自下而上计算 LR分析器的栈增加一个域来保存综合属性值 若产生式 AXYZ 的语义规则是 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 . . .
19
例:简单计算器的语法制导定义改成栈操作代码 产 生 式 语 义 规 则 代 码 段
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 [ top1] ) val [top 2 ] = val [top 2]+val [top] —— val [top 2 ] = val [top 2]val [top] val [top 2 ] = val [top 1] ——
20
例:下面是产生字母表Σ = {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
21
若按22+0+20+2-1+0+2-3来计算,对小数点左边部分的计 算不利:需要继承属性来确定每个B离开小数点的距离
4.2 S属性定义的自下而上计算 例题2 例:为下面文法写一个语法制导的定义,用S的综合属性val给 出下面文法中S产生的二进制数的值。例如,输入 时,S.val = 5.625(可以修改文法) S L . L | L L L B | B B 0 | 1 若按 来计算,对小数点左边部分的计 算不利:需要继承属性来确定每个B离开小数点的距离 若按(12+0)2+1计算,不能直接用于小数点右边,需改成 ((12+0)2+1)/23,这时需要综合属性来统计B的个数 S . L B
22
4.2 S属性定义的自下而上计算 例题2 例:为下面文法写一个语法制导的定义,用S的综合属性val给 出下面文法中S产生的二进制数的值。例如,输入 时,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
23
第4章 语法制导的翻译 4.3 L属性定义的自上而下计算 2学时
24
属性的计算次序一定受分析方法所限定的分析树结点建立次 序的限制 分析树的结点是自左向右生成
4.3 L属性定义的自上而下计算 边分析边翻译的方式能否用于继承属性? 属性的计算次序一定受分析方法所限定的分析树结点建立次 序的限制 分析树的结点是自左向右生成 如果属性信息是自左向右流动,那么就有可能在分析的同时 完成属性计算
25
如果每个产生式 AX1…Xj-1Xj…Xn 的每条语义规则计算的属 性是A的综合属性;或者是 Xj 的继承属性,但它仅依赖:
4.3 L属性定义的自上而下计算 4.3.1 L属性定义 如果每个产生式 AX1…Xj-1Xj…Xn 的每条语义规则计算的属 性是A的综合属性;或者是 Xj 的继承属性,但它仅依赖: 该产生式中Xj左边符号X1, X2, …, Xj-1的属性; A的继承属性 S属性定义属于L属性定义
26
例:变量类型声明的语法制导定义是一个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
27
例:把有加和减的中缀表达式翻译成后缀表达式 如果输入是8+5-2,则输出是8 5 + 2 - E T R
4.3 L属性定义的自上而下计算 4.3.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(-)}
28
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
29
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 }
30
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 T1F 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)
31
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 产生式部分不再给出
32
例 例:左递归的消除引起继承属性 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的入口
33
把预测分析器的构造方法推广到翻译方案的实现 产生式R +TR | ε 的分析过程 void R( ) {
4.3 L属性定义的自上而下计算 4.3.3 预测翻译器的设计 把预测分析器的构造方法推广到翻译方案的实现 产生式R +TR | ε 的分析过程 void R( ) { if (lookahead == '+' ) { match ( '+' ); T( ); R( ); } else / 什么也不做 /
34
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
35
例: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
36
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
37
第4章 语法制导的翻译 4.4 L属性定义的自下而上计算 2学时
38
在自下而上分析的框架中实现L属性定义的方法 归约时进行属性计算 它能实现任何基于LL(1)文法的L属性定义
也能实现许多(但不是所有的)基于LR(1) 的L属性定义
39
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 ('-')} 这些动作的一个重要特点: 没有引用原来产生式文法符号的属性
40
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 继承属性的计算可 以略去,引用继承属 性的地方改成引用其 他符号的综合属性
41
addType(val[top], val[top3])
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[top3]) addType(val[top], val[top1])
42
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}
43
增加标记非终结符,把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)}
44
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 }
45
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;
46
举例说明:在text归约成B时,B的ps属性都在次栈顶位置
4.4 L属性定义的自下而上计算 例 举例说明:在text归约成B时,B的ps属性都在次栈顶位置 S M s B L s text sub N s
47
例 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[top1] = val[top] val[top+1] = 10 val[top2] = max(val[top2], val[top]) val[top+1] = val[top1] val[top3] = disp (val[top3], val[top] ) val[top+1] = shrink(val[top2]) val[top] = val[top] val[top1]
48
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
49
例:给出把中缀表达式翻译成没有冗余括号的中缀表达式的 语法制导定义。例如,因为 + 和 是左结合,
4.4 L属性定义的自下而上计算 例题 例:给出把中缀表达式翻译成没有冗余括号的中缀表达式的 语法制导定义。例如,因为 + 和 是左结合, (( a ( b + c )) ( d ))可以重写成 a (b + c ) d 两种方法: 先把表达式的括号都去掉,然后在必要的地方再加括号 去掉表达式中的冗余括号,保留必要的括号
50
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;}
51
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;}
52
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;}
53
给E,T和F两个继承属性 left_op 和 right_op 分别表示左右 两侧算符的优先级
例题 第二种方法 给E,T和F两个继承属性 left_op 和 right_op 分别表示左右 两侧算符的优先级 给它们一个综合属性 self_op 表示自身主算符的优先级 再给一个综合属性 code 表示没有冗余括号的代码 分别用1和2表示加和乘的优先级,用3表示 id 和 (E) 的优先 级,用0表示左侧或右侧没有运算对象的情况
54
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;}
55
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;}
56
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 || ")";}
57
本章要点 注释分析树、语法树、综合属性、继承属性 语法制导定义和翻译方案的实现 S属性的自下而上计算(边分析边计算)
4 语法制导的翻译 本章要点 注释分析树、语法树、综合属性、继承属性 语法制导定义和翻译方案的实现 S属性的自下而上计算(边分析边计算) L属性的自上而下计算(边分析边计算) L属性的自下而上计算(边分析边计算) 构造语法树的语法制导定义 用栈代码实现属性计算
58
习题 注释分析树 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)
Similar presentations