【问题标题】:Calculating FIRST sets by hand手动计算 FIRST 组
【发布时间】:2012-07-19 01:19:39
【问题描述】:

我有一个小问题困扰了我很长一段时间,我一直无法在网上找到合适的答案。

给定一个语法:

S = Sc | Eab | Db | b
D = EDcD | ca | ɛ
E = dE | DY
Y = Ed | Dad | ɛ

要找到第一组说 Y,所以 FIRST(Y),我是否正确假设它是这样的:

FIRST(Y)
= FIRST(Ed) ∪ FIRST(Dad) ∪ FIRST(ɛ)
= FIRST(E) ∪ (FIRST(D)\{ɛ}) ∪ FIRST(ad) ∪ {ɛ}
= FIRST(E) ∪ (FIRST(D)\{ɛ}) ∪ {a, ɛ}

现在的问题是如何找到 FIRST(E) 和 FIRST(D)?

【问题讨论】:

    标签: parsing compiler-construction grammar


    【解决方案1】:

    因此,FIRST(E) 和 FIRST(D) 的问题在于 E 和 D 相互引用。当您想要一种“最小固定点”时,解决方案是通常的解决方案 - 从所有内容都为空开始并不断迭代直到它们稳定。

    即:首先,将所有 FIRST 集初始化为空集。现在,反复考虑每个产品,并假设您当前对非终端的 FIRST 集的估计是真实的。 (实际上,它们通常会“低估”。)计算出产品告诉您的有关其 LHS 的 FIRST 集的内容,并相应地更新您对该非终端的 FIRST 集的估计。继续这样做,依次处理所有产品,直到您完成所有产品并且您的估计没有改变。至此,您就完成了。

    在这种情况下,事情是这样的(当然,假设我没有犯错)。第一遍依次产生 S: {b}, D: {c,ɛ}, E: {c,d}, Y: {c,d,ɛ}。第二个依次产生 S: {b,c,d}, D: {c,d,ɛ}, E: {c,d,ɛ}, Y: {c,d,ɛ}。第三个并没有改变任何这些,所以这些是最终的答案。

    【讨论】:

    • 这种计算 FIRST 的方法是否总是为每个非终端提供正确的 FIRST 集?或者我们应该只在两个非终端相互引用的情况下使用这种方法?
    • 如果没有两个非终结符曾经相互引用(直接或间接),那么同样的过程可以工作,而且更明显的是它可以工作:-)。想象一下,从每个符号(终端或非终端)到依赖它的其他事物绘制一个箭头。如果你没有依赖的“循环”,那么会发生正确的 FIRST 集合沿着箭头传播出去,并且在有限的时间长度之后,你跟随每个箭头并且一切都停止了变化,你就完成了。跨度>
    猜你喜欢
    • 1970-01-01
    • 2014-07-17
    • 2017-07-17
    • 2018-12-21
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    • 2021-04-05
    相关资源
    最近更新 更多