LL(1)型文法的改造及预测分析(实验)

题目描述

1.对文法进行LL(1)判别,若不是LL(1)型文法,则进行等价变换。构造预测分析表。
2.编程实现预测分析表

分析

在拿到我们自己的文法后,首先要对自己的文法进行LL(1)型判别,判别的方法有以下两种。

1.判断是否有左递归
2.判断是否有左公因子

  • 左递归和左公因子的是啥东西将会在下面进行解释

如果你的文法中有左递归或左公因子,就可以说明你的文法并不是 LL(1)型 文法,需要进行等价变换。

左递归

递归是什么意思呢? 递归在程序设计语言中就是:有一个函数名字为fn(),在这个函数的内部调用了自己的函数,例如下面的代码。

void fn() 
{
	fn()
}

这段代码就用到了递归,从这段代码可以看出,如果不加一个限制条件,那么该段代码将会进入一个死循环,没有终止。这肯定会导致系统的崩溃,在文法中也一样。

在文法中,左递归分为直接左递归和间接左递归

直接左递归

我们来看这样一组文法

在这里插入图片描述
在这个文法中,箭头的左边和右边都有A,这就说明左边的A可以一直推导出右边的A,如果不加限定条件,则进入死循环。
在这里插入图片描述

这里需要注意,只有A在最左边的时候才是左递归,如果A -> aA | b,则不为左递归,因为在预测分析中,每次替换的都是最左边的那个非终结符

如果你的文法中存在类似的情况,则说明需要进行等价变换。方法如下。

等价变换的结果就是得到消除该文法的左递归,但是由消除左递归后的文法推出来的式子必须与消除前一致。

例如上述文法
在这里插入图片描述
该文发的右边部分有一个符号’|',这个符号的是或的意思,也就是说A既可以推出Aα,也可以推出β,如果不使该文法陷入死循环,那么该文法的最后一个推导一定是A -> β,因为只有进行到A -> β,推导才会结束,因为推导时,只能选择Aα和β这两者中的一个,没有被选择的将会被抛弃。
上面的文法,最后一定得到的是下面这个式子
在这里插入图片描述
所以说等价变换得到的文法,最后也应该可以推出来βα…α这个式子。

消除直接左递归的方法

因为由A -> Aα | β 这个式子得出的最终推导结果为βα…α,所以消除左递归的文法也能得到βα…α,由βα…α可以看出,在结果中一定有一个β,并且β的位置排在第一个,然后后面紧跟着n个α,从这可以看出有两部分,一部分是β的,一部分是n个α的,然后给大家看一下消除左递归等价变换的例子。应该可以看明白,很简单。

A -> Aα | β  		 //这是原来的文法不用管他,下面的是方法

A -> β A'
A' -> α A' | e          //因为输入打不出来伊布西龙,这里用e代替

这俩就是等价变换后的文法

A -> β A'
A' -> α A' | e 

其实这里的α和β就是一个标记,他可以表示1个或多个字母,例如下面的这几个例子


消除前
在这里插入图片描述
消除后
在这里插入图片描述


消除前
在这里插入图片描述
消除后
在这里插入图片描述


消除直接左递归的一般形式

在这里插入图片描述

间接左递归

直接左递归是进行一步推导时就会面对递归的问题,而间接左递归就是进行两步以上推到时会出现左递归的问题。例如

S -> Aa | b
A -> Ac | S d | e

这里就出现了间接左递归,大家看第二个式子中出现了Sd,则将S展开写会出现以下情况

S -> Aa
   -> Sda

第二行出现了递归,所以这种情况称为间接左递归,那么如何消除呢?下面说方法
1.将S的定义带入到A的式子中
2.消除A的左递归

// 1.将S的定义带入到A的式子中,得
A → A c | A a d | b d | ε
// 2.消除A的左递归,得
A → b d A’ | A’
A’ → c A’ | a d A’ | ε

这样就将间接左递归消除完毕了

左公因子

左公因子是啥呢?其实就是咱们数学中学的公因式,比如 ab + ac + ad = a(b+c+d)这里得a就是公因子。那么在文法中是下面的这种情况。

S -> aAd | aBe

看到没,aAd和aBe这俩都有a,所以a是它俩的公因子,但是在文法里我们叫它左公因子。
如何让消除呢?很简单,和数学一样,就是提取公因式,下面是例子。

S -> aAd | aBe
将a提出来
S -> aS'
S' -> Ad | Be

这样我们就将文法改造好了。

预测分析表

