是否所有LL(1)文法都属于LALR(1)文法?LL(k)与LALR(k)关系咨询
LL(1)与LALR(1)文法的关系
先给你一个明确的结论:并不是所有LL(1)文法都是LALR(1)文法,有经典的反例可以证明这一点。
比如下面这个文法:
S → aAd | bBd | aBe | bAe A → ε B → ε
为什么它是LL(1)文法?
对于非终结符S的四个产生式:
First(aAd) = {a},First(bBd) = {b},First(aBe) = {a},First(bAe) = {b}
当输入符号是a时,我们可以通过后续的符号唯一确定产生式:- 若下一个符号是
d,则选择S→aAd - 若下一个符号是
e,则选择S→aBe
同理,输入b时也能通过后续符号精准匹配产生式,整个预测分析表没有冲突,所以它是LL(1)文法。
为什么它不是LALR(1)文法?
当构造LALR(1)的项目集时,合并同心项目后会出现归约-归约冲突:
- 项目
A→ε·, {d}和B→ε·, {e}会被合并到同一个项目集中,但当后续符号是d或e时,无法确定是归约A还是B,导致冲突。因此这个文法不是LALR(1)文法。
反过来,也存在LALR(1)文法不是LL(1)的情况,比如常见的左递归算术表达式文法:
E → E + T | T T → T * F | F F → (E) | id
它是LALR(1)文法,但因为存在左递归,不符合LL(1)文法的条件(LL(1)无法直接处理左递归,必须先消除),所以不是LL(1)文法。
LL(k)与LALR(k)的通用关系
LL(k)和LALR(k)都是基于k个向前看符号的文法,但两者的分析机制完全不同:
- LL(k)是最左推导的预测分析,核心是根据当前非终结符和k个向前看符号,唯一确定要使用的产生式
- LALR(k)是最右推导逆过程的归约分析,核心是根据当前状态和k个向前看符号,唯一确定是移进还是归约
它们的能力范围是部分重叠、互不包含的:
- 存在LL(k)文法不是LALR(k)的(比如上面的LL(1)反例,推广到k的情况也类似)
- 存在LALR(k)文法不是LL(k)的(比如左递归文法,LL(k)需要消除左递归才能处理,而LALR(k)可以直接支持)
- 当然也存在同时属于LL(k)和LALR(k)的文法,比如简单的变量声明文法:
D → type id,type → int | float
随着k的增大,两者的识别能力都会增强,但它们的能力边界始终不会完全覆盖彼此。
内容的提问来源于stack exchange,提问作者John Pence
相关产品推荐
相关产品推荐

