View
19
Download
0
Category
Preview:
Citation preview
纵观全局
• 语言的规约1:词法单元的模式(串接结构,一维线性结构);
词法单元的模式 → 正则表达式 → DFA → 词法分析程序;
• 语言的规约2:上下文无关类的语法(嵌套结构:树形结构);
语法规则 → 上下文无关文法 → 推导 → 语法分析程序
源程序 语法分析树;
• 语法分析树是逐步建立的,有过程。能否在语法分析树的结点
上记录一些信息,并借助于它来做一些想做的事情,比如翻译
(把源程序翻译成中间代码)?
语法分析程序
对语法分析的观察分析
• 语法分析树是逐步建立的,体现在LL分析中,每展开一个非终
结符,在LR分析中,每规约一次。能否在语法分析树的结点上
记录一些信息,并借助于它来做一些想要的事情,比如翻译
(把源程序翻译成中间代码)?
• 自顶向下的语法分析:对词法流从左到右逐一扫描,来选择产
生式,形成一颗语法树;每选一次产生式,树就增大一次;
• 自底向上的语法分析:对词法流从左到右逐一扫描,来选择产
生式来规约,每规约一次,树就增大一次;
什么叫语法制导的翻译
求表达式的值id1 + id2 *id3 【4 + 3 * 5】
文法:EE + E | E * E | id
E5
id3
+E1 E4
*E2 E3
id2
id1
E1= id1E2= id2E3= id3E4= E2* E3E5= E1 + E4
对于计算器的计算结果:
对于计算机执行的指令流:
19四者的语义相同
上下文无关文法引导语言的翻译
上下文无关文法中的非终结符号代表了语言的某类结构;
l 程序设计语言的结构由更小的结构组合而成
l 一个结构的语义可以由小结构的含义综合而来;
比如:表达式x+y的类型由其x、y和运算符+决定。
l 可以由附近的结构继承而来
比如:对于变量声明:int x; x 的类型由它左边的类型决定。
观察与分析——自底向上语法分析的特性
id + id * id输入串:
EE + E E E * E E id
归约的过程就是树的形成过程,也是计算
的过程(即翻译的过程)。
* E3
+E1
id
E2
id
id * E3
+E1 E4
E2
①
② ③
④
⑤
E5
+E1 E4
⑤
观察与分析——自底向上的语法分析
id1 + id2 *id3:4+3*5 EE + E | E * E | id
E5
id3
+E1 E4
*E2 E3
id2
id1
E1.val=id1.val =4
E2.val=id2.val =3
E3.val=id3.val =5
E4.val=E2.val *E3.val=15
E5.val=E1.val *E4.val=19
①
②
③
⑤
④
归约的过程就是树的形成过程,也是计算的过程,也是翻译的过程。
归纳与总结——提升成知识和理论
id1 + id2 *id3:4+3*5 EE + E | E * E | id
E5
id3
+E1 E4
*E2 E3
id2
id1
E1.val=id1.val =4
E2.val=id2.val =3E3.val=id3.val =5
E4.val=E2.val *E3.val=15
E5.val=E1.val +E4.val=19①
②
③
⑤
④
产生式 语义规则
1)EE1 + E2 2)EE1 * E2 3)E id
E.val =E1.val +E2.valE.val =E1.val +E2.valE.val =id.val
语法制导定义(SDD):l 上下文无关文法;l 属性;l 规则;
进一步对知识和理论进行观察分析
E5
id3
+E1 E4
*E2 E3
id2
id1
E1.val=4
E2.val=3E3.val=5
E4.val=15
E5.val=19
①
②
③
⑤
④
产生式 语义规则
1)EE1 + E2 2)EE1 * E2 3)E id
E.val =E1.val +E2.valE.val =E1.val +E2.valE.val =id.val
语法制导定义(SDD):l 上下文无关文法;l 属性;l 规则;
实例
S属性的语法制导定义
定义
综合属性:(synthesized attribute)一个结点的属性值由它的子节点而来;
语法制导定义(SDD)
文法由产生式构成,语法制导定义中的定义是指:
• 定义文法的非终结符的属性;
• 产生式表达了非终结符的构成关系,一个产生式中的非终结
符的属性,它们彼此之间存在联系(即规则来刻画联系);
• SDD是上下文无关文法和属性/规则的结合;
– 属性和文法符号相关联
– 规则和产生式相关联;
观察与分析——自顶向下语法分析
T T *F | F F id
一个运算式( id1 * id2)由运算符*,和两个分量(id1 , id2)构成;
对于T' *FT1',它自然包含了一个运算式,做如下布局:左分
量在T'上, 右分量自然是F,运算符是*,结果放在T1'上。
T FT'T' *FT1' T' F id
id1 * id2* id3输入串:
T
F T'
F1* T'1
id2
id1④ ⑤
③
①
②
* T'2Fid3
⑥ ⑦
自顶向下语法分析的SDD观察分析
T T *F | F F id
T2’,意思是空运算,表示收尾了。
现在最终的结果在T2'上,要把它传回到根节点T上,于是,最右
的结点链T, T',T1', T2'都还要带有一个综合属性;
T FT'T' *FT1' T' F id
id1 * id2* id3输入串:
T
F T'
F1* T'1
id2
id1④ ⑤
③
①
②
* T'2Fid3
⑥ ⑦
自顶向下语法分析的SDD例子
id1 * id2* id3输入串:
T
F T'
F1* T'1
id2
id1④ ⑤
③
①
②
* F3
id3
T'2⑥ ⑦
synval
val
val
syn
syn
inh
inh
inh
val
val val
val
文法的非终结符的属性定义
自顶向下语法分析的SDD
语法分析树中结点的属性的值的求解过程。
id1 * id2* id3输入串:
T
F T'
F1* T'1
id2
id1
④
⑤
③
①
②
* F3
id3
T'2⑥
⑦
valval
val
val
val
val
inh
inh
inh
val
val val
val
⑩
⑨
⑧
自顶向下语法分析的SDD例子:4*2*3T
F T'
F1* T'1
id2
id1
④
⑤
③
①
②
* F3
id3
T'2⑥
⑦
synval
val
val
syn
syn
inh
inh
inh
val
val val
val
⑩
⑨
⑧
产生式 语义规则1)TFT' 2)T'*FT1' 3)T'4)Fid
T'.inh = F.val, T.val = T'.synT1'.inh = T'.inh * F.val, T’.syn= T1’.synT’.syn= T’.inhF.val =id.val
文法的非终结符的继承属性T
F T'
F1* T'1
id2
id1
④
⑤
③
①
②
* F3
id3
T'2⑥
⑦
synval
val
val
syn
syn
inh
inh
inh
val
val val
val
⑩
⑨
⑧
产生式 语义规则
2)T'*FT1' T1'.inh = T'.inh * F.val, T’.syn= T1’.syn
文法:非终结符T’的属性inh的值由T’的父结点,T’的兄弟,以及自己,这三者的属性值来计算确定 继承属性。
注释语法分析树(annotated parse tree)
T
F T'
F1* T'1
id2
id1
* F3
id3
T'2
syn=24val=4
val=4
val=24
syn=24
syn=24
inh=4
inh=8
inh=24val=2
val=2 val=3
val=3
显示出了各结点的属性的值的语法分析树
依赖图——SDD的求值顺序
T
F T'
F1* T'1
id2
id1
* F3
id3
T'2
synval
val
val
syn
syn
inh
inh
inh
val
val val
val
依赖图:语法分析树中的各结点的属性的求值顺序
依赖图的拓扑排序:id1,F,T'.inh, id2, F1, T1'.inh, ......
SDD: 文法和 目标(此例为表达式求值)
SDD
产生式 语义规则
1)SE
2)EE1 + T
3)ET
4)TT1 * F
5)TF
6)F (E)
7)F id
S.val =E.val
E.val =E1.val+T.val
E.val =T.val
T.val =T1.val*F.val
T.val =F.val
F.val =E.val
F.val =id.val
LR分析,规约时发生;只有S属性, 直观,简洁
为了LL分析,对文法消左递归
E→ E1 + T E→ T T→ T1 * F T→ F F→ (E) F→ id
E→ TE'E' → +TE' E' → εT→ FT'T'→ * F T'T'→ εF→ (E)F→ id
消左递归
引入了两个非终结符E', T'
消左递归后, 文法的SDD
产生式 语义规则
1)ETE' 2)E‘+TE1'3)E'4)TFT' 5)T'*FT1' 6)T'7)F(E)8)Fid
E'.inh = T.val, E.val = E'.synE1'.inh = E'.inh +T.val, E’.syn= E1’.synE’.syn= E’.inhT'.inh = F.val, T.val = T'.synT1'.inh = T'.inh * F.val, T’.syn= T1’.synT’.syn= T’.inhF.val =E.valF.val =id.val
E', T'是为消左递归而引入的, 既有综合属性,也有继承属性;
E,T,F,是原有的非终结符,只有综合属性
概念S属性的SDD:每个属性都是综合属性;
L属性的SDD:其属性是:综合属性,或者是继承属性的
子集:由父结点,左兄弟结点,自己的属性来确定。
产生式 语义规则
1)EE1 + E2 2)EE1 * E2 3)E id
E.val =E1.val +E2.valE.val =E1.val +E2.valE.val =id.val
产生式 语义规则
1)TFT' 2)T'*FT1' 3)T'4)Fid
T'.inh = F.val, T.val = T'.synT1'.inh = T'.inh * F.val, T’.syn= T1’.synT’.syn= T’.inhF.val =id.val
SDD的应用1——实现一个计算器
产生式 语义规则0)SE1)EE1 + E2 2)EE1 * E2 3)E id
{ print(E.val) }E.val =E1.val +E2.valE.val =E1.val +E2.valE.val =id.val
产生式 语义规则0)ST1)TFT' 2)T'*FT1' 3)T'4)Fid
{ print (T.val) }T'.inh = F.val, T.val = T'.synT1'.inh = T'.inh * F.val,T’.syn= T1’.synT’.syn= T’.inhF.val =id.val
应用2——生成抽象语法树的SDD
抽象语法树的构造
产生式 语义规则
1)E→ E1 + T 2)ET 3)TT1 * F4)TF5)F→ (E)6)F→id
E.node = new Node('+', E1.node, T.node)E.node =T.nodeE.node = new Node('*', T1.node, F.node)T.node = F.nodeF.node = E.nodeF.node = new Leaf(id, id.entry)
我们走到哪儿了?
给定上下文无关文法G,在第四章,解决了的问题:
lG是不是LL(1)文法, 是不是LR(1)文法的问题;
l文法 LL文法的预测分析表,LR文法的语法分析表 语法分
析器源程序生成工具;
语义分析,中间代码的生成,不是独立的环节,而是在语法分析
的过程中(LL分析中的展开,LR分析中的规约,)附带完成;
第五章, 在文法的产生式上加上动作,构造SDT。有了SDT,语
法分析,语义分析,中间代码生成,这三个工作的源程序就可由
语法分析器生成工具来自动得到;
复习
Syntax Directed Definition (SDD):文法 + 目标 属性,规
则
S属性:对于一个产生式,头部非终结符的属性值,由产生式体中
的符号的属性值决定,体现在规则上;
Syntax Directed Transaction Scheme (SDT):以LL(1)分析,
或LR(1)分析,基于栈的实现机制,通过设置动作来完成目标;
l S属性,继承属性,L属性;
l 注释语法分析树,抽象语法分析树;
① EE+E
② EE*E
③ E(E)
④ Eid
I0E'→EE→ E + E E→ E*EE→ (E) E→ id
I3E→ id
I1E'→EE→ E + EE→ E*E
I4E→ E + E E→ E + E E→ E*EE→ (E) E→ id
I7E→ E + E E→ E + EE→ E*E
I5E→ E*E E→ E + E E→ E*EE→ (E) E→ id
I8E→ E * E E→ E + EE→ E*E
E + E
* E
I2F→ (E) E→ E + E E→ E*EE→ (E) E→ id
I6F→ (E )E→ E + EE→ E*E I9
E→ (E)
id
id
(
(
(
id
id
*
E
)(
$Accept
+
*
+
*
+
LR分析中基于栈的SDT实现,以为表达式求值这个目标为例
ACTION:移入, 归约
规约时做翻译;
① EE+E ② EE*E ③ E(E) ④ Eid
LLR分析中基于栈的SDT实现,以id+id*id为例 (4+3*5)
E1.s=4E1id E1
+
id
E1
+E2
E1
+E2
*
id
E1
+E2
*
E3
E1
+E4
E5
翻译目标为求值
E2.s=3 E3.s=5E4.s=15
E5.s=19
① EE+E ② EE*E ③ E(E) ④ Eid
LR分析中基于栈的SDT实现:目标为生成中间代码,以id+id*id为例 (4+3*5)
t1=id1
E1id E1
+
id
E1
+E2
E1
+E2
*
id
E1
+E2
*
E3
E1
+E4
E5
翻译目标为生成中间代码
t2=id2 t3=id3t4=t2*t3
t5=t1+t4
本质:通
过栈缓存
来实现了
顺序调转
LR分析中文法的SDD
目标:求表达式的值。规约时,做翻译
产生式 语义规则
1)E→ E1 + E2 3)EE1 * E2
5)E→ (E1)6)E→id
E.val = E1.val+ E2.valE.val = E1.val * E2.valE.val = E1.valE.val = id.val
LR分析中的SDT
求表达式的值的SDT,规约时,执行动作,而且是先翻译,后规约
语义动作
1)E→ E1 + E2 { E.val = E1.val+ E2.val }2)EE1 * E2 { E.val = E1.val * E2.val }3))E→ (E1) {E.val = E1.val }4)E→id { E.val = id.val }
就LR文法, 由SDD到SDT非常简单、直观
SDD
产生式 语义规则
1)SE
2)EE1 + T
3)ET
4)TT1 * F
5)TF
6)F (E)
7)F id
S.val =E.val
E.val =E1.val+T.val
E.val =T.val
T.val =T1.val*F.val
T.val =F.val
F.val =E.val
F.val =id.val
语义动作
1)SE { print E.val }2)EE1 + T { E.val =E1.val+T.val }3)ET { E.val =T.val }4)TT1 * F { T.val =T1.val*F.val }5)TF { T.val =F.val }6)F (E) { F.val =E.val }7)F id { F.val =id.val }
后缀SDT
LR分析,规约时发生;只有S属性, 直观,简洁
为了LL分析,对文法消左递归
E→ E1 + T E→ T T→ T1 * F T→ F F→ (E) F→ id
E→ TE'E' → +TE' E' → εT→ FT'T'→ * F T'T'→ εF→ (E)F→ id
消左递归
引入了两个非终结符E', T'
消左递归后, 文法的SDD
产生式 语义规则
1)ETE' 2)E‘+TE1'3)E'4)TFT' 5)T'*FT1' 6)T'7)F(E)8)Fid
E'.inh = T.val, E.val = E'.synE1'.inh = E'.inh +T.val, E’.syn= E1’.synE’.syn= E’.inhT'.inh = F.val, T.val = T'.synT1'.inh = T'.inh * F.val, T’.syn= T1’.synT’.syn= T’.inhF.val =E.valF.val =id.val
E', T'是为消左递归而引入的, 既有综合属性,也有继承属性;
E,T,F,是原有的非终结符,只有综合属性
消左递归后,文法的SDT
E→ T { E'.inh = T.val } E' { E.val = E'.syn}E' → +T { E1'.inh = E'.inh + T.val } E' {E’.syn= E1’.syn}
E' → ε {E’.syn= E’.inh}
T→ F { T'.inh = F.val } T' { T.val = T'.syn}
T'→ * F{ T1'.inh = T'.inh * F.val } T1' {T’.syn= T1’.syn}
T'→ ε {T’.syn= T’.inh }
F→ (E) {F.val= E.val}
F→ id { F.val= E.val }
这个SDT是基于LL分析,而构思出来的。怎么构思?看下文分解
LL语法分析实现翻译的过程同一案例id+id*id(4+3*5)
E
id
+
T E'
*
T1
F2
F T'
id ε F1 T1'
id
E1'
ε
T2'
ε
每棵树(子树)的
最右边的结点链
路是综合之路。
即处理累积到最
右的叶节点。
从左到右:先继
承,后综合
③
①
②④
⑤
⑥
⑦
⑧
⑨
⑩ 12
13
1415
16
17
18
11
观察:LL语法分析实现翻译的特点
E
id
+
T E'
*
T1
F2
F T'
id ε F1 T1'
id
E1'
ε
T2'
ε
E', T'是为消左递归而
引入的两个非终结符,
既有综合属性,也有
继承属性;
E,T,F,是原有的非终
结符,只有综合属性
③
①
②④
⑤
⑥
⑦
⑧
⑨
⑩ 12
13
1415
16
17
18
11
LL分析中基于栈的SDT实现:将SDT倒着入栈。同一案例id+id*id(4+3*5
E.synE
E→ T { E'.inh = T.val } E' { E.val = E'.syn}
E.syn { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}
TT.val
展开
T'id ε
E
TF
id* F
F
id
+ T1
E'
T1'E1'ε
T2'ε
按照SDT倒着入栈
T→ F { T'.inh = F.val } T' { T.val = T'.syn}
展开展开时,综合属性保留
id ε
E
T E'F T'
T
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
{ T.val = T'.syn}
T'和T'.inhT'.syn
{ T'.inh = F.val}
FF.val
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
F→ id {F.val= E.val}
展开
id ε
E
T E'F T'
{ T.val = T'.syn}
T'和T'.inhT'.syn
{ T'.inh = F.val}
FF.val
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
{ F.val = id.val}id.val
{ T.val = T'.syn}
T'和T'.inhT'.syn
{ T'.inh = F.val}F.val
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
弹栈
观察:
栈顶不为非终结符时:
1)匹配输入串;
2)执行栈顶的操作;
3)弹栈;
直到栈顶为非终结符
{ F.val = id.val}id.val=4
{ T.val = T'.syn}
T'和T'.inhT'.syn
{ T'.inh = F.val}F.val
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
{ T.val = T'.syn}
T'和T'.inhT'.syn
{ T'.inh = F.val}F.val = 4
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
继续弹栈
观察:
栈顶不为非终结符时:
1)匹配输入串;
2)执行栈顶的操作;
3)弹栈;
直到栈顶为为非终结符
{ T.val = T'.syn}
T'和T'.inhT'.syn
{ T'.inh = F.val}F.val= 4
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
{ T.val = T'.syn}
T'和T'.inh= 4T'.syn
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
观察
观察:
栈顶为非终结符
须展开:T'→ ε { T.val = T'.syn}
T'和T'.inh= 4T'.syn
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
展开
{ T’.syn = T'.inh}
展开
id ε
E
T E'F T'
{ T.val = T'.syn}
T'和T'.inh= 4T'.syn
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
{ T.val = T'.syn}T'.syn
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
T'.inh
弹栈
{ T’.syn = T'.inh}
{ T.val = T'.syn}T'.syn
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
T'.inh=4
{ T.val = T'.syn}T'.syn = 4
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
观察:
栈顶不为非终结符,
执行栈顶的操作;
然后弹栈;
直到栈顶为为非终结
符
继续弹栈(1)
{ T.val = T'.syn}T'.syn = 4
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val
E.val { E.val = E'.syn}
E’ 和 E'.inhE'.syn
{E'.inh = T.val}T.val = 4
观察:
栈顶不为非终结符,
执行栈顶的操作;
然后弹栈;
直到栈顶为为非终结
符
继续弹栈(2)
E.val { E.val = E'.syn}
E’ 和E’.inhE'.syn
{E'.inh = T.val}T.val = 4
E.val { E.val = E'.syn}
E’ 和E’.inh = 4E'.syn
观察:
弹栈之后,现在栈顶
为非终结符,因此接
下来是展开操作
id ε
E
T E'F T'
展开
E' → +T { E1'.inh = E'.inh + T.val } E1' {E’.syn= E1’.syn}
有问题!!!
当在后面执行该操作时,E'.inh在栈中已经不存在了
+ T
EE'
E1'
E.val { E.val = E'.syn}
E1’和E1’.inh
E'.syn {E’.syn= E1’.syn}
E1'.syn
T
{E1'.inh = E'.inh + T.val}T.val
展开
E.val { E.val = E'.syn}
E’ 和E’.inh = 4E'.syn
+
E' → +T { E1'.inh = E'.inh + T.val } E1' {E'.syn= E1'.syn} 在操作上存在问题
弹栈展开
E.val { E.val = E'.syn}
E1’和E1’.inh
E'.syn {E’.syn= E1’.syn}
E1'.syn
T
{E1'.inh = E'.inh + T.val}T.val
E.val { E.val = E'.syn}
E1’和E1’.inh
E'.syn {E’.syn= E1’.syn}
E1'.syn
{E1'.inh = E'.inh + T.val}T.val
E.val { E.val = E'.syn}
E1’和E1’.inh
E'.syn {E’.syn= E1’.syn}
E1'.syn
{E1'.inh = E'.inh + T.val}T.val = 15
E' → +T { E1'.inh = E'.inh + T.val } E1' {E'.syn= E1'.syn} 应修改为
E' → { E1'.inh= E'.inh } +T { E1'.inh = E1'.inh + T.val } E1' {E’.syn= E1’.syn}
E.val { E.val = E'.syn}
E1’和E1’.inh
E'.syn {E’.syn= E1’.syn}
E1'.syn
T
{E1'.inh = E1'.inh + T.val}
T.val
展开
E.val { E.val = E'.syn}
E’ 和E’.inh = 4E'.syn
+{E1'.inh= E'.inh }
弹栈,然后匹配
E.val { E.val = E'.syn}
E1’和E1’.inh
E'.syn {E’.syn= E1’.syn}
E1'.syn
T
{E1'.inh = E1'.inh + T.val}
T.val
+{E1'.inh= E'.inh }
E.val { E.val = E'.syn}
E1’和E1’.inh = 4
E'.syn {E’.syn= E1’.syn}
E1'.syn
T
{E1'.inh = E1'.inh + T.val}
T.val
+
E.val { E.val = E'.syn}
E1’和E1’.inh = 4
E'.syn {E’.syn= E1’.syn}
E1'.syn
T
{E1'.inh = E1'.inh + T.val}
T.val
总结——基于LL分析的SDT动作特点
E' → { E1'.inh= E'.inh } +T { E1'.inh = E1'.inh + T.val } E1' {E’.syn= E1’.syn}
只能使用A的继承属性,修改左边的X,Y,Z的继承属性值
A →{ } X{ }Y{ }Z{ }
只能使用X的综合属性,修改左边的Y,Z的继承属性值
只能使用Y的综合属性,修改左边的Z的继承属性值
只能使用Z的综合属性,修改A的综合属性值
栈顶为非终结符,要展开
弹栈展开
E.val { E.val = E'.syn}
E1’和E1’.inh
E'.syn {E’.syn= E1’.syn}
E1'.syn
T
{E1'.inh = E'.inh + T.val}
T.val
E.val { E.val = E'.syn}
E1’和E1’.inh = 4
E'.syn {E’.syn= E1’.syn}
E1'.syn
{E1'.inh = E'.inh + T.val}T.val
E.val { E.val = E'.syn}
E1’和E1’.inh = 4
E'.syn {E’.syn= E1’.syn}
E1'.syn
{E1'.inh = E'.inh + T.val}T.val = 15
弹栈
弹栈
E.val { E.val = E'.syn}
E1’和E1’.inh = 4
E'.syn {E’.syn= E1’.syn}
E1'.syn
{E1'.inh = E'.inh + T.val}T.val = 15
E.val { E.val = E'.syn}
E1’和E1’.inh =19
E'.syn {E’.syn= E1’.syn}
E1'.syn
id* F
F
id
+ TE'
T'E1'ε
T'ε
栈顶为非终结符,要展开
E.val { E.val = E'.syn}
E1’和E1’.inh =19
E'.syn {E’.syn= E1’.syn}
E1'.syn
id* F
F
id
+ TE'
T'E1'ε
T'ε
E.val { E.val = E'.syn}
E'.syn {E’.syn= E1’.syn}
E1'.syn
{E1’.syn= E1’.inh}
E1'.inh = 19
栈顶不为非终结符,弹栈
E.val { E.val = E'.syn}
E'.syn {E’.syn= E1’.syn}
E1'.syn = 19
E.val { E.val = E'.syn}
E'.syn = 19
+ T
EE'
E1'
目标不同,SDD不同:LR分析中的SDT
求中间代码时的SDT,规约时,做翻译。而且是先翻译,后规约
语义动作
1) E→ E1 + E2 { E.addr = new temp(); genCode( E.addr '=' E1.addr '+' E2.addr ); }2) EE1 * E2 { E.addr = new temp(); genCode( E.addr '=' E1.addr '*' E2.addr); }3) E→ (E1) {E.addr = E1.addr }4) E→id { E.addr = new temp(); genCode( E.addr '=' id.addr; }
总结
l SDD是对文法,针对特定目标而来的。不同的目标,定义的
属性不同,规则也不同;
l 属性是指对着非终结符来的,规则是对着产生式来的;
l 文法,它可能不是LL的,因此就谈不上用LL分析来实现;
l 同理,文法可能不是LR的,因此就谈不上用LR分析来实现;
l 确定了SDD,然后就是用LL分析还是LR分析?SDT是一种
实施操作方案;
课程特点
课堂,仅只是取一个例子来点开视野,阐释特征、特点,策略
试验呢,则能见到整体,全貌。组合概念,课堂中没有提。
例如词法分析:keyword, variable, number, 数值/逻辑运算符,标点符号等等合到一起,构成一个综合完整的DFA。
语法分析也一样,课堂只是以表达式为例来阐释状态穷举。试验则要考虑语句,如赋值语句,申明语句,控制语句等,还有逻辑表达式,这些组合到一起形成一个很大的DFA。
试验一定要套知识点,套原则,如果没结合上,就等于0。
产生式 语义规则TBC
Bint BfloatC[num]C1
C
C.inh_t = B.t C.inh_w = B.wT.t = C.t, T.w = C.wB.t = integer, B.w=4B.t = float, B.w=8C1.inh_t = C.inh_tC1.inh_w = C.inh_wC.t = array(num, C1.t)C.t= C.inh_tC.w =C.inh_w
t
T
B C
C1int
inh
C2
[ 2 ]
[ 3 ]
syn
syninh
inh
syn
syn
下列文法不是LR的,因此就谈不上LR分析来实现, 只能是LL分析来实现
例, int [2][3] 类型表达式为 array(2, array(3,integer)
LL分析中,SDD可行,但是在实施操作中遇到了问题
产生式 语义规则
TBC
Bint Bfloat
C[num]C1
C
C.inh_t = B.t C.inh_w = B.wT.t = C.t, T.w = C.w
B.t = integer, B.w = 4B.t = float, B.w = 8
C1.inh_t = C.inh_tC1.inh_w = C.inh_wC.t = array(num, C1.t)
C.t = C.inh_tC.w =C.inh_w
问题:2在求C的综合属性t时用到,但此时已经不在栈里了
t
T
B C
C1int
inh
C2
[ 2 ]
[ 3 ]
syn
syninh
inh
syn
syn
对LL分析中遇到的上述问题,其解决办法
对于C[num]C1,中的num,其特点:只有规约(即求C的综合属性)时用到,并不须要下传。 处理办法是最右端加一个非终结符S,它只有继承属性,其产生式为S,无动作。
1)TBC2)Bint 3)Bfloat4)C[num]C1
5)C
1)TBC2)Bint3)Bfloat4)C[num]C1S5)C S
对LL分析中遇到的问题的解决办法——在产生式中新加一个非终结符
1)TB{C.inh_t = B.t; C.inh_w = B.w;} C { T.t = C.t; T.w = C.w; }
2)Bint {B.t= integer; B.w = 4; }
3)Bfloat {B.t= float; B.w = 8; }
4)C{ C1.inh_t = C.inh_t; C1.inh_w = C.inh_w; } [num {S.inh= num; } ] C1 { C.t = array(S.inh, C1.t); C.w =S.inh* C1.w } S
5) C {C.t = C.inh_t; C.w = C.inh_w; } 6)S
当S变成栈顶时,要弹出它,然后用它的产生式的右部倒着压入栈
中,现在S,而且这个产生式中没有动作。即S直接出栈。
同一内容,其LL文法与LR文法是不一样的
例如,int [2][3] 的类型表达式为array(2, array(3,integer))
1)TBC 2)Bint 3)Bfloat 4)C C1[num]5)C [num]
1)TBC2)Bint 3)Bfloat4)C[num]C1
5)C
LL文法 LR文法
注意:LR文法中,允许左递归,不允许出现C 之类的产生式; LL文法中,不允许左递归,允许C
LR分析中的语法分析树
例如,int [2][3] 的类型表达式为array(2, array(3,integer))
T
B
int C
[ 2 ]
C
[ 3 ]
1)TBC 2)Bint 3)Bfloat 4)C C1[num]5)C [num]
观察:LR分析中,在规约出C时,B在栈中
LR文法
在LR分析中的 SDT
例如,int [2][3] 的类型表达式为array(2, array(3,integer))
1) TBC { T.t = B.t; T.w = B.w; while(int i=C.Stack ->pop() ) { B.t = array(i, B.t); T.w = T.w* i; } delete C.Stack; AddType(id, T.t, T.w); }2) Bint { B.t = integer; B.w = 4 } 3) Bfloat { B.t = float; B.w = 8 } 4) C C1[num] { C.Stack = C1.Stack; C.Stack ->push(num); }5) C [num] { C.Stack = new stack(); C.Stack ->push(num); }
在LR分析中的 SDT
例如,int [2][3] 的类型表达式为array(2, array(3,integer))
1) TBC { T.t= B.t; T.w= B.w; while(int i=s.pop()) { B.t = array(num, B.t); T.w=T.w* i; } delete s; AddType(id, T.t, T.w); } }
2) Bint { B.t = integer; B.w = 4 }
3) Bfloat { B.t = float; B.w = 8 }
4) C C1[num] { s.push(num); }
5) C [num] { s = new stack(); s.push(num); }
s是一个全局变量,该方案可行吗?
LL分析中,展开/弹栈/执行代码/匹配的具体实现
C{ C1.inh_t = C.inh_t; C1.inh_w = C.inh_w; } [num {S.inh= num; } ] C1 { C.t = array(S.inh, C1.t); C.w =S.inh* C1.w } S
当前输入符为a;
C.syn
{ C1.inh_t = C.inh_t; C1.inh_w = C.inh_w;}
S和S.inh = 4
]
{C.t = array(S.inh, C1.t); C.w =S.inh* C1.w}
C1.syn
{S.inh= num;}
num.val
C1和C1.inh
[
栈中元素的数据结构——分为四个类别
class node { int type ; int id; void * content);
type: 代码;非终结符和继承属性;非终结符的综合属性; 终结符
每段代码有标识符id;
非终结符也有标识符id;
终结符也有标识符id; C.syn
{ C1.inh_t = C.inh_t; C1.inh_w = C.inh_w;}
S和S.inh = 4
]
{C.t = array(S.inh, C1.t); C.w =S.inh* C1.w}
C1.syn
{S.inh= num;}
num.val
C1和C1.inh
[
栈顶元素为代码结点的处理——执行
switch (cur_element. type) { case 'CODE': switch(cur_element. id) { case 20: break;
例:{'C', 20, null}
elment[pos -5].inh.t = node.inh.t;elment[pos -5].inh.w = node.inh.w;pop( );
C.syn
{ C1.inh_t = C.inh_t; C1.inh_w = C.inh_w;}
S和S.inh = 4
]
{C.t = array(S.inh, C1.t); C.w =S.inh* C1.w}
C1.syn
{S.inh= num;}
num.val
C1和C1.inh
[
栈顶元素为非终结符的处理——展开
switch (cur_element. type) { case 'EXTEND': switch(cur_element. id) { case 'C': cur_node = pop(); if (a==$) 按 C 展开 else 按 C[num] C展开; break;
C.syn S和S.inh = 4
{C.t = array(S.inh, C1.t); C.w =S.inh* C1.w}
C1.syn C1和C1.inh
push(new node(‘CODE’, code_id ));push(new node(’EXT', 'C', cur_node));push(new node('CSYM', ']' ));push(new node(‘CODE’, 21));push(new node('CSYM', 'num' )); ......
栈顶元素为非终结符综合属性的处理——下沉,至代码元素或非终结符元素
switch (cur_element. type) { case ' SYN' : while (cur_element. type == 'SYN') cur_element = cur_element. next; break;
C.syn S和S.inh = 4
{C.t = array(S.inh, C1.t); C.w =S.inh* C1.w}
C1.syn
elment[pos -2].syn.t = array(elment[pos -1].inh, elment[pos +1].syn.t); elment[pos -2].syn.w = elment[pos -1].inh * elment[pos +1].syn.w);pop( ); pop();
栈顶元素为终结符的处理——匹配,或对其综合属性赋值
switch (cur_element. type) { case 'CONST_SYMBOL':
if (cur_element.id = 'ID' ) cur_element. addr = position(a);else if (cur_element.id = 'NUM' ) cur_element. val = a;else if(a != cur_element.symbol ) 报错pop( );
C.syn S和S.inh = 4
]
{C.t = array(S.inh, C1.t); C.w =S.inh* C1.w}
C1.syn
{S.inh= num;}
num.val
C1和C1.inh
[
语法制导翻译方案SDT
语法制导翻译方案(Syntax directed traslation Scheme)是
在上下文无关文法的产生式体中嵌入程序片断(语义动作),
表达联系的发生时刻;它与分析方法(LL,LR)相关联;
SDT的最直观实现方法:
建立语法分析树;
从左到右、深度优先地执行这些动作;
可用SDT来实现SDD:
基本文法是LR的,SDD是S属性的
基本文法是LL的,SDD是L属性的
LR分析中的SDT例子
SDD
产生式 语义规则
1)SE
2)EE1 + T
3)ET
4)TT1 * F
5)TF
6)F (E)
7)F id
S.val =E.val
E.val =E1.val+T.val
E.val =T.val
T.val =T1.val*F.val
T.val =F.val
F.val =E.val
F.val =id.val
语义动作
1)SE { print E.val }2)EE1 + T { E.val =E1.val+T.val }3)ET { E.val =T.val }4)TT1 * F { T.val =T1.val*F.val }5)TF { T.val =F.val }6)F (E) { F.val =E.val }7)F id { F.val =id.val }
后缀SDT
LR分析,规约时发生;只有S属性, 直观,简洁
LR分析中的SDT实例——实现计算器
发现:实现S属性的SDD
语义动作在每次规约时执行。并不须要先建立语法树,再执行
scheme。
E
id3
+E1 T1
id1 + id2 *id3
*T2 F2
F1
id2
T
F
id1
语义动作
1)SE { print E.val }2)EE1 + T { E.val =E1.val+T.val }3)ET { E.val =T.val }4)TT1 * F { T.val =T1.val*F.val }5)TF { T.val =F.val }6)F (E) { F.val =E.val }7)F id { F.val =id.val }
语法分析树
SDT中的语义动作在产生式中的位置
产生式 语义规则1)TFT' 2)T'*FT1' 3)T'4)Fid
T'.inh = F.val, T.val = T'.synT1'.inh = T'.inh * F.val,T’.syn= T1’.synT’.syn= T’.inhF.val =id.val
SDT:还表达了执行的时期
SDD:仅只表达了逻辑关系
1)TF { T'.inh = T.val } T' { T.val = T'.syn}2)T'*F { T1'.inh = T'.inh * F.val } T1' {T’.syn= T1’.syn}3)T' { T’.syn= T’.inh }4)Fid { F.val =id.val }
在LL分析中,进栈和弹栈规则 继承属性的值传递动作可能要做位置调整
1)TF { T'.inh = T.val } T' { T.val = T'.syn}2)T'*F { T1'.inh = T'.inh * F.val } T1' {T’.syn= T1’.syn}3)T' { T’.syn= T’.inh }4)Fid { F.val =id.val }
2)T'{ T1'.inh = T'.inh} * F { T1'.inh = T1'.inh * F.val } T1' {T’.syn= T1’.syn}
SDT中的语义动作在产生式中的位置
• 对于产生式:BX{a}Y
• LR分析时,a在X出现在栈顶时执行
• LL分析时,在试图展开Y或者在输入中检测到Y时执行a
不是所有的SDT都可以在分析过程中实现
例如,E { print('+') } E1 + T,
E T
在LR分析中,就不行。因为在起始时刻,E1 都还未规约出来,
E1后面的'+'就更不知道是否存在;
消左递归时S属性在SDT中的处理
对 EE | β消左递归:
E βE'
E' E' |
例如:对EE + T | T,消左递归:
ETE' E' +TE' |
语义动作
EE1 + T { E.val =E1.val + T.val }ET { E.val =T.val }
语义动作1)ET { E'.inh = T.val } E' { E.val = E'.syn}2)E'+T { E1'.inh = E'.inh + T.val } E1' {E’.syn= E1’.syn}3)E' {E’.syn= E’.inh}
消左递归时S属性SDT的处理
E
+E1 T1
T
E
T E'
T1+ E'1
④
⑤
③
①
②
synval
val
syn
inh
inhval
1)ET { E'.inh = T.val } E' { E.val = E'.syn}2)E'+T { E1'.inh = E'.inh + T.val } E1' {E’.syn= E1’.syn}3)E' {E’.syn= E’.inh}
EE1 + T { E.val =E1.val + T.val }ET { E.val =T.val }
含左递归,适合LR分析
消除左递归,适合LL分析
消左递归时S属性在SDT处理中的通用化
A
A1 Y
X
A
X R
Y R1
④
⑤
③
①
②
ss
a
s
i
i
A X { R.i = f(X.s) } R {A.a = R.s}R Y { R1.i = g(R.i, Y.s) } R1 { R.s = R1.s }R ε { R.s = R.i }
AA1Y { A.a = g(A1.a, Y.s) }AX { A.a = f(X.s) }
含左递归,适合LR分析
消除左递归,适合LL分析
s
消左递归时SDT的转换(2)
• 如果动作不涉及属性值,则将动作当作是终结符进行处理
例如,原始的产生式
– E E1+T { print(‘+’) }
– E T
• 转换后得到:
– E T E'
– E' + T {print (‘+’)} E'
– E' ε
SDT在语法分析过程中的实现
• 两类SDT:实现S属性的SDD(后缀SDT),实现L属性的SDD;
• 两类语法分析:LR分析, LL分析;
S属性的SDD LL分析
L属性的SDD LR分析
L属性包含了S属性,因此只要解决L属性,即解决了所有。
SDT中的消左递归的例子
E→ E1 + T
E→ T
T→ T1 * F
T→ F
F→ (E)
F→ id
E→ TE'E' → +TE'
E' → ε
T→ FT'
T'→ * F T'
T'→ ε
F→ (E)
F→ id
消左递归
增加了两个非终结符E',T'
消左递归后SDT的变化
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→ id { F.val =id.val }
E→ T { E'.inh = T.val } E' { E.val = E'.syn}E' → +T { E1'.inh = E'.inh + T.val } E' {E’.syn= E1’.syn}E' → ε {E’.syn= E’.inh}T→ F { T'.inh = F.val } T' { T.val = T'.syn}T'→ * F{ T1'.inh = T'.inh * F.val } T1' {T’.syn= T1’.syn}T'→ ε {T’.syn= T’.inh}F→ (E) {F.val= E.val}F→ id {F.val= E.val}
两种语法分析的过程对比
E
id
+T E'
*
T
F
F T'
id ε F T'
id
E1'ε
T'ε
自顶向下分析(LL分析)
语法分析树(8次规约)
E
id
+E T
id1 + id2 *id3
*T F
F
id
T
F
id
自底向上分析(LR分析)语法分析树(11次展开)
在语法分析的过程中,完成语义分析和中间代码生成两项工作
三地址中间代码表:
row_id tag code goto src_row_id1 L1: i = j + k
2
3
nextInstr
语法分析中通过栈缓存来实现了顺序调换,使得中间代码的生成具
有只增不插的特点。
LL分析中实现控制语句翻译的框架——例1
产生式:S while(B) S1
B
S1
L1
L2
S.nextL1: if ( B ) goto L2 goto B.falseL2: S1.code goto L1
S.next:
S.code=L1 : || B.code || L2: ||S1.code || goto L1 || S.next:
继承属性:S.nextB.false=S.next;B.true = newLabel();
综合属性:S.code;B.code;
LL分析中实现控制语句翻译的SDT——例1
产生式:S while (B) S1
while ( { begin = newLabel(); B.true=
newLabel(); B.false = S.next;S1.next= begin; Y. label = B.true; Z.Label= begin;
AddLabel( begin ':'); } B )
{AddLabel( Y.Label ':'); } Y S1 { gen(' goto' Z.Label); } ZY ; Z
产生式:S while ( B ) Y S1 Z
c=20L0: if (c>10) goto L1
goto L2
L1: c=c-1 goto L0
L2: x=1
LL分析中实现控制语句翻译的SDT——例2
产生式:S if (B) S1 else S2
S.code=B.code ||L1: || S1.code || goto S.next|| L2: || S2.code|| S.next:
B
S1L1
L2
S.nextS2
if ( B ) goto L1 goto L2
L1: S1.code goto S.nextL2: S2.codeS.next:
继承属性:S.nextB.false=newLabel();B.true =newLabel();
综合属性:S.code;B.code;
程序例子2
c=20;if (a>b)
d=x+y;else
d=x*y x=1
c=20 if(a>b) goto L3
goto L4
L3: d=x+y goto L5
L4: d=x*yL5: x=1
LL分析中实现控制语句翻译的SDT——例2
产生式:S if (B) S1 else S2
if ( { B.true= newLabel(); B.false =
newLabel();S1.next= S.next; S2.next= S.next; Y. label = B.true; Z.Label= B.false;
Z.nextLabel =S.next; W. label = S.next; }
B) {AddLabel( Y.Label ':'); } Y S1 else
{ gen(' goto' Z.nextLabel); AddLabel( Z.Label ':'); } Z S2
AddLabel( W.Label ':'); }Y ; Z ; W
产生式:S if ( B) Y S1 else Z S2 W
c=20 if(a>b) goto L3
goto L4
L3: d=x+y goto L5
L4: d=x*yL5: x=1
在LL分析中,布尔表达式的翻译
c=20;if (a>b) d=x+y; x=1
c=20 if(a>b) goto L3
goto L5
L3: d=x+yL5: x=1
产生式:S if (B)S1
S.code=B.code ||L3: || S1.code || L5:
三个非终结符:S,B,S1
继承属性:S.next
B.false=S.next;B.true =newLabel();
S1.next=S.next;
在LL分析中,布尔表达式的翻译
c=20;if (a>b) d=x+y;else
d=x*y x=1
c=20 if(a>b) goto L3
goto L4
L3: d=x+y goto L5
L4: d=x*yL5: x=1
产生式:S if (B)S1 else S2
S.code=B.code ||L1: || S1.code || goto S.next|| L2: || S2.code|| S.next:
四个非终结符:S,B,S1, S2
继承属性:S.next
B.false=newLabel();B.true =newLabel();
S1.next=S.next;S2.next=S.next;
在LL分析中,布尔表达式的翻译
c=20;while (a>b) b=x+y; x=1
c=20L0: if(a>b) goto L3
goto L4
L3: b =x+y goto L5
L4: x=1
产生式:Swhile (B)S1
S.code=L1: || B.code || L3: ||S1.code || goto S1.next|| S.next:
三个非终结符:S,B,S1
继承属性:begin= newLabel();S.next
B.false=S.next;B.true =newLabel();
S1.next=begin;
翻译布尔表达式B的SDD
产生式 语义规则
BE1 rel.op E2 B.code =E1.code || E2.code
|| gen('if' E1.addr rel.op E2.addr 'goto' B.true)
|| gen('goto' B.false)
在LL分析中,布尔表达式的翻译
• if (x > 200 && x!= y) x = 0;
将其视作:if (B1 && B2) x = 0;
三地址码如下:
if x > 200 goto L2
goto L3
L2: if x != y goto L4
goto L3
L4: x=0
L3:
BB1 && B2
B1
B2
继承属性:
B1.true =newLabel(); B1.false = B.false;B2.true =B.true; B2.false = B.false;
翻译布尔表达式的SDD
产生式 语义规则
BB1 && B2 B1.true = newlabel( );
B1.false = B.false;
B2.true = B.true;
B2.false = B.false;
B.code =B1.code || label (B1.true) || B2.code
注意:该文法不是LL文法,因产生式含左递归。
SDD仅只表达了逻辑关系,不是SDT。
在LL分析中,布尔表达式的翻译
• if (x > 200 || x!= y) x = 0;
将其视作:if (B1 || B2) x = 0;
三地址码如下:
if x > 200 goto L4
goto L5
L5: if x != y goto L4
goto L3
L4: x=0
L3:
BB1 || B2
B1
B2
继承属性:
B1.true =B.true; B1.false = newLabel();
B2.true =B.true; B2.false = B.false;
在LL分析中,翻译布尔表达式的SDD
产生式 语义规则
BB1 && B2 B1.true = B.true;
B1.false = newlabel( );
B2.true = B.true;
B2.false = B.false;
B.code =B1.code || label (B1.false) || B2.code
注意:该文法不是LL文法,因产生式含左递归。
SDD仅只表达了逻辑关系,不是SDT。
在LL分析中,布尔表达式的翻译例子
• if (x<100 || x > 200 && x!= y) x = 0; 优先级:先&&, 后 ||
if x < 100 goto L2
goto L3
L3: if x >200 goto L4
goto L1
L4: if x != y goto L2
goto L1
L2: x=0
L1:
S.next = L1; B.true =newLabel() = L2; B.false = S.next = L1;
B1.true =B.true = L2; B1.false =newLabel() = L3;B2.true =B.true = L2; B2.false = B.false = L1;
B2.1.true =newLabel() = L4; B2.1.false = B2.false = L1; B2.2.true = B2.true = L2; B2.2.false = B2.false = L1;
三地址码如下:
LL语法分析中程序文法的表达
P S ① S if (B) S T T else S | ③ S id = E ④ S while(B) S ⑤ S T id⑥ S {L} LSL L
E E+E | E*E | (E) | id B B && B | B || B | (B) | E > E | id | true | false
程序if语句
赋值语句while语句变量定义语句语句序列
当前输入符为 } 或者$, 选择L
程序例子
c=0;while(c>10) {
c=c-1;if (a>b) then {
d=x+y; } else { d=x*y; }
}x=1
c=0L0: if (c>10) goto L1
goto S(while).nextL1: c=c-1 if(a>b) goto L3
goto L4
L3: d=x+y goto S(if).nextL4: d=x*y goto S(if).nextS(if).next: goto L0
S(while).next: x=1
LL语法分析树例子
{ c=0; while(c>10) {
c=c-1; if (a>b)
d=x+y; else d=x*y;
} x=1}
S L
c=c-1
if ( B ) S else S
d=x+y d=x*y
S L
c = 0 L
x = 1Swhile (B) S
S
S L
Lc > 10
S{ L }
{ L }
LL分析中实现语句翻译的SDT——例子3
产生式:P S
P { S.next= newLabel(); } S
产生式:L S L1
{ if (当前输入符=='if' || 'while' ) S.next= newLabel(); L1.next= L.next; } S L1
产生式:L
不做任何事情, 本来是要给综合属性赋值
产生式:S {L}
P { { L.next = S.next;; } S }
I4S→ id = E
I0P→SS→ {S} S→ if(B) SS→ while(B) S S→ id = E
I1P→S
S
if
id
I3S→if( B ) S S→ {S}S→ if(B) SS→ while(B) S S→ id = E I6
S→if( B ) S
{
if
I8S→ SS
SS
I2S→ {S} S→ SS S→ if(B) SS→ while(B) S S→ id = E
I5S→ {S} S→ SS S→ if(B) SS→ while(B) S S→ id = E
I7S→ {S}}
S
{
DFA的优势——LR语法分析实用的原因
LR分析中实现控制语句翻译的SDT
产生式:S while(B) S1 B
S1
L1
L2
S.next
LL分析中,
定义了继承属性:
S.next
B.true
B.false
S.code=L1 : || B.code || L2: ||S1.code || goto L1 || S.next:
LR分析中,
则定义综合属性:
S.nextList;
B.falseList;
B.trueList;
实现同一目标:生成中间代码
goto分两种:前向,后向
c=20;while(c>10 || a>b)
c=c-1;x=1
c=20L0: if (c>10) goto L1
if (a>b) goto L1
goto L2
L1: c=c-1 goto L0
L2: x=1
前向
后向
综合属性:S.nextList;B.falseList;B.trueList
一旦变得已知,就要记录下来,用于回填
对L0, 在后面要用它,因此要记录下来
对前向goto,使用S.nextList,B.falseList,B.trueList来记录要回填的行
c=20;while(c>10 || a>b)
c=c-1;x=1
L0: if (c>10) goto L1
if (a>b) goto L1
goto L2
L1:
B被规约出来,得到B.falseList = {4}; B.trueList = {2,3}接下来就要生成S1的代码了,此刻,L1 为nextInstr= 5,要记下来,用于回填B.trueList中所指的行。
中间代码表:
Rid code1 c=202 if (c>10) goto X3 if (a>b) goto X4 goto X5nextInstr
产生式:S while(B) S1
LR分析中,综合属性的含义
c=20;while(c>10 || a>b)
c=c-1;x=1
c=20L0: if (c>10) goto L1
if (a>b) goto L1
goto L2
L1: c=c-1 goto L0
L2: x=1
综合属性:B.trueList
综合属性:B.falseList;
综合属性:S.nextList = B.falseList;
BB1 || B2
B.trueList = B1.trueList B2.trueList
B.falseList = B2.falseList
LR分析中,一个语句的next变得确定的时刻
c=0; if(c>10) {
c=c-1; if (b>c) {
b=x+y; if (a>b) { a=x*y;
} }
} x=1
在S规约出来之后,看当前输入符,如果不是’}’,意味着该语句后接另一语句,即SSS。此时S.next 变得确定,就是nextInstr;如果是'}',则说明是S是子句的末尾句,它的.next还不确定 。
c=0 if (c>10) goto L1 goto L0L1: c=c-1 if(b>c) goto L3 goto L2L3: b=x+y if(a>b) goto L5 goto L4L3: a=x*yL0: L2: L4: x=1
LR分析中,语句与语句之间的关系
c=0; if(c>10) {
c=c-1; if (b>c) {
b=x+y; if (a>b) { a=x*y;
} }
} x=1
父子关系:Sif (B) S1 { S.nextlist = B.falselist + S1.nextlist; }兄弟关系:SS1{ backpatch(S1.nextlist,nextInstr); } S2 {S.nextlist = S2.nextlist; }
c=0 if (c>10) goto L1 goto L0L1: c=c-1 if(b>c) goto L3 goto L2L3: b=x+y if(a>b) goto L5 goto L4L3: a=x*yL0: L2: L4: x=1
LR分析中实现控制语句的翻译SDT——例1
产生式:S while (B) S1
M { M.instr = nextinstr };
Swhile (M1 B) M2 S1 { backpatch(B.truelist, M2.instr);
backpatch(S1.nextlist, M1.instr);
gen('goto' M1.instr);
S.nextlist = B.falselist; }
产生式:S while (M1 B) M2 S1
c=0L0: if (c>10) goto L1 if (a>b) goto L1 goto L5L1: c=c-1 goto L0L5: x=1
LR分析中实现控制语句的翻译SDT——例2
产生式:S if (B) S1 else S2
if ( a>b ) goto L1 if ( c>10 ) goto L1 goto L2 L1: d= x+y goto S.nextL2: d= x*y S.next:
M { M.instr = nextinstr }; N { N.nextlist = makelist(nextinstr); gen('goto _'); N.instr = nextinstr;}
Sif (B) M S1 else N S2
{ backpatch(B.truelist, M.instr);
backpatch(B.falselist, N.instr);
temp= merge(S1.nextlist, N.nextlist);
S.nextlist = merge(temp, S2.nextlist); }
产生式:S if (B) M S1 else N S2
LR分析中实现布尔表达式的回填翻译SDT
BE1 rel E2 { B.truelist = makelist(nextinstr); B.falselist = makelist(nextinstr + 1);
gen('if' E1.addr rel.op E2.addr 'goto _');
gen('goto _'); }
LR分析中实现布尔表达式的回填翻译SDT
BB1 && { B2.instr = nextinstr; } B2 { Backpatch(B1.truelist, B2.instr);
B.truelist = B2.truelist;
B.falselist = merge(B1.falselist, B2.falselist); }
BB1 || { B2.instr = nextinstr; } B2 { Backpatch(B1.falselist, B2.instr);
B.falselist = B2.falselist;
B.truelist = merge(B1.truelist, B2.truelist); }
LR分析中实现语句翻译的SDT——例子3
产生式:Sid = E
Sid = E; { S.nextlist =null; }
产生式:S S1 S2
SS1 { backpatch(S1.nextlist, nextinstr); } S2 { S.nextlist = S2.nextlist; }
产生式:S {S1}
S{S1} { S.nextlist =S1.nextlist ; }
我们走到哪儿了?
给定上下文无关文法G,在第四章,解决了的问题:
lG是不是LL(1)文法, 是不是LR(1)文法的问题;
l文法 LL文法的预测分析表,LR文法的语法分析表 语法分
析器源程序生成工具;
语义分析,中间代码的生成,不是独立的环节,而是在语法分析
的过程(LL分析中的展开,LR分析中的规约,)中附带完成;
第五章, 在文法的产生式上加上动作,构造SDT。有了SDT,语
法分析,语义分析,中间代码生成,这三个工作的源程序就可由
语法分析器生成工具来自动得到;
第五章 语法制导的翻译
语法制导翻译方案SDT
语法制导翻译
语法制导定义SDD
继承属性综合属性
文法SDD
属性计算
SDDSDT
L属性的SDT
语法制导翻译应用
依赖图 计算顺序
可高效实现的SDD
S属性定义
L属性定义
抽象语法树构造
语义分析和中间代码生成
中间代码表示
类型检查和翻译
中间代码生成
DAG图
三地址码
静态单赋值
表达式翻译
控制流
翻译
过程翻译
回填
S属性的SDT
Recommended