compiler-construction - 将语法转换为 LL(1) 语法 : some problems

标签 compiler-construction grammar compiler-theory

这不完全是家庭作业,但与我的学习有关:

语法例如如下:

E -> E+E|E*E|-E|(E)|id

消除歧义后,它变成(从最低优先级运算符开始)

E->-F|F
F->F+G|G
G->G*H|H
H->(E)|id

删除左递归和左因子分解(本例中不需要)后,最终的 LL1 语法为:

E->-F|F
F->GF'
F'->+GF'|e
G->HG'
B->*HG'|e
H->(E)|id

这给出了一个工作正常的无错误解析器表。 现在关于我面临的问题,假设语法是这样的:

E -> E+E|E*E|id=E|(E)|id

现在我无法生成没有冲突的解析表,这意味着我的最终语法不是 LL1。步骤如下:

消除歧义后:

E->id=F|F
F->F+G|G
G->G*H|H
H->(E)|id

去掉左递归和左分解后,语法变成:

E->id=F|F
F->GF'
F'->+GF'|e
G->HG'
B->*HG'|e
H->(E)|id

但是解析器表中存在我无法删除的冲突,这意味着我错过了某些步骤,或者步骤中存在一些我无法找到的错误。请告诉我我做错了什么,以及如何解决这个问题。我已经研究这个问题很长时间了。

最佳答案

这么说吧:

E -> E+E|E*E|id=E|(E)|id

将变成:

E -> E+E|E*E|(E)|E'
E' -> id=E|id

然后你可以消除歧义和左手递归并得到:

E -> GF       FIRST(E) = FIRST(G)
F -> +GF|e
G -> HG'      FIRST(G) = FIRST(H)
G' -> *HG'|e
H -> (E)|E'   FIRST(H) = {(} + FIRST(E') = {(, id} 
E' -> idE''   FIRST(E') = {id}
E'' -> =E|e   FIRST(E'') = {=} + {#}

当然,问题是,您失去了给定的运算符优先级。

如果对于任何非终结符 N语法不会是 LL(1), 中将存在任何公共(public)元素 FIRST(N -> a)FIRST(N -> b) 对于 N -> aN -> bN 不同的产品。

如您所见,在任何其他位置添加生产 N -> id= 都会违反该规则

您可以创建一个 LL(2) 语法(但这可能不是您想要的),它可以在任何地方产生 id=E 产生式。 (FIRST2 集合由 2 元素字符串组成)。

此外,如果您再看一遍所提供的语法:

E -> E+E|E*E|id=E|(E)|id

我在上面的解决方案中设置的运算符优先级很有可能是适合实际应用的。看看吧!

关于compiler-construction - 将语法转换为 LL(1) 语法 : some problems,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9950819/

相关文章:

regex - 生成与某些输入集匹配的正则表达式是否是一个可解决的问题?

c - 编译器如何知道堆栈或堆上是否分配了某些内容?

c++ - Windows 8 中的开发人员 C : gcc Internal Error

c++ - 为什么函数参数名称在 C++ 声明中不重要?

c# - C#如何验证C#私有(private)定义?

scala - 语法、Scala 解析组合器和无序集

c - 英特尔 mpicc 链接器错误未定义对 `_mm_idivrem_epi32' 的引用

c++ - D 的语法真的是上下文无关的吗?

java - 在嵌入式DSL的语法中指定规则,如果编译器无法验证它?

java - Lambda 表达式如何转换成 Java 字节码