Parsing 了解语法是否为LR(1)且没有解析表
我发现了一个练习,它需要一个技巧来理解语法是否是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>代码>的产生规则。如
S -> Aa | Bb
A -> aAb | ab
B -> aBbb | abb
你知道背后的诡计是什么吗
谢谢,:)假设您是一个LR(1)解析器,您刚刚阅读了aab
,并对b
进行了前瞻。(我知道,你可能在想“老兄,这种事一直发生在我身上!”)你到底应该在这里做什么
查看语法,你不能知道最初的产品是<代码> Aa <代码>还是<代码> Bb < /代码>,所以你必须同时考虑<代码> > <代码>和<代码> b>代码>的产生规则。如果您查看
A
选项,您将看到这里的一个选项是减少A
→ ab
,这在这里是合理的,因为前瞻性是ab
,这正是您在展开a
时看到ab
后所期望的结果(请注意,有一条规则a
→ aRb
,因此任何递归扩展的A
s后面都会跟着Ab
)。所以这告诉你要减少。另一方面,请查看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
将导致问题),并找到两个产生式规则之间递归不同的地方