编译原理 LL(1)文法

复习

为了构建语法树(目的)我们采用了自顶向下的语法分析(方法),深度优先地创建各个节点。这其中我们讨论到非递归向下的语法分析,需要借助预测分析表来实现。所谓LL(k)文法,就是构造出向前看k个输入符号的预测分析器。这一节讨论向前看1个输入符号的LL(1)文法。

FIRST函数

  • 定义:FIRST(α)表示可从α推导得到的串的首符号的集合。其中α为任意的文法符号串(非终结符,终结符,空串e)。特别地,如果α=>*e,那么e也在FIRST(α)中。
  • 目标:求出每个非终结符的FIRST集合。
  • 求FIRST(X)的方法:(顺带提一句,笔者认为这种东西最好的记忆方法就是把自己当成计算机,给自己写个程序调用一下,可能是计算机学傻了hh)
//Step1
if(X为终结符)
	FIRST(X)={X};
//Step2	
if(X为非终结符 && X->Y1Y2Y3...Yk && k>=1)
{
	if(i<k && a属于FIRST(Yi) && 空串e属于FIRST(Y1),FIRST(Y2)...FIRST(Y-1))	
	{
		FIRST(X).append(a);
	}	
	else if(i==k)
	{
		FIRST(X).append(空串e);
	}
}
//也就是说,对于一个表达式 X->Y1Y2...Yk, 先把 FIRST(Y1)的所有符号加入FIRST(X),再继续往后观察FIRST(Y2)...
//如果有空串e属于FIRST(Y2)...那就将FIRST(Y2)...的所有符号全部加入FIRST(X)直到某个FIRST(Yi)
//不含空串e或者FIRST(Yk)也含空串那就把空串e也加进去。

//Step3
if(X->空串e是一个产生式) append(e);

举例:
在这里插入图片描述
这里有个技巧,因为X为终结符和X->空串e的规则都很简单,所以我们要关注第二条规则,尽量按照第二条规则中可能会出现的串的顺序依次求其FIRST集合。比如,上例中的文法求FIRST(S),按照规则二要分别求FIRST(B)、FIRST(S),FIRST(A)、FIRST(S),故最好先求下面两个的FIRST集合。这个例子还太过简单,不是很明显。

FOLLOW函数

  • 定义:FOLLOW(A)表示可能在某些句型中紧跟在A右边的终结符号的集合。
  • 目标:求出每个非终结符的FOLLOW集合。
  • 求一个文法的所有FOLLOW(A)的方法:
//Step1
if(A是开始符) FOLLOW(A).append(结束标记$);
//Step2
if(存在句型A->αBβ)
{
	FOLLOW(B).append(FIRST(β)中所有非空的符号);
	if(FIRST(β)包含空串e) FOLLOW(B).append(FOLLOW(A)中的除了空串的所有符号);
}
//Step3
if(存在句型A->αB) FOLLOW(B).append(FOLLOW(A)中的所有符号);

以上规则显得有些乱。需要理清楚的是,这个规则更倾向于求一个文法的所有FOLLOW集合的步骤。除了第一步,将开始符的FOLLOW集合中放入结束标记$,之后我们所做的工作就是不断对每一个非终结符推出的每一条文法进行规则中两种句型的识别,不断更新每个非终结符的FOLLOW集合。求FOLLOW集合的前提是先求FIRST集合。由于第二第三条规则的存在,求的时候最好先求出句型A->αBβ的左边的非终结符的FOLLOW集合,因为B会包含FOLLOW(A)。

举例:
在这里插入图片描述
除了开始符,我们要做的就是对右侧的所有产生式进行三条规则的遍历(当然还是要先确定对哪个非终结符,然后在右侧的产生式中寻找带有该终结符的所有产生式调用三个规则)。遍历结束我们的FOLLOW集合应该也就都求好了。

构建预测分析表

有了前面对于FIRST和FOLLOW函数的准备,我们就可以着手实现预测分析表。构造预测分析表需要对该文法G的每一条产生式进行遍历。
对于每一条产生式A->α:

  • 计算FIRST(α),对于FIRST(α)中的每一个终结符号a(排除空串e)把A->α添加到M[A,a]。
  • 如果空串e在FIRST(α)中,对于FOLLOW(A)中的每个终结符号b(排除空串),把A->α添加到M[A,b]。
  • 如果空串e在FIRST(α)中,且$在FOLLOW(A)中,也将A→α加入到M[A,$]。

举例:对于上文提到的文法,构建预测分析。
在这里插入图片描述

LL(1)文法

  • LL(1)文法:可以构造出预测分析器,即不需要回溯的递归下降语法分析器。第一个L,从左至右(left)扫描输入;第二个L,表示产生最左推导;1表示每步只需要看1个lookahead符号。也就是说,预测分析表中的每一个空最多只可能有一条产生式,这样避免了出现多条产生式后需要用回溯法的效率低问题。
  • 任何两个产生式A->α|β 都满足下列条件:
    FIRST(α)∩FIRST(β) = ∅;不能有左公因子。
    若β==>*e,那么FIRST(α)∩FOLLOW(β) = ∅。构造预测分析表的时候不会出现一个空两产生式的情况。
  • 性质:
  1. 没有公共左因子,如果有左公因子,那么一定不是LL(1)文法。
  2. 不是二义的,如果有二义性, 那么一定不是LL(1)文法。
  3. 不含左递归,如果有左递归, 那么一定不是LL(1)文法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值