文章目录
一、自下而上分析
自上而下分析的方法是产生语言的自然过程。但是对于分析源程序来讲,自下而上分析的方法更自然,因为语法分析处理的对象一开始都是终结符组成的串,而不是文法的开始符号。
同时,自下而上分析中最一般的方法,LR方法的能力比自上而下分析的LL方法要强,从而使得LR分析成为最为实用的语法分析方法。
1.短语
方法:画出分析树,根据分析树分析
- 短语:以非终结符为根子树中所有从左到右的叶子;
- 直接短语:只有父子关系的树中所有从左到右排列的叶子(树高为2);
- 句柄:直接短语中最左边父子关系树中所有从左到右排列的叶子(句柄是唯一的)。
例:文法:
E→E+T|T
,T→T*F|F
,F→id
句型:id1+id2*id3
分析树:
短语:
id1+id2*id3 (E1)
id2*id3 (T1)
id1 (E2, T2, F1)
id2 (T3, F3)
id3 (F2)
直接短语:
id1 (F1)
id2 (F3)
id3 (F2)
句柄:id1 (F1)
PS:
问题:id1+id2
是句型id1+id2*id3
的短语吗?
答案:不是。
为什么?
① 没有一个E的子树,它的全部叶子是id1+id2
;或者②找不到某个E,使得 E=*>E*id3
,E=+>id1+id2
2.最左归约
最左归约的逆过程是一个最右推导,分别称最右推导和最左归约为规范推导和规范归约。
替换为相应产生式左部非终结符,归约符号是<=
3.移进-归约分析器
(1)工作模式
- 工作方法:放幻灯,每个幻灯片是一个格局。
- 格局:(
#栈中内容
,当前剩余输入#
,改变格局的动作
) - 改变格局的动作:
- 移进(shift):输入序列中的终结符进栈。(匹配终结符)
- 归约(reduce):将栈顶句柄替换为对应非终结符(最左归约)
- 接受(accept):宣告分析成功
- 报错(error):发现语法错误,调用错误恢复例程
PS:栈中保留的总是一个右句型的前缀(加上若干终结符形成句型),称为活前缀
例3.27 用移进-归约方法分析
abbcde
:abbcde<=aAbcde<=aAde<=aABe<=S
二、构造SLR(1)分析器
1.定义3.17 项目
一个LR(0)项目(简称项目)是这样一个产生式,在它右部的某个位置有一个点“.”。对于A→ε,它仅有一个项目A→.。
E→E-T|T T→T*F|F F→-F|id 的全部LR(0)项目:
E→.E-T E→E.-T E→E-.T E→E-T.
E→.T E→T.
T→.T*F T→T.*F T→T*.F T→T*F.
T→.F T→F.
F→.-F F→-.F F→-F.
F→.id F→id.
项目A→α.β
显示了分析过程中看到(移进)了产生式的多少。
- β不为空的项目称为可移进项目,
- β为空的项目称为可归约项目。
2.拓广文法与识别活前缀的DFA
(1)拓广文法G’
G' = G∪{S'→S}
其中:
S'→.S
是识别S的初态,S'→S.
是识别S的终态。- 目的是使最终构造的DFA状态集中具有唯一的初态和终态。
例:文法G:
E→E-T|T
,T→T*F|F
,F→-F|id
拓广文法:G' = G∪{E'→E}
唯一初态与终态:E'→.E
和E'→E.
(2)NFA(项目)→DFA(项目集)
词法分析器-“子集法” :
- ① ε_闭包(I):从状态集I不经任何字符能到达的状态全体;
- ② smove(I,a):所有从I经字符a能直接到达的状态全体。
类似的两个过程:
- ①
closure(I)
:从项目集I不经任何文法符号到达的项目全体; - ②
goto(I,x)
:所有从I经文法符号x能直接到达的项目全体。
定义3.20
项目[S'→.S]
和所有“.”不在产生式右部最左边的项目称为核心项目(kernel items),其它“.”在产生式右部最左边的项目(不包括[S’→.S])称为非核心项目(nonkernel items)。
(3)构造DFA:
- 计算DFA的初态,
I0=closure({S'→.S})
- 计算所有状态的所有状态转移,即考察每个未标记状态
Ii=closure(goto(Ii,x))
)
例:G :
S→AB
,A→aAb |ab
,B→c |Bc
拓广文法 G' = G∪{S'→S}
,构造的 DFA 如下,其中 I0 为初态,I1 为终态。
(4)项目集中的冲突
冲突:
- 移进/归约冲突:
A→β1.β2
和B→β1.
【β1.
有东西和没东西】:既可移进又可归约 - 归约/归约冲突:
A→α.
和B→α.
【α.
都没东西】:均可指导下一步分析
解决方法:简单向前看一个终结符:
移进/归约冲突:若FIRST(β2)∩FOLLOW(B)=Φ
,冲突可解决
归约/归约冲突:若FOLLOW(A)∩FOLLOW(B)=Φ
,冲突可解决
【移进是看输入文法序列中的下一个字符,即项目.
右部的字符,所以是FIRST(β2);归约是舍弃当前栈中的非终结符,即项目左部。】
【交集为空,表示下一步展开是唯一的,所以冲突可解决】