Parsing 了解语法是否为LR(1)且没有解析表

Parsing 了解语法是否为LR(1)且没有解析表,parsing,context-free-grammar,lr,Parsing,Context Free Grammar,Lr,我发现了一个练习,它需要一个技巧来理解语法是否是LR(1),而不需要解析表操作 语法如下: S -> Aa | Bb A -> aAb | ab B -> aBbb | abb 你知道背后的诡计是什么吗 谢谢,:)假设您是一个LR(1)解析器,您刚刚阅读了aab,并对b进行了前瞻。(我知道,你可能在想“老兄,这种事一直发生在我身上!”)你到底应该在这里做什么 查看语法,你不能知道最初的产品是 Aa 还是 Bb < /代码>,所以你必须同时考虑 > 和 b>代码>的产生规则。如

我发现了一个练习,它需要一个技巧来理解语法是否是LR(1),而不需要解析表操作

语法如下:

S -> Aa | Bb
A -> aAb | ab
B -> aBbb | abb
你知道背后的诡计是什么吗

谢谢,:)

假设您是一个LR(1)解析器,您刚刚阅读了
aab
,并对
b
进行了前瞻。(我知道,你可能在想“老兄,这种事一直发生在我身上!”)你到底应该在这里做什么

查看语法,你不能知道最初的产品是<代码> Aa <代码>还是<代码> Bb < /代码>,所以你必须同时考虑<代码> > <代码>和<代码> b>代码>的产生规则。如果您查看

A
选项,您将看到这里的一个选项是减少
A
ab
,这在这里是合理的,因为前瞻性是a
b
,这正是您在展开
a
时看到
ab
后所期望的结果(请注意,有一条规则
a
aRb
,因此任何递归扩展的
A
s后面都会跟着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
s的数量。解析器在某个时候必须确定它是否喜欢
ab
A
或者它是否喜欢
abb
B
,但在做出决定之前,它无法同时看到
B
。这让我想到,我们希望找到某种冲突,在这种冲突中,我们已经看到了足够多的情况,知道发生了某种递归(因此,后面的
b
将导致问题),并找到两个产生式规则之间递归不同的地方