在语法分析的开始,LLR(1)是一个 从左到右 自上而下分析 的思路较为简单的算法。
但是细节上仍然可能会存在一些问题。
一、首先介绍一下First集
First集看名字我们大致也知道是第一个非终结符号。
-非终结符号的第一个非终结符号:E->abc,那么First(E)=a
-First集中的非终结符号包括ε空串
--比如E->abc|ε,那么First(E)={a,ε}
①如果F->Ed,如果First(E)={a,ε},如果E恰好取ε,那么F的首项就变为d,此时First(F)={a,d}
②如果F->ED,如果First(E)={a,ε},现在我们只看E取ε时,现在D也是非终结符号,E=ε时F的首项就要看First(D),假若First(D)={d,ε},那么First(F)={a,d,ε}。如果类似地有多个非终结符符号,那么如果取空时一直向后推直至不能推为止。
二、然后我们再看Follow集
Follow集就是非终结符后面的第一个终结符号
-Follow集中的终结符不包括ε空串
①如果E是文法开始符号,E->Fa, 那么$终止符属于Follow(E). 而且从E->Fa可以看出a∈Follow(F)
②如果E->aF,那么Follow(E)也属于Follow(F)
③既然Follow集中的终结符不包括ε空串,那么如果发生E->FB。那么Follow(F)就是First(B),假若First(B)={a,ε},那么如果取ε时那么此时相当于E->F那么同②。当然如果后面还存在一个终结符号那么就是终结符号了。
三、LL1
可能会遇到的问题:
①LL1是从左到右,自上而下也就是从文法开始推导,那么势必不能有左递归。
②首字符冲突。E->ab|ac
解决上面问题的办法分别就是 等价替换 和提取公因子,比如E->ab|ac,就变成了E->aF,F=b|c
然后就是构造分析表
结合First和Follow集就出现了Select集。就是为了描述一串规则的首非空终结符。
比如A->α,α不确定是否有ε
①如果α不含ε,那么Select(A)=First(α)
②如果α含ε,那么Select(A)=First(α)/{ε} ∪ Follow(A)。也就是A->ε时,就要看Follow(A),即A后面的终结符。
四、例子
上面两个推导箭头,左边是消除左递归之后的,右边是原先存在左递归的原式
由上面介绍的求出First和Follow集。比如求Follow(T)时,T后面是E',那么就应该是First(E')/{ε},当E'=>ε时,E->T,此时Follow(E)∈Follow(T);E'->+T, Follow(E')属于Follow(T)。其他同理。
此时相当于求Select集,就是求一串规则遇到的首个非空终结符.
比如E'->ε,那么此规则遇到的首个非空终结符 就只能是Follow(E')即E'后面的
LL1分析表就是将上面整理成二维表即可,空的格子是报错。
在用栈分析时,首先$压栈底,接着把开始符号E压栈,再从左到右扫描待输入字符串。查表用相应的规则替换即可,如果替换规则的时候要逆序入栈,意思就是保持和待输入字符串能从左到右的顺序比较,遇到相同的就消去不同的就查表。直至栈中就一个$,待输入串中就一个$才算成功。