在判断一个文法是不是LL(1)文法之前我们需要首先掌握一些基础知识:
三个重要的集合
开始符号集FIRST 后跟符号集FOLLOW 选择集合SELECT
首先是FIRST集合
定义1:
G=(V
N
, V
T
, P, S)
是上下文无关文法
α→β
,
(α
∈
VN , β∈(VN∪
V
T
)* )
FIRST(β) = {a | a∈VT 且β⇒* a......}
若β⇒* ε 则规定ε ∈FIRST(β)
直观上说文法符号串β 的开始符号集是由β推导
出的所有的
终结符开头
和
可能的ε
组成
例题:
文法G
2
[S]:
S→Ap
S→Bq
A→a
A→cA
B→b
B→dB
求出每条规则右部的符号串的FIRST集合
FIRST(Ap)={a,c}
FIRST(Bq)={b,d}
FIRST(a)={a }
FIRST(cA)={c}
FIRST(b)={b}
FIRST(dB)={d}
这里注意一点在求FIRST集合时很多时候会忘了ε,如果推导不出来那就没关系但是如果可以推导出来的话一定要写上。
接下来是FLLOW集合这个是最复杂的也是最难的
定义
4.2
G=(V
N
, V
T
, P, S)
是上下文无关文法
B→xAy
,
(A, B
∈
V
N , x,y∈(VN∪
V
T
)* )
FOLLOW(A)={a|S=>*…Aa…
,
a
∈
V
T
}
,
若有
S=>* …A
,则规定
#
∈
FOLLOW(A)
注:输入串
#
,‘
#
’做为输入串的结束符
直观上说,非终结符A的后跟符号集是由句型中
紧跟A后的那些
终结符
(包括
#
)组成
FOLLOW(A)
的计算方法
1
如果
A
为文法的识别符号,则规定
#
∈
FOLLOW(A)
2
如果有形如
B→α Aβ
的规则,则
FIRST(β)
的非空元素
∈
FOLLOW(A)
3
如果有
β=>*ε
,戒者形如
B→α A
的规则,则
把
FOLLOW(B)
加入到
FOLLOW(A)
中
反复使用上述规则,直到每个非终结符的
FOLLOW
集不再增大
为止
之所以说这个复杂跟他的第3条规则有很大的关系反复使用这个规则在计算中会很复杂。
例子:
文法
G
3
[S]: S→aA|d A→bAS|ε
FOLLOW(A)=Follow(S) ∪ {FIRST(S)-{
ε
}}
={#} ∪{a,d}
={#, a, d}
FOLLOW(S)= {#} ∪ FOLLOW(A)
={#, a, d}
最后是
SELECT
集合的部分这个是跟之前的FIRST集合和FOLLOW集合是有很大关系的。
G=(V
N
, V
T
, P, S)
是上下文无关文法
A
→
β
,
(A
∈
V
N
,
β ∈
(V
N∪
V
T
)* )
若 β ≠>*ε,
则
SELECT(A→β)=FIRST(β)
若 β=>*ε, 则
SELECT(A→β)=(FIRST(β)-{ε} ) ∪
FOLLOW(A)
例子:
G
3
[S]:
S→aA
S→d
A→bAS
A→ε
SELECT(S→aA)=FIRST(aA)={
a
}
SELECT(S→d)=FIRST(d)={
d
}
SELECT(A→bAS)=FIRST(bAS)={
b
}
SELECT(A→ε)
=(FIRST(ε)-{ε})+ FOLLOW(A)={
#,a,d
}
最后一个重要的知识点FIRST集合所面对的是一个单词,FOLLOW集合面对的是一个非终结符,SELECT集合所面对的是一个产生式。