编译原理follow集与first集的计算

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理follow集与first集的计算相关的知识,希望对你有一定的参考价值。

参考技术A 下面我将介绍一下我关于LL(1)文法部分的计算文法非终结符First集以及Follow集两个知识点的理解。

首先是First集的计算部分,计算First集首先看我们原文法的左边,原文法左边不重复的都要进行First集的计算,计算时具体有以下三种情况:

(1)先看产生式后面的第一个符号,如果是终结符,那就可以直接把它写到这个产生式的First集中,例如:产生式为M->nDc,那在First集中我们就可以直接写上First (M)= n ;

(2)如果产生式后面的第一个符号是非终结符,就看这个非终结符的产生式,看的时候同样利用前面的两种看法;但是当产生式为ε时,则需要把ε带入到待求First集的元素的产生式中再判断。例如:A->Bc; B->aM;B->ε,求First(A)时,我们看到A的第一个产生式中的第一个符号是B,B是一个非终结符,所以我们就要接着看B的产生式,B的第一个产生式的第一个符号为a,a是一个终结符,直接把a写入First(A),B的第二个产生式为ε,把ε带入A->Bc中,A->c(注意:如果将B->ε带入表达式后A的产生式为A->ε,ε不可以忽略),c是终结符,所以把c也写入First(A),最后First (A)= a,c 。

(3)当产生式右边全为非终结符,且两个非终结符又都可以推出ε时,我们需要把这个产生式的所有情况都列出来,再分析。例如:A->BC;B->b|ε;C->c|ε。我们把A的所有产生式利用上述两种方法列出来就是A->bc,A->b;A->c,A->ε;最后First (A)=b,c, ε。

接下来介绍一下Follow集的部分,先简单介绍一下计算Follow集的大致规则。比如我们要求Follow(X),文法中多个产生式中含有X,则需要考虑多种情况,以下是具体计算时的三种情况:

(1)文法开始符:所有文法开始符的Follow集中都有一个#。

(2)S->αB的形式:求Follow(B),因为B的后面为空,把Follow(S)写入B的Follow集中。

(3)S->αBβ的形式:求Follow(B),B后部不为空。

①当β是终结符时,直接把β写入Follow(B)。

②当β是非终结符时,将First (β)(如果First(B)中有ε,就把ε删掉)写入Follow(B)中。(需要注意的是:如果β->ε,那么原产生式就变成了S->αB,也就是第二种情况,这两种情况都要算在Follow(B)中)。

编译原理: FIRST(x) FOLLOW(x) SELECT(x)的计算

目录
已知文法G[S]:
           S→MH|a
           H→LSo|ε
           K→dML|ε
           L→eHf
           M→K|bLM
判断G是否是LL(1)文法。

First计算

First集合的定义就是某个非终结符表达式可以推导出来的第一个字符可以是什么
比如表达式S --> abb,它的First(S)=a

First(S)=a+First(M)+First(H)+ε=a,b,d,e,ε
# S表达式存在单个的终结符a,添加a
# S表达式以M开头,添加First(M)
# 根据后面的表达式判断,M可以推出K,K可以推出空,所以M可以为空,此时S以H开头,添加First(H)
# 由于H也可以推出空,所以S最终也会指向空,添加 空集
First(M)=b+First(K)+ε=b,d,ε
# M表达式以终结符b开头,添加b
# M表达式可以推导出单个的K表达式,所以添加First(K)
# K有可能推导出空集,即M可以推导出空,所以添加 空集
First(K)=d+ε=d,ε
# K可以以终结符d开头,添加d
# K可以推导出空,添加空集
First(H)=First(L)+ε=e,ε
# H可以推导出以L开头的表达式,所以添加First(L)
# H可以推导出空,所以添加空集
First(L)=e
# L只能推导出一个表达式,并且开头是终结符,所以添加e

## 最后将已知的表达式代入到未知的表达式当中去,即可求出全部First集合

Follow计算

Follow表示某个非终结符后面可以跟着什么样的字符
Follow集不存在空集
为表达式编号

