编译原理求FIRST集、FOLLOW集和SELECT集

avatar 2018年5月28日22:03:04 评论 6,434 views

所有大写字母代表非终结符,小写字母代表终结符,省略号代表未知数目(可能为0)的不确定类型的文法符号。

First集合:

First集合顾名思义就是求一个文法符号串所可能推导出的符号串的第一个终结符的集合

First(X)就是求X所有推导出的符号串的第一个符号的集合。

求First集合可分如下几种情况:

1、单个符号的First集合:单个终结符的First集合就是它自己。

2、单个非终结符的First集合:

A-->a… 产生式右部以终结符开头,根据定义,这种情况下显然可以看出a属于First(A)。

A-->B… 产生式右部以非终结符开头,根据定义,既然可以把A替换成B……,也可以看出First(B)属于First(A)。这是一个递归的推导。

 

3、多个符号形成的符号串的First结合:

符号串ABC…,并且A不能推导出空串ε,显然根据定义First(ABC…)=First(A)

 

符号串ABC…,并且A可能推导出空串ε,当A不是空串的时候,显然First(A)属于First(ABC…),但当A是空串的时候,ABC…就成了BC…,此时根据B是否能推出空串来决定是否将First(B)加入First (ABC…)。这是一个递归的推导,综上所述,符号串中的第一个不能推出空串的符 号前面所有符号的First集合减去空串ε都属于First(ABC…),第一个不能推出空串的 符号的First集合也属于First(ABC…)。也就是假设A、B都可以推出空串,C不能推 出空串,First(ABC…)=First(A)-ε∪First(B)-ε∪First(C)。

 

注意:First集合中的符号一定是终结符,终结符也包括空串ε。

A–>…UP… 要求的Follow集合的非终结符后跟非终结符

 

Follow集合:

Follow集合也是顾名思义的,就是文法符号后面可能跟随的终结符的集合(不包括空 串ε)

Follow(X)就是求X后面可能跟随的符号集合。

求Follow集合可分如下几种情况:

终结符的Follow集合没有定义,只有非终结符才会有Follow集合。

 

 

A–>…Ua… 要求的Follow集合的非终结符后跟终结符

根据定义,显然a属于Follow(U)。这种情况下,Follow(U)和A没有任何关系,产 生式左边是什么无所谓。

 

A–>…UP… 要求的Follow集合的非终结符后跟非终结符

根据定义,显然P的第一个符号属于Follow(U),也就是First(P)属于Follow(U)。

 

A–>…UP并且ε属于First(P) 要求的Follow集合的非终结符后跟非结尾的终结符, 并且结尾非终结符的First集合包含空串。

这是上一种情况的一种特例,除了要按上一种情况处理,First(P)属于Follow(U) 以外还要进行分析;因为当P推导为空串时,空串不能出现在Follow集合中,所以U 后面跟随的应该是P后面的东西,可P已经是结束的符号,此时U后面显然就是A后 面跟随的东西了。所以在这种情况下Follow(A)也属于Follow(U)

 

A–>…U 要求的Follow集合的非终结符在产生式结尾

这时候又要递归推导,U是A的结尾,所以U后面跟随的东西也就是A后面跟随的东 西。所以Follow(A)属于Follow(U)

 

注意:Follow集合中的符号一定是终结符,并且不能包括空串ε,而且定义开始符号 的Follow集合初始为{#(句子括号)}

 

Select集合:

Select集合就是产生式左部的可能的推导结果的起始符号。

Select(A–>B)就是求这个产生式中A可能推导出起始符号集合(不包含空串ε)。

求Select集合可分如下几种情况:

A–>X (X为任意文法符号串,不限于非终结符或单个符号),并且X不能推导出空串 ε

根据定义,显然A推出的符号串起始就是X的起始,也就是First(X).

Select(A–>X)= First(X)

A–>X (X为任意文法符号串,不限于非终结符或单个符号),并且X能推导出空串ε

根据定义,显然First(X)属于Select(A–>X),此外,当X推导为空串时,显然A 也推导为空串,那么此时推导出的符号串就会是A后面的符号的推导结果。也就是 Follow(A),所以,此时Follow(A)也属于Select(A–>X)。

注意:Select集合中不包括空串ε,但有可能会包含#(句子括号)。

 

举个例子:

S→AB

S→bC

A→ε

A→b

B→ε

B→aD

C→AD

C→b

D→aS

D→c

求他的first,follow,select

先求First集

  • 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)文法

 

原文地址:

https://blog.csdn.net/u014374031/article/details/50239667

https://blog.csdn.net/luobida222/article/details/73542851

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: