但是,L'
Nullable 也将Follow(L)
包含Follow(C)
?
相反。Follow(C)
将包含Follow(L)
. 想想下面的句子:
...Lx...
其中 X 是某个终端,因此在Follow(L)
. 这可以扩展为:
...CL'x...
并进一步:
...Cx...
所以跟在L之后的,也可以跟在C之后。相反的不一定成立。
要计算以下,请考虑一个图,其中节点是 (NT, n),这意味着非终结NT
符的标记长度如下(在 LL(1) 中,n
为 1 或 0)。您的图表如下所示:
_______
|/_ \
(L, 1)----->(L', 1) _(C, 1)
| \__________|____________/| |
| | |
| | |
| _______ | |
V |/_ \ V V
(L, 0)----->(L', 0) _(C, 0)
\_______________________/|
其中(X, n)--->(Y, m)
表示长度为 的跟随n
,X
取决于长度m
为Y
(当然,m <= n
)的跟随。即计算(X, n)
,首先你应该计算(Y, m)
,然后你应该查看包含X
在右侧和Y
左侧的每个规则,例如:
Y -> ... X REST
将每个inREST
扩展为长度,然后将每个结果与集合中的每个跟随连接起来。您可以在计算 的第一个时计算扩展的内容,只需持有一个标志,说明是完全扩展为第一个还是部分扩展。此外,添加first of with length如下。例如:n - m
m
[0, n)
(Y, m)
REST
REST
REST
REST
n
X
S -> A a b c
A -> B C d
C -> epsilon | e | f g h i
然后找到长度为 3 的 B 的跟随(它们是e d a
和d a b
)f g h
,我们看一下规则:
A -> B C d
我们拿这个句子C d
,看看它可以产生什么:
"C d" with length 0 (complete):
"C d" with length 1 (complete):
d
"C d" with length 2 (complete):
e d
"C d" with length 3 (complete or not):
f g h
现在我们把这些和合并follow(A, m)
:
follow(A, 0):
epsilon
follow(A, 1):
a
follow(A, 2):
a b
follow(A, 3):
a b c
"C d" with length 0 (complete) concat follow(A, 3):
"C d" with length 1 (complete) concat follow(A, 2):
d a b
"C d" with length 2 (complete) concat follow(A, 1):
e d a
"C d" with length 3 (complete or not) concat follow(A, 0) (Note: follow(X, 0) is always epsilon):
f g h
这是我们正在寻找的集合。所以简而言之,算法变为:
- 创建跟随依赖关系图
- 找到连接的组件并从中创建一个DAG。
- 从末端(从没有任何依赖关系的节点)遍历 DAG,并使用上面的算法计算以下,事先计算好第一个。
值得注意的是,上述算法适用于任何 LL(K)。对于 LL(1),情况要简单得多。