LL(1)解析 - 第一个(A)具有递归的第一替代方案

时间:2013-03-18 11:20:31

标签: parsing compiler-construction grammar context-free-grammar ll

如何在生产中应用FIRST()规则,例如:

A - > AAb | Ab |小号

其中A是非终端,b,s是终端。

备选方案1&的第一个(A) 2将再次成为A,但是这将以FIRST的无限应用结束,因为我需要一个终端来获得FIRST集?

3 个答案:

答案 0 :(得分:1)

要计算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集。

希望这有帮助!

答案 1 :(得分:-1)

我的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是生产集(规则),ε是null字符串,⋅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}

答案 2 :(得分:-2)

您的语法规则已经实现了left recursion和LL解析器are not able to parse grammars with left recursion

所以你需要首先摆脱左递归,然后你应该能够计算规则的第一组。