Compiler construction 将语法转换为LL(1)语法:一些问题

Compiler construction 将语法转换为LL(1)语法:一些问题,compiler-construction,grammar,compiler-theory,Compiler Construction,Grammar,Compiler Theory,这不完全是家庭作业,但与我的学习有关: 例如,语法如下: E->E+E | E*E |-E |(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)| i

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

例如,语法如下:

E->E+E | E*E |-E |(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'') = {=} + {#}
当然,问题是,您失去了给定的运算符优先级

语法不会是LL(1)如果对于任何非终结符
N
,在
FIRST(N->a)
FIRST(N->b)
中有任何公共元素,对于
N->a
N->b
是与
N
不同的产物

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

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

此外,如果您再看一次呈现的语法:

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

这是一个很高的机会,我在上面的解决方案中的运算符优先级是适合实际应用的。看看

一元减号运算符的优先级不是最低的,它在其他二元运算符上总是最高的
E -> E+E|E*E|id=E|(E)|id