编译原理LL(1)

编译原理LL(1)分析法学习总结

刚上完编译原理,下午1,2节都有点打瞌睡,重新学习整理一下


学习内容

1、first集
2、follow集
3、 LL(1)文法


内容

找first集

1:这是书上first集合的定义:
在这里插入图片描述

很显然这么定义是看不懂的也不知道 这句话在干什么


那就直接来看FIRST集的分析方法 :

对于文法中的符号X∈VN∪VT,其FIRST(X)集合可反复应用下列规则计算,直到其FIRST(X)集合不再增大为止:

1)若 X∈VT,则FIRST(X)={X}。

2)若X∈VN,且具有形如X→aα的产生式(a∈VT),或具有形如X→ε的产生式,则把a或ε加进FIRST(X)。//把X能推出的第一个终结符加入FIRST(X)。

  1. 设G中有形如X→Y1…Yk的产生式,其中X,Y1…Yk∈VN,且Y1…Yi-1均能=>*ε(1≤i≤k),则FIRST(Y1)-{ε},…, FIRST(Yi-1)-{ε},FIRST(Yi)都包含在FIRST(X)中。// Yi推导不出ε,所以Yi+1不在FIRST(X)中。

  2. 若对一切1≤i≤k,均有ε∈FIRST(Yi),则将ε符号加进FIRST(X)。//若X=>*ε,则将ε加入FIRST(X)。

看完是不是觉得还是思路还是不是很会:

那我们就举个例子

例子

首先先说一下默认规则 :

起始符E,其余大写字母为非终结符;
小写字母为终结符,#为ε;
产生式: E->TE, 其中这个是关于A的产生式,A为左部(左边部分),BC为右部 (右边部分)
Vt是终结符
Vn是非终结符

题目

随便找个文法G[S]:

S-> B|bC

A->#|b

B->aB|#

其实first集就是该符号的所有产生式右部第一个是终结符

求解

S的产生式有两个:S->AB,S->bC

1、S->bC,明显右部第一个终结符是b, 那关于这个产生式的终结符就是b 了

这个时候把b放进来 first(S)={b}

2、然后是S->AB,这时右部的第一个是A,非终结符,所以不成立。这时你就要再把A的产生式引进来(因为A有关于他的产生式)。

关于A的产生式为:A->#,A->b,分别代入S->AB的产生式得:S->B(应该是S->#B,但是#可以省略) 和S->bB.

看第二个S->bB ,马上就可以知道遇到的第一个终结符是b,

这个时候first(S)={b}
3、然后看第一个S->B,这个时候B不是终结符,所以不成立,这时就要把B的产生式导进来。

变成S->aB ,S->#,

然后上面两个式子,分别第一个终结符为a,和 #

则这个时候first(S)={b, a , #}

然后按照这种方式把所有非终结字符first集全求出来

找follow集

就是该符号后面跟着的第一个终结符
follow集定义:

follow(A)={a | S=*>…Aa…,a∈Vt}…

若 S=*>…AB…,则follow(A)=first(B)…

若S=*>…A ,因为这个时候A属于S,因此这个时候应该看得是S后面的东西也就是follow(S)∈follow(A)…

若S=*>…AB,这个时候first(B)存在空的情况,而这个时候first的空集不能出现在follow集中,因此还应该看S后面的东西,因此这个等于follow(A)=(first(B)-{#})∪follow(S)…

follow集的分析方法

  1. 对于文法的开始符号S,置#于FOLLOW(S) 中;

  2. 若A→αBβ是一个产生式,则把FIRST(β)-{e}加至FOLLOW(B)中;若β=>*e (即eÎFIRST(β)),则把FOLLOW(A)加至FOLLOW(B)中。//若B有可能是最后一个符号,则把

FOLLOW(A)加至FOLLOW(B)中,否则把FIRST(β)- {e}加至FOLLOW(B)中。

反复使用上述规则,直到所求FOLLOW集不再增大为止。

例子

题目

注意:FIRST集从产生式左侧推导,而FOLLOW集从产生式右侧推导。例如求A的FIRST集,要先从产生式左侧找到A,然后根据产生式右侧的信息求出A的FIRST集;求A的FOLLOW集时,要先从产生式右侧找到A,然后根据A右侧的符号信息求出A的FOLLOW集。

S->xAy

A->aBb

求解

FOLLOW(A):

因为要找A后面的跟着的第一个终结符,所以应该直接看谁能产生A,得

S->xAy,

此时A后面跟着的终结符是y,因此follow(A)={y}

求FOLLOW(B)

则先找谁能产生B:

B的产生式:

A->aBb,此时,要把first(b)(因为是B后面遇到第一个终结符,也就是first(b),也就是b的first集合)

但是如果这个时候b等于#,那么B的follow集应该取得是b(假设b可能为空的情况)后面的东西,那么问题来了,b后面的东西怎么来呢?

S->xAy,先看下A的产生式,(因为永远是从S出发,因此当产生式出现B的时候一定是这样的流程)

然后代入A的产生

S->xaBby

可以看到出现B的时候是这样的,所以这个时候就应该是把b忽视,直接看y,那么这个时候是不是很熟悉?没错就是跟上面求FOLLOW(A)的一样做法,也就是follow(A)∈follow(B)

这个时候可以总结一个规律

当b为#的时候,follow(B) 就应该看谁产生生它的那个非终结符的follow(),在这里就是因为A->xBy,因此看follow(A)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值