目录
一、说明
含有左公因子、左递归的文法一定不是LL(1)文法
因此要想实现某些非LL(1)文法到LL(1)文法的转变,需要设法消除左公因子与消除文法中的左递归
1、什么是左公因子、左递归
(1)左公因子
同一个非终结符不同产生式右部的第一个相同的终结符
例如:A→ab | ac a为显式左公因子 A→Bb|a B→a a为隐式左公因子
而A→ba|ca 中 a不是左公因子
(2)左递归
非终结符产生式右侧第一个字符是非终结符本身
例如:S→Sa 直接左递归
S→Ba B→Sa 间接左递归
2、含有左递归不是LL(1)文法的原因
例如:S→Sa|b
FIRST集 | SELECT集 | |
S→Sa S→b | {b} {b} | {b} {b} |
SELECT(S→Sa)∩SELECT(S→b)={b}∩{b}=b
∵同一个非终结符的SELECT集交集不为空
∴不是LL(1)文法
3、含有左公因子不是LL(1)的原因
例如:S→ba|b
FIRST集 | SELECT集 | |
S→ba S→b | {b} {b} | {b} {b} |
同样,因为同一个非终结符的SELECT集交集不为空,所以不是LL(1)文法
二、方法
技巧:无论是提取左公因子还是消除左递归,其本质上都是引入一个非终结符
1、消除左公因子
(1)显式左公因子
例如:A→ab | ac
①提取左公因子
A→a(b|c) 其中:()为元符号,而并非终结符
②左公因子保留,非左公因子引入新的非终结符替换
另A'→b | c,则A→aA'
即,该文法消除左公因子后的结果为
A→aA'
A'→b | c
③说明
正规文法可等价变换为正规式
正规文法是指 左边只有一个非终结符,而右边为任意符号
(2)隐式左公因子
例如:
A→Bd
A→a
B→aA
①代入
A→aAd
A→a
②提取左公因子
A→a(Ad|ε)
③左公因子保留,非左公因子引入新的非终结符替换
A→aA'
A'→Ad|ε
为该文法消除左公因子后的结果
2、消除左递归
(1)直接左递归
例如:S→Sa|b
①正规式表达为闭包(*)的形式
闭包:字符重复0~n次
S→ba*
②非闭包保留,闭包替换
S→bS'
S'→a*
③造闭包产生式的右递归
S'→aS'|ε 即:S'=>aaS'=>aaaS' ......直到S'被替换为空
④综上
该文法消除左递归后的结果为
S→bS'
S'→aS'|ε
(2)间接左递归
例如:
A→aB
A→Bb
B→Ac
B→d
①代入
B→aBc
B→Bbc
B→d
②正则表达式表达为闭包
B→(aBc|d)(bc)*
③非闭包保留,闭包替换
B→(aBc|d)B' ,即B→aBcB'| dB'
B'→(bc)*
④造闭包的右递归
B'→bcB'|ε
⑤综上
该文法消除左递归后的结果为
B→aBcB'| dB'
B'→bcB'|ε