1: S→MH|a
2: H→LSo|ε
3: K→dML|ε
4: L→eHf
5: M→K|bLM
Follow(S)=$+o=o,$
# 在表达式1中,S是一个非终结符,S是孤立的一个表达式,其Follow可以添加$,即添加$
# 在表达式2中,S后面跟上了o,所以添加o
Follow(H)=Follow(S)+f=f,o,$
# 在表达式1中,S后面跟了什么,MH后面就跟了什么,所以添加Follow(S)
# 在表达式4中,H后面跟了f,所以添加f
Follow(M)=First(H)+Follow(S)+First(L)=e,o,$
# 在表达式1中,M后面跟了H,所以添加First(H)
# 在表达式2中可知,H可以推导出空,所以回到表达式1,S后面跟了什么,M后面就跟了什么,所以添加Follow(S)
# 在表达式3中,M后面跟了非终结符L,所以添加First(L)
# 在表达式5中,M后面跟了什么,bLM后面就跟什么,都是Follow(M),表达式不变
Follow(L)=First(S)+Follow(K)+o+$+First(M)+Follow(M)=a,b,d,e,o,$
# 在表达式2中,L后面跟了非终结符S,所以添加First(S)
# 在表达式2中,First(S)可以推出空,所以此时L后面跟着o,添加o
# 在表达式3中,K后面跟了什么,dML后面就跟了什么,所以添加Follow(K)
# 在表达式4中,L属于单一元素,所以添加$
# 在表达式5中,L后面跟上了非终结符M,所以添加First(M)
# 在表达式5中,从上得知,First(M)可以推导出空,所以此时M后面跟着什么,L后面就要跟着什么,所以添加Follow(M)
Follow(K)=$+Follow(M)=e,o,$
# 在表达式3中,K是单一字符,添加$
# 在表达式5中,M后面跟着什么,K后面就跟着什么,所以添加Follow(M)

注意:在书写Follow集中要时刻检查First集是否可以为空.

Select计算

分割表达式,如果非空则是First集,是空则为Follow集

Select(S→MH)=First(M)+First(H)+Follow(S)=b,d,e,o,$
# S以M开头,加入First(M)
# First(M)可以为空,加入First(H)
# M和H都可以为空,加入Follow(S)
Select(S→a)=a
# S只能推导出a,加入a
Select(H→LSo)=First(L)=e
# H以L开头,并且First(L)不可以为空,即加入First(L)
Select(H→ε)=Follow(H)=f,o,$
# H推导出空,加入Follow(H)
Select(K→dML)=d
# K以终结符d开头,加入d
Select(K→ε)=Follow(K)=e,o,$
# K可以为空,加入Follow(K)
Select(L→eHf)=e
# L以终结符e开头,加入e
Select(M→K)=First(K)+Follow(M)=d,e,o,$
# M可以推出K,加入First(K)
# First(K)可以为空,即M可以加入Follow(M)
Select(M→bLM)=b
# M可以推出以终结符b开头,加入b

判断是否是LL(1)文法

LL(1)文法就是同一非终结符推出来的Select集合相交为空,现在开始逐一判断

Select(S→MH)∩Select(S→a)
Select(H→LSo)∩Select(H→ε)
Select(K→dML)∩Select(K→ε)
# L只有一个表达式,省略L
Select(M→K)∩Select(M→bLM)

易知,上述表达式都为空,所以这个表达式是LL(1)文法

预测分析表的书写

先列出First集和Follow集的表格

FirstFollow
Sa,d,b,e, ε$,o
He,εf,o,$
Kd,εe,o,$
Lea,b,d,e,o,$
Mb,d,εe,o,$

然后将非终结符、终结符作为横纵行,填入表达式

以上是关于编译原理follow集与first集的计算的主要内容,如果未能解决你的问题,请参考以下文章

编译原理的follow集怎么求

编译原理: FIRST(x) FOLLOW(x) SELECT(x)的计算

编译原理: FIRST(x) FOLLOW(x) SELECT(x)的计算

编译原理: FIRST(x) FOLLOW(x) SELECT(x)的计算

编译原理 LL文法判别方法

编译原理 LL文法判别方法