预测分析表是代码里比较重要的一项,大家一定要写对,然后再去调程序啊!!!

下面来说一说预测分析表怎么求吧
1.求First集和Follow集
2.求SELECT集
3.根据SELECT集构造分析表

FIRST集和FOLLOW集

点我即可进入first集和follow集的网站

进入网站之后点击它
在这里插入图片描述

进入之后,输入你等价变换后的文法,点击提交即可。
注意:输入的时候一定要注意,每个字符直接都要有空格,括号一定要为英文状态下的括号,否则会出错
在这里插入图片描述

提交后得到first集和follow集
在这里插入图片描述

SELECT集

SELECT集是根据FIRST集和FOLLOW集求出来的,所以大家一定要先得出正确的文法,然后得出正确的FIRST集和FOLLOW集,进而求得SELECT集。下面以如下表所示的FIRST集和FOLLOW集来演示如何求SELECT集。

下表所示FIRST集和FOLLOW集的文法是

G:	
	M -> HM'
	M' -> aHM' |  ε
	H -> bH' | ( M )
	H' -> ( M ) |  ε
标识符FIRST集FOLLOW集
Mb ($ )
M’a ε$ )
Hb (a
H’( εa

我们在求SELECT集之前需要将产生式中的|去掉,也就是说把|的左边和右边全都单独的写成一个式子,例如上边的文法去掉|后变成如下文法

M -> HM'
M' -> aHM'
M' ->  ε
H -> bH'
H -> ( M )
H' -> ( M )
H' ->  ε

为了解说方便,我直接将本题的SELECT给到大家

(1)M -> HM'				SELECT(1) = {  b (  }
(2)M' -> aHM'				SELECT(2) = {  a 	}
(3)M' ->  ε				SELECT(3) = {  $ )  }
(4)H -> bH'				SELECT(4) = {  b   	}
(5)H -> ( M )				SELECT(5) = {  (   	}
(6)H' -> ( M )				SELECT(6) = {  (    }
(7)H' ->  ε				SELECT(7) = {  a    }

**注意序号!!!**

三个规则
1.如果->右边的第一字符是小写字母或者任意的符号,如a,b,左括号(,右括号),加号+,星号*, 那么直接将它放入对应的SELECT集中,例如(2)、(4)、(5)、(6)
2.如果->右边只有ε,那么将->左边的字母的FOLLOW集中的所有东西(去查表)放入那一行的SELECT集中,如(3)、(7)。M’的FOLLOW集是$ 和 ),所以将$和)放入SELLECT(3)中。
3.如果->右边的第一个字符是大写字母,则将改大写字母的FIRST集中的所有东西,放入那一行的SELLECT集中。如(1),H的FIRST集为b和(,所以将b和(,放入SELLECT(1)中

构造预测分析表
在这里插入图片描述
这张表是由上边求得的SELECT集转化而来的,至于如何转化的大家应该一目了然,这里就不详细说了,大致意思就是先将SELECT集中的字符写到输入符号下方,然后把->左边的那些大写字母写到非终结符那一列,然后一行一行填表即可。比如我们先看第一行(非终结符为M的这一行),去上边->左边字母为M的式子

(1)M -> HM'				SELECT(1) = {  b (  }

先看SELECT(1),里边有 b 和 ( ,意思就是,当非终结符M遇到输入符号为 b 或( 时,他的产生是为
M -> HM’ 所以将M -> HM’ 填入预测分析表中M那一行的 b 列和 ( 列。其余的做法都一样。很简单!!!

如何改代码呢

打开老师提供的代码,我们需要以下这些地方。
1.先将你的文法中的|去掉,如何去掉,上面已经说过。
2.找到这个地方

在这里插入图片描述
VT[20] = {这里改成你自己的文法中的终结符(终结符就是一些小写字母或者一些符号)}
VN[20] = {这里改成你自己的文法中的非终结符(大写字母)}

在这里插入图片描述

把结束符号改成你自己的,原来的是#,其实#或$都可以,不改也无所谓。

4.在这里插入图片描述
在这里插入图片描述
将这部分改成你自己的
注意:如果你的文法中有像H’这样的内容,需要将H’用别的字母来替换,改成W或者Z啥的都可以

在这里插入图片描述
将这个也改为你自己的,这个地方是根据预测分析表改的[ ][ ]这个指的是第几行第几列
在这里插入图片描述
根据自己的表填写即可。


大家如何有任何疑问都可以直接联系我或者在评论区留言

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张居然的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值