期末复习中,编译原理要搞死我了。。。。
在被编译原理搞死之前,我要搞死编译原理。。。。
求First(x)的算法:
若x∈VT ,则first(x)={x}
若X∈VN ,且有产生式 Xa… , a∈VT ,则a∈first(X)
若X∈VN ,xε,则ε∈first(X)
若X∈VN ,且有产生式 XY1Y2…Yn ,其中Y1,Y2,… Yn都∈VN
当Y1,Y2,… Yi-1都能推导出ε时(1<=i<=n),
则 first(Y1) - {ε}∈first(X)
first(Y2) - {ε}∈first(X)
…
first(Yi) ∈first(X)
当Y1,Y2,… Yn都能推导出ε时,
则first(X) = (first(Y1)-{ε})∪(first(Y2)-{ε})∪ ……
∪(first(Yn)-{ε})∪{ε}
(上面那个是老师ppt里面粘过来的,我看不懂,能不能说人话。。。这是什么鬼算法。。。你要是也看不懂就别理他了,看我下面的例子和解释)
求follow集算法:
设S为开始符号,把{#}加入Follow(S)中(#为句子括号)
若A→αBβ,则把 First(β)–{ε} 加入Follow(B)中,
如果β ε,则把 Follow(A)也加入Follow(B)中。
反复2,直到每个VN的Follow集不再增大为止。
举个例子:
S→AB
S→bC
A→ε
A→b
B→ε
B→aD
C→AD
C→b
D→aS
D→c
求他的first,follow,select
First(S) =(First(A)-{ε})∪(First (B)-{ε}) ∪{ε}∪{b}
={a,b,ε}
因为A的first有ε,B的first有ε,S->AB,所以是First(A)-{ε})∪(First (B)-{ε}) ∪{ε},然后S->bC,所以再加一个b,就是First(A)-{ε})∪(First (B)-{ε}) ∪{ε}∪{b},
First (A)={b, ε}
没什么好解释的
First (B)={a, ε}
ε不用解释,就是B->ε,所以有他,a就是因为B->aD,第一个非终结符是a所以有a,那要不要加上D的first呢,就是a和c,答案是不用,就只要aD里面的a就可以
First (C)={a,b,c}
C->AD这一句,AD都是非终结符,所以要找A和D的first集,D的是a,c,A的是b,ε,因为不是AD同时都能推出ε所以C的first是A和D的first的并集减去ε,还要加上b,因为有C->b这一句
First (D)={a,c}
D->c不用解释,D->aS这一句,不用加上S的first!!!
First (AB)={a,b,ε}First (bB)={b}
First (ε)={ε} First (b)={b}
First (aD)={a} First (AD)={a,b,c}
First (aS)={a} First (c)={c}
AB同时能够推出ε,所以first(AB)就是A和B的first的并集减去ε再并上ε
bB的first就是b,不用加上B的first
ε的就是ε,b就是b,c就是c,只有一个终结符ε没什么好说的
一个终结符和一个非终结符的,就要那个终结符就可以,不用管后面那个非终结符,
两个非终结符的要看是不是他们两个同时能推出ε,能就有ε,要是有一个不能推出ε,那first集就没有ε
AB有ε是因为AB都能推出ε,AD没有是因为A能D不能推出ε
以上first集就求完了,是不是很简单,我搞了一上午。。。
接下来求follow集
从开始符号S开始推倒,开始符号的follow里面一定要有#,
所以开始符号的S的follow集要有#,
follow是找->后面的,比如找S的follow,就要看谁的->后面有S,D->aS里面有S,然后在看D->aS的S后面有没有别的符号,没有就加上D的follow集,如果有,就加上后面那个字母的first集里面除了ε以外的符号,在看这个字母能不能推出ε,如果能,就再加上->左边的那个字母的follow
看A的follow,首先找所有->后面有A的,找到了S->AB,C->AD,先看S->AB,A后面有B,所以要加上B的first集里面除了ε的其他符号,再看B能不能在有限的步骤里推出ε,有B->ε这句,所以能,就要再加上->左边的S的follow集,所以目前的A的follow集里面有a,和follow(S),再看C->AD这一句,A后面有D,所以要加上D的first集里面除了ε的其他的,再看B能不能在有限的步骤里推出ε,D不能,所以不用加->左边的C的follow,所以A的follow就是a,follow(S),a,c,但是如果有重复的,就只要一个,所以最终就是a,c,follow(S),这个follow(S)到后面还要算出来的,不能就这样写
看B的follow,找所有->后面有B的,找到了S->AB,看B后面有字母吗?没有,就加上->左边的S的follow,所以follow(B)=follow(S)
看C的follow,找所有->后面有C的,找到了S-bC,看C后面有字母吗?没有,就加上->左边的S的follow集,所以follow(C)=follow(S)
看D的follow,找所有->后面有D的,找到了B->aD。C->AD,这两句D后面都没有字母,所以加上->左边的B和C的follow,所以follow(D)=follow(B)并上follow(C)
最终要把以上的follow都求出来,看follow(S)=#+follow(D),follow(D)=follow(B)+follow(C),所以follow(S)=#+follow(B)+follow(C),follow(B)=follow(S),follow(C)=follow(S)所以follow(S)=#+follow(S)+follow(S),所以follow(S)就是#,follow(B),follow(C),follow(D)也都是#,所以follow(A)就是ac,#,求完了,以上所有的+代表求并集
再看select怎么求
对于A->a,如果a=/>ε,那么select(A->a)=first(a),如果a=*>,那么select(A->a)就是first(a)-ε+follow(A)
看select(S->AB),AB都能推出ε,所以select(S->AB)=first(AB)-ε+follow(S)所以结果是a,b,#
看select(S->bC),bC不能推出ε,所以是first(bC),结果是b
看select(A->ε),A能推出ε所以是first(ε)-ε+follow(A)结果a,c,#
看select(A->b),这里的A是推出b不是ε所以是first(b),结果是b
看select(B->ε),B能推出ε,所以是first(ε)-ε+follow(B),结果是#
看select(B->aD),这里B不能推出ε,所以是first(aD),结果是a
看select(C->AD),这里D不能推出ε,所以算AD不能推出ε,就是first(AD),结果是a,b,c
看select(C->b),C推不出看ε,所以是first(b),结果是b
看select(D->aS),这里不能推出ε,所以是first(aS),结果是a
看select(D->c),这里D不能推出ε,所以是first(c),结果是c
LL(1)文法
是自顶向下分析,从左到右扫描输入串,最左推导,只需向右看一个符号就可以决定如何推倒
LL(1)文法满足条件:左部相同的产生式的select集的交集为空,并且产生式的右部不能同时推导出ε,那么这个文法是LL(1)文法,否则不是
上面的文法select(C->AD)和select(C->b)的交集是b不是空,select(S->AB)和select(S->bC)的交集也是b不是空,所以这不是一个LL(1)文法