我不明白我的导师提供的一个例子。
实施例
S ::= aBA | BB | Bc
A ::= Ad | d
B ::= ε
我们有
FIRST(B) = FIRST(ε)
= {ε}
FIRST(A) = FIRST(Ad) ∪ FIRST(d)
= FIRST(A) ∪ {d}
= {d}
FIRST(S) = FIRST(aBA) ∪ FIRST(BB) ∪ FIRST(Bc)
= FIRST(a) ∪ (FIRST(B)\{ε}) ∪ FIRST(B) ∪ (FIRST(B)\{ε) ∪ FIRST(c)
= {a, ε, c}
为什么FIRST(S)计算中存在FIRST(B)?不应该是
(FIRST(B)\{ε)?
为什么FIRST(S)计算中缺少A?
答案 0 :(得分:8)
This page给出了导出FIRST(和FOLLOW)集的机械规则。我将尝试解释这些规则背后的逻辑以及它们如何应用于您的示例。
FIRST(u)
是可以在u
的完全推导中首先出现的终端集合,其中u
是终端和非终端的序列。换句话说,在计算FIRST(u)
集合时,我们只查找可能是可以从u
派生的字符串的第一个终端的终端。
根据定义,我们可以看到FIRST(aBA)
缩减为FIRST(a)
,然后缩减为a
。这是因为无论A
和B
制作是什么,终端a
将始终首先出现在aBA
派生的任何内容中,因为a
是终端,并且不能从该序列的前面删除。
我现在暂时跳过FIRST(BB)
并转到FIRST(Bc)
。这里的情况有所不同,因为B
是非终端的。首先,我们说FIRST(B)
中的任何内容都在FIRST(S)
中。不幸的是,FIRST(B)
包含导致问题的ε
,因为我们可能有方案
FIRST(Bc)
-> FIRST(εc)
= FIRST(c)
= c
其中箭头是可能的派生/减少。因此,一般而言,我们说FIRST(Xu)
ε
位于FIRST(X)
,(FIRST(X)\{ε}) ∪ FIRST(u)
等于FIRST(BB)
。这解释了计算中的最后两个术语。
使用上述规则,我们现在可以将(FIRST(B)\{ε}) ∪ FIRST(B)
推导为FIRST(BBB)
。同样,如果我们计算 FIRST(BBB)
= (FIRST(B)\{ε}) ∪ FIRST(BB)
= (FIRST(B)\{ε}) ∪ (FIRST(B)\{ε}) ∪ FIRST(B)
,我们会将其缩小为
S
-> BB
-> εε
-> ε
值得注意的是,在计算FIRST集时,符号序列中的最后一个符号永远不会从中删除空字符串,因为此时空字符串是合法的可能性。这可以从您的示例中的可能派生中看出:
FIRST(B)
希望您可以从上述所有内容中看到为什么FIRST(A)
出现在您的计算中,而{{1}}却没有。