我发现了一个练习,它需要一个技巧来理解语法是否是LR(1),没有解析表操作。
语法如下:
S -> Aa | Bb
A -> aAb | ab
B -> aBbb | abb你知道背后的诀窍是什么吗?
谢谢:)
发布于 2016-07-01 21:17:58
假设您是一个LR(1)解析器,并且您刚刚阅读了aab,并且看上去比b更超前。(我知道,你可能在想“伙计,我一直都是这样!”)你到底应该在这里做什么?
从语法上看,您无法判断最初的生产是Aa还是Bb,因此您必须同时考虑A和B的生产规则。如果您查看A选项,您将看到这里的一个选项是减少A→ab,这在这里是有道理的,因为展望是一个b,而这正是您在展开A时看到ab后所期望的(注意,有规则A→aRb,所以任何递归扩展的A都将后面跟着b)。所以这就告诉你要减少。另一方面,看看B选项。如果你看到aab后面跟着一个b,你会想:“哦,第二个b要做aabb,然后我去减少B→abb,因为这完全是我喜欢做的事情,因为我是LR(1)解析器。”所以它告诉你要变换。就在这一点上,砰!您有一个移位/减少冲突,所以您几乎肯定不会有LR(1)语法。
那这真的发生了吗?那么,让我们来构建LR(1)配置集,如果我们确实读过aab,就会看到它,并将b看作是一种展望:
Initial State
S' -> .S    [$]
S  -> .Aa   [$]
S  -> .Bb   [$]
A  -> .aAb  [a]
A  -> .ab   [a]
B  -> .aBbb [b]
B  -> .abb  [b]
State after reading a
A  -> a.Ab  [a]
A  -> a.b   [a]
A  -> .aAb  [b]
A  -> .ab   [b]
B  -> a.Bbb [b]
B  -> a.bb  [b]
B  -> .aBbb [b]
B  -> .abb  [b]
State after reading aa
A  -> a.Ab  [b]
A  -> a.b   [b]
A  -> .aAb  [b]
A  -> .ab   [b]
B  -> a.Bbb [b]
B  -> a.bb  [b]
B  -> .aBbb [b]
B  -> .abb  [b]
State after reading aab
A  -> ab.   [b]
B  -> ab.b  [b]还有嘿!我们说的是转移/减少冲突。第一项在b上减少,第二项在b上移动,所以你就这样做了!我们的直觉使我们认为这不是LR(1)语法,如果我们查看表,证据就会得到数据的支持。
那你怎么知道要试试呢?嗯,一般来说,很难做到这一点。至少对我来说,最主要的线索是,解析器必须在某个时候猜测它想要的是A还是B,但它打破联系的方式是b的数量。解析器必须在某个时候决定它是否喜欢ab和A,或者喜欢abb和B,但在做出决定之前,它不能同时看到两者。这让我认为,我们希望找到某种冲突,在这种冲突中,我们已经足够地了解了某些递归的发生(这样,跟踪的b就会造成问题),并找到递归在两种生产规则之间不同的位置。
https://stackoverflow.com/questions/37485918
复制相似问题