Parsing 手工计算第一组

Parsing 手工计算第一组,parsing,compiler-construction,grammar,Parsing,Compiler Construction,Grammar,我有一个小问题,困扰了我很长一段时间,我一直无法在网上找到合适的答案 给定语法: S=Sc | Eab | Db | b D=EDcD|ca| E=dE|DY Y=Ed|Dad|603 要找到第一组Y,那么第一(Y),我假设它是这样的,对吗 第一(Y) =第一(Ed)∪ 第一(爸爸)∪ 第一(ɛ) =第一(E)∪ (第一(D)段)∪ 第一(广告)∪ {ɛ} =第一(E)∪ (第一(D)段)∪ {a,ɛ} 现在的问题是如何找到第一(E)和第一(D) 所以,第一(E)和第一(D)的问题是,E和D相互

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

给定语法:

S=Sc | Eab | Db | b

D=EDcD|ca|

E=dE|DY

Y=Ed|Dad|603

要找到第一组Y,那么第一(Y),我假设它是这样的,对吗

第一(Y)

=第一(Ed)∪ 第一(爸爸)∪ 第一(ɛ)

=第一(E)∪ (第一(D)段)∪ 第一(广告)∪ {ɛ}

=第一(E)∪ (第一(D)段)∪ {a,ɛ}

现在的问题是如何找到第一(E)和第一(D)

所以,第一(E)和第一(D)的问题是,E和D相互参照。当你想要一个“最小不动点”时,通常的解决方案是——从所有的东西都是空的开始,不断迭代,直到它们稳定下来

即:首先,将所有第一个集合初始化为空集合。现在,重复地考虑每一个产品,假设你目前对非终端的第一组的估计是真实的。(事实上,它们通常是“低估的”。)计算出产品对第一组LHS的信息,并相应地更新您对该非终端的第一组LHS的估计。继续这样做,依次处理所有的制作,直到你完成了所有的制作并且你的估计没有改变。到那时,你就完了

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

所以,第一个(E)和第一个(D)的问题是,E和D相互引用。当你想要一个“最小不动点”时,通常的解决方案是——从所有的东西都是空的开始,不断迭代,直到它们稳定下来

即:首先,将所有第一个集合初始化为空集合。现在,重复地考虑每一个产品,假设你目前对非终端的第一组的估计是真实的。(事实上,它们通常是“低估的”。)计算出产品对第一组LHS的信息,并相应地更新您对该非终端的第一组LHS的估计。继续这样做,依次处理所有的制作,直到你完成了所有的制作并且你的估计没有改变。到那时,你就完了


在这种情况下,情况是这样的(当然,假设我没有搞错)。第一个过程依次产生S:{b},D:{c,ɛ},E:{c,D},Y:{c,D,ɛ}。第二个依次产生S:{b,c,d},d:{c,d,ɛ},E:{c,d,ɛ},Y:{c,d,ɛ}。第三种方法不会改变其中任何一种,因此这些都是最终答案。

这种先计算的方法是否总是为每个非U终端提供正确的第一组?或者我们应该只在两个非_终端相互引用的情况下使用此方法?如果没有两个非终端相互引用(直接或间接),那么相同的过程可以工作,更明显的是它可以工作:-)。想象一下,从每个符号(终端或非终端)到依赖于它的其他事物绘制一个箭头。如果没有依赖项的“循环”,那么所发生的事情就是正确的第一个集合沿着箭头传播,经过一段有限的时间,你跟随每个箭头,一切都停止了变化,一切都完成了。这种先计算的方法,是否总是为每个非_终端提供正确的第一个集合?或者我们应该只在两个非_终端相互引用的情况下使用此方法?如果没有两个非终端相互引用(直接或间接),那么相同的过程可以工作,更明显的是它可以工作:-)。想象一下,从每个符号(终端或非终端)到依赖于它的其他事物绘制一个箭头。如果没有依赖项的“循环”,那么所发生的事情就是正确的第一个集合沿着箭头传播,在有限的时间之后,你跟随每个箭头,一切都停止了变化,你就完成了。