【问题标题】:Follow sets Top-Down parsing跟随集合自顶向下解析
【发布时间】:2014-05-08 10:55:35
【问题描述】:

我对遵循以下规则有疑问:

L -> CL'
L' -> epsilon
       | ; L
C -> id:=G
      |if GC
      |begin L end

我计算出Follow(L)Follow(L') 中。 Follow(L') 也在 Follow(L) 中,所以它们都将包含:{end, $}。但是,由于 L' 可以为 Nullable,Follow(L) 是否也包含 Follow(C)

我计算出Follow(C) = First(L')Follow(C) subset Follow(L) = { ; $ end}

在答案中Follow(L)Follow(L') 仅包含{end, $},但它不应该包含; 以及Follow(C) 中的L' 可以为空吗?

谢谢

【问题讨论】:

    标签: parsing compiler-construction ll


    【解决方案1】:

    但是,由于L' 是可空的,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) 表示X 的长度为n 的跟随,取决于Y 的长度为m 的跟随(当然,m <= n)。也就是计算(X, n),首先你应该计算(Y, m),然后你应该查看每个包含右侧X和左侧Y的规则例如:

    Y -> ... X REST
    

    对于[0, n) 中的每个m,将REST 扩展为长度n - m,然后将每个结果与(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 ad a bf 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
    

    这是我们要找的系列。所以简而言之,算法就变成了:

    • 创建跟随依赖关系图
    • 找到connected components 并从中创建一个DAG
    • 从末端(从没有任何依赖关系的节点)遍历 DAG,并使用上面的算法计算以下,预先计算出第一个。

    值得注意的是,上述算法适用于任何 LL(K)。对于 LL(1),情况要简单得多。

    【讨论】:

    • '告诉我詹姆斯:你还睡在枕头下的龙书吗? +1 清晰、详细。
    • @user1666959,度过了很多个夏夜crafting these algorithms
    • @user1666959 另外,我找不到那个报价,它来自哪里?
    • “明日永不死”,Paris Carver (Tery Hatcher) 在派对上告诉 Bond,稍微改写一下,承认你对编译器构造的了解可能与 Bond 对他的 Walther PPK 的了解一样多。
    • @user1666959,感谢您的补充和信息;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多