【发布时间】:2013-03-18 11:20:30
【问题描述】:
我如何将 FIRST() 规则应用于生产,例如:
A -> AAb |抗体 | s
其中 A 是非终结符,b,s 是终结符。
备选方案 1 和 2 的 FIRST(A) 将再次成为 A,但由于我需要终端来获取 FIRST 集,因此这将导致 FIRST 的无限应用?
【问题讨论】:
标签: parsing compiler-construction grammar context-free-grammar ll
我如何将 FIRST() 规则应用于生产,例如:
A -> AAb |抗体 | s
其中 A 是非终结符,b,s 是终结符。
备选方案 1 和 2 的 FIRST(A) 将再次成为 A,但由于我需要终端来获取 FIRST 集,因此这将导致 FIRST 的无限应用?
【问题讨论】:
标签: parsing compiler-construction grammar context-free-grammar ll
要计算 FIRST 集,您通常执行定点迭代。也就是说,您从一小组值开始,然后迭代地重新计算 FIRST 集,直到这些集收敛。
在这种情况下,您首先要注意产生式 A → s 意味着 FIRST(A) 必须包含 {s}。所以最初你设置 FIRST(A) = {s}。
现在,您遍历 A 的每个产生式,并根据您迄今为止计算的 FIRST 集的知识更新 FIRST。比如规则
A → AAb
意味着您应该更新 FIRST(A) 以包含 FIRST(AAb) 的所有元素。这不会导致 FIRST(A) 发生变化。然后你访问
A → Ab
您再次更新 FIRST(A) 以包括 FIRST(Ab),这又是一个无操作。最后,您访问
A → s
而且由于 FIRST(A) 已经包含 s,这不会导致任何变化。
由于本次迭代没有任何改变,您最终会得到 FIRST(A) = {s},这确实是正确的,因为从 A 开始的任何推导最终都会产生一个 s 作为其第一个字符。
有关更多信息,您可能会发现these lecture slides 很有用(这里是part two)。他们详细描述了自顶向下解析的工作原理以及如何迭代计算 FIRST 集。
希望这会有所帮助!
【讨论】:
b 绝对不在 FIRST(A) 中。我所知道的用于计算 FIRST 集的算法的工作原理是为 FIRST 集播种所有从终端开始的产品,然后从那里开始。
A -> b 形式的规则播种 FIRST,但这还不够通用。但我投反对票的原因是,您建议在从A -> AAb 计算 FIRST 时,只需要查看第一个 A,这是错误的,因为虽然不是在这种情况下,但可能是 A =*=> ε,这将使FIRST(A) 包含b。请参阅我对 FIRST 的一般解决方案的回答。
我的teaching notes 是西班牙语,但算法是英语。这是计算FIRST的一种方法:
foreach a ∈ Σ do
F(a) := {a}
for each A ∈ N do
if A→ε ∈ P then
F(A) := {ε}
else
F(A) := ∅
repeat
for each A ∈ N do
F'(A) := F(A)
for each A → X1X2...Xn ∈ P do
if n > 0 then
F(A) := F(A) ∪ F'(X1) ⋅k F'(X2) ⋅k ... ⋅k F'(Xn)
until F(A) = F'(A) forall A ∈ N
FIRSTk(X) := F(X) forall X ∈ (Σ ∪ N)
Σ 是字母表(终端),N 是非终端的集合,P 是产生式(规则)的集合,ε 是空字符串,⋅k 是连接修剪到k 的地方。请注意∅ ⋅k x = ∅,连接两个集合会产生笛卡尔积中元素的连接。
手动计算FIRST组的最简单方法是每次算法迭代使用一个表。
F(A) = ∅
F'(A) = F(A) ⋅1 F(A) .1 F(b) U F(A) .1 F(b) U F(s)
F'(A) = ∅ ⋅1 ∅ ⋅1 {b} U ∅ ⋅1 {b} U {s}
F'(A) = ∅ U ∅ U {s}
F'(A) = {s}
F''(A) = F'(A) ⋅1 F'(A) .1 F'(b) U F'(A) .1 F'(b) U F'(s)
F''(A) = {s} ⋅1 {s} ⋅1 {b} U {s} ⋅1 {b} U {s}
F''(A) = {s} U {s} U {s}
F''(A) = {s}
我们已经完成了,因为 F' = F''、FIRST = F'' 和 FIRST(A) = {s}。
【讨论】:
您的语法规则有left recursion,正如您已经意识到的那样,LL 解析器有are not able to parse grammars with left recursion。
所以你需要先摆脱左递归,然后你应该能够计算出规则的第一组。
【讨论】: