LL(1)文法左因子提取疑问:我的改写与标准答案为何不同?
你的改写思路没问题,两种文法均符合LL(1)要求,只是递归形式不同
原始文法的核心问题
原始文法中Name → id | id.Name的两个产生式FIRST集均为{id},LL(1)分析器遇到id时无法确定选择哪个产生式,这是典型的左因子冲突,你的改写思路(提取左因子)完全正确。
你的改写分析
你给出的文法:
Addr → Name@Name.id Name → idName' Name' → epsilon | .Name
- 通过
Name → idName'提取了公共左因子id,直接解决了原始的左因子冲突; Name' → ε | .Name通过间接递归实现了Name的可选扩展,推导能力和原始文法完全一致(可生成id、id.id、id.id.id等结构);- 从LL(1)规则验证:
FIRST(.Name) = {.},FOLLOW(Name') = {@, .};- 输入符号为
.时,因.属于FIRST(.Name),选择Name' → .Name; - 输入符号为
@时,@不属于任何产生式的FIRST集,且@ ∈ FOLLOW(Name'),选择Name' → ε; - 无冲突,完全符合LL(1)文法要求。
给定答案的区别
给定答案的文法:
Addr → Name@Name.id Name → idName' Name' → epsilon | .idName'
- 同样提取了左因子,只是将你的间接递归
Name' → .Name改为直接递归Name' → .idName',避免了间接调用Name; - 推导能力和你的文法、原始文法完全等价,这种直接递归形式是左因子提取后的标准写法,分析器处理时更直观高效。
总结
你的理解没有错误,改写后的文法是合法的LL(1)文法,给定答案只是更简洁的直接递归版本,两者都正确。
内容的提问来源于stack exchange,提问作者young03600
相关产品推荐
相关产品推荐

