自上而下分析算法要点:
。由根向下构造语法树
。构造最左推导
。推导出的终结符是否与当前输入符匹配
5.1 确定的自顶向下分析思想
例1 :若有文法G1[S]
S →pA | qB
A →cAd |a
B → dB |bf
对于输入串:W=pccadd自顶向下推导过程:
S pA pcAd pccAddpccadd分析成功
该文法有两个特点:
- l 每个产生式的右部都有终结符号开始。
- l 如果两个产生式左部相同,那么他们右部有不同的终结符开始。
(1)First集
定义5.1 设G=(VT, VN,P,S)是上下文无关文法,
FIRST(a)={a|a ab,a∈VT, a, b∈V* }。
若a ε则规定ε∈FRIST(a),称FIRST(a)为a的首符号集。
例2:
S →Aa | Ba A →cb B →bA | aBc 问符号串cba是否为该文法句子。
SAa (S → Aa)
cba (A → cb)
FRIST(Aa)={c} FRIST(Ba)={b, a}
FRIST(Aa)∩Ba) =Φ
(2)Follow集
定义5.2 设G=(VT, VN,P,S)是上下文无关文法
FOLLOW(A)={a|S m A b且a ∈ FRIST(b),m∈V*, b∈V+ }
若S u A b,且b ε,则规定#∈FOLLOW(A)
例3:
S →dB | ε B →dfa是否为该文法句子。
SAa (S → Aa)
dBa (A → dB)
dfa (B → f)
FRIST(dB)A)={a ,e }
FRIST(dB)∩FOLLOW(A)=Φ
一个文法G能进行确定的自顶向下分析,当且仅当对于G的每一个非终结符A的任何两个不同产生式A®α½β,下面的条件成立:
FIRST(α)∩FIRST(β)=f,也就是α 和β推导不出以同一个终结符a为首的符号串;它们不应该都能推出空字e.
假若βε,那么,FIRST(α)∩FOLLOW(A)=f。 也就是,若βε则α所能推出的串的首符号不应在FOLLOW(A)中.
(3)SELECT集
定义5.3 设G=(VT,P,S)是上下文无关文法,对P中的任一 产生式 Aa α,VN ,V*。
若αε, 则SELECT(A→α)= FRIST(α)
若αε,则SELECT(A→α)=(α)-{ε})∪A)
如果对于G的每一个非终结符A的任何两个不同产生式A→ α|β,都有
A →α)⋂A→β)=Φ,其中α、β不能同时ε。
G进行确定的自顶向下分析。
例2中:S –> Aa | Ba SELECT(S –> Aa) ∩S –> Ba )= Φ
A –>cb
B –> bA | aBc SELECT(B –> bA) ∩B –> aBc)=Φ
所以能对文法G[S]进行确定的自顶向下分析。
例3中:S –> Aa | bB SELECT(S –> Aa) ∩S –> bB )=Φ
A –>dB | ε SELECT(A –>dB) ∩A –>e=Φ
B –> Ae | f SELECT(B –> Ae) ∩B –> f )=Φ
所以能对文法G[S]进行确定的自顶向下分析。
(4)LL(1)的定义
定义5.4 一个上下文无关文法是1)文法的充分必要条件是:对于G的每一个非终结符A的任何两个不同产生式A→ α|β,满足SELECT(A →α) ∩A→β)=Φ,其中α、β不能同时ε。
5.2 LL(1)文法的判别
一个文法G是LL(1)的,当且仅当对于G的每一个非终结符A的任何两个不同产生式A→α|β,下面的条件成立: SELECT(A →α) ∩A→β)=Φ,其中α、β不能同时ε。
步骤如下:
(1)求出能推出ε的非终结符
可通过求其First集,First集中含ε即可。
(2)计算FIRST集
1)若X∈VT,则FIRST(X)={X}。
2)若X∈VN,且有产生式X→a…,则把a加入到FIRST(X)中;若X→a也是一条产生式,则把ε也加到FIRST(X)中。
3)若X→Y…是一个产生式且Y∈VN,则把FIRST(Y)中的所有非ε元素都加到FIRST(X)中;若X→Y1,Y2,…,Yi-1都是非终结符,而且,对于任何j,1≤j ≤i-1,Yj)都含有ε (即Y1。。Yi-1 * ε ),则把FIRST(Yj)中的所有非e元素都加到FIRST(X)中;特别是,若所有的FIRST(Yj ,2,…,K)均含有ε,则把ε加如FRIST(X)。
(3)计算FOLLOW集
1)对于文法的开始符号S,置#于FOLLOW(S)中;
2)若A→αBβ是一个产生式,则把FIRST(β)-{ ε}加至FOLLOW(B)中;
3)若A→αB是一个产生式,或A®αBβ是一个产生式而βε(即eÎFIRST(β)),则把FOLLOW(A)加至FOLLOW(B)中?(S …Aa… … αBβa…)。
(4)计算SELECT集
对上下文无关文法G=(VT,P,S)中的任一产生式A→α(VN , α∈V* ),计算SELECT集:
当α*ε时,SELECT(A→α)= FRIST(α)。
当α*ε时,SELECT(A→α)=(-{ε})∪A)。
例4:G[ E]:
(1)2)3)e
(4)5)6)e
(7)E)8) i
第一步:各非终结符的FIRST集合为:
FIRST(E)={(,i};FIRST(E′)={+,ε};FIRST(T)={(,i}
FIRST(T′)={*,ε};FIRST(F)={(,i}
第二步FOLLOW集合为:
E)={),#};E′)={),#};FOLLOW(T)={+,),#}
T′)={+,),#};FOLLOW(F)={*,+,),#}
第三步:求各非终结符的SELECT集:
E’ →+TE’ | e
E’ →= FIRST(+TE’)={+}
SELECT (E’ →e)=FOLLOW(E′)={),#}
T’ →e
T’ →= FIRST(*FT’)={*}
T’ → e= FOLLOW(T′)={+,),#}
F→ (E) | i
F→(E) )= FIRST((E))={(}
F→ (E)= FIRST(a)={i}
因为文法中每个非终结符的所有产生式的SELECT集两两不相交,所以G[E]是LL(1)的
5.3 某些非LL(1)文法到LL(1)文法的等价变换
5.3.1提左公因子
αβ|αγ 变换为:A→αB
|γ
例5:S →aS S → ε
改写为: S →b|ε)ε
在改写:S →aSA A→b|ε S→ε
有时,左公共因子是隐式的。
例6:A →Bc B →bB
改写为:A →aAc|bBc B →bB
改为:A →aA’|bBc A’ →aA B →bB
5.3.2 消除直接左递归
α 或A→B β 且α,含有左递归的文法不能进行自顶向下分析。
一般情况:A→Aα1|Aα2|…Aαm| β1 |β2… | βk
变形为:A®A(α1|α2|…αm)1 |β2… | βk )
改写为:A→(β1 |β2… | βk )A’ A’ →(α1α2|…αm)A’| ε
例7:Qc|c Q →Rb|b R→Sa|a
非终结符次序S,Q,R
Qca|ca|a R →Rbca|bca|ca|a
改写为:S →Qc|c Q →Rb|b R →(bca|ca|a )R’ R’ →bcaR’|e
5.4 不确定的自顶向下分析
(1)对于文法G中的某一个非终结符A,存在A的两个不同产生式A→ α|β,并且
FIRST(α)∩FIRST(β)≠Φ
确定不了用哪个产生式推导。
举例如下:带回溯的自上而下分析
S→ b | bB
推导串:a a a b b。
正确过程:
S(1) AB S –> AB
(2) aAB A –> aA
(3) aaAB A –> aA
(4) aaaAB A –> aA
(5) aaa ε B A –> ε
(6) aaab B –> b
错误推导:
S(1) A。。。> AB
(2) aA。。。> aA
(3) aaA。。。> aA
(4) aaaA。。。> aA
(5) aaa ε B A –> ε
(6) aaa b B B –> bB
(7) aaabb B –> b
因为:FIRST(B –> b)∩FIRST(B –> bB)={b}
(2)对于文法G中的某一个非终结符A,存在A的两个不同产生式A→ α|β,并且
假若βε,那么,FIRST(α)∩FOLLOW(A)≠Φ
(3)文法G中含有左递归
5.5 确定的自顶向下分析方法
确定的自顶向下分析方法:
- l 特征——根据下一个输入符号为当前要处理的非终结符选择产生式。
- l 要求——文法是LL(1)。
ü L:从左到右扫描输入串
ü L :生成的是最左推导
ü lookahead)
5.5.1 递归子程序法
递归下降子程序: 对应文法中每个非终结符编写一个过程。
例:递归子程序实现 --表达式的语法分析
〈表达式〉∷=[+|-]〈项〉{(+|-)〈项〉}
〈项〉∷=〈因子〉{(*|/)〈因子〉}
〈因子〉∷=ident|number|(〈表达式〉)
〈表达式〉∷=[+|-]〈项〉{(+|-)〈项〉}
5.5.2 预测分析方法
预测分析方法是自顶向下分析的一种方法,一个预测分析器是由三个部分组成。
- l 预测分析程序(总控程序)
- l 先进后出栈(stack)
- l 预测分析表
下推栈的初始状态包含两个符号:‘#S’,其中‘#’为栈底,‘S’为文法开始符号。整个分析过程在语法分析程序控制下进行。在语法分析中用到的文法产生式的表,称为语法表。
(1)基本模型
基本模型如下:
预测分析程序是无回溯的自顶向下分析程序。
(2)工作过程
其工作过程如下:
图中符号说明如下:
- l “#”句子括号即输入串的括号
- l “S”文法的开始符号
- l “X”存放当前栈顶符号的工作单元
- l "a"存放当前输入符号a的工作单元
(3)预测分析法步骤
通过举例讲解预测分析法具体步骤如下:
例:G[ E]: (1)E →2)3)E’ → e
4)T →FT’ (5)T’ →6)T’e
7)F →(E)8) a
第一步:构造预测分析表
设每个终结符或“#”用a表示:
1)对文法G的每个产生式A®a执行:
若ÎSELECT(A®a) ,则把A®a加至M[A,a]中。
2)把所有无定义的M[A,a]标上“出错标志”。
可以证明,一个文法G的预测分析表不含多重入口,当且仅当该文法是LL(1)的。
SELECT(E→= FIRST(TE’)FT’)a}
SELECT(E’ →+TE’)= FIRST(+TE’)={+}
SELECT (E’ →ε)=FOLLOW(E′)={),#}
SELECT(T→ FT’)= FIRST(FT’)a}
SELECT(T’ →= FIRST(*FT’)={*}
SELECT(T’ →ε)= FOLLOW(T′)={+,),#}
SELECT(F→ (E) )= FIRST( (E))={(}= FIRST(a)={a}
因为文法中每个非终结符的所有产生式的SELECT集两两不相交,所以G[E]是LL(1)的。
其预测分析表如下:
第二步:分析输入串#a+a#
栈内容b ]
1 #E E a +a# E→ TE’
2 #E’T T a +a# T→ FT’
3 #E’T’F F a +a# F→ a
4 #E’T’a a a +a#
5 # E’T’ T’ + a# T’ →ε
6 #E’ E’ + a# E’ → +TE’
7 #E’T+ + + a#
8 # E’T T a # T→ FT’
9 #E’T’F F a # F→ a
10 #E’T’a a a #
11 #E’T’ T’ # T’ → e
12 #E’ E’ # E ’ → e
13 # # #