理解语法是否是没有解析表的LR(1)

时间:2016-05-27 14:24:00

标签: parsing context-free-grammar lr

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

语法如下:

public static void installMouseMotionListenerOnAll(Component c, MouseMotionListener mml) {
  c.addMouseMotionListener(mml);
  if (c instanceof Container) {
    for (Component child : ((Container)c).getComponents()) {
      installMouseMotionListenerOnAll(child, mml);
    }
  }
}

你知道背后的诀窍是什么?

谢谢,))

1 个答案:

答案 0 :(得分:1)

想象一下,你是一个LR(1)解析器,而你刚刚读过aab并且前瞻b。 (我知道,你可能在想“男人,这一直发生在我身上!”)你究竟应该在这做什么?

查看语法,您无法判断初始制作是Aa还是Bb,因此您必须同时考虑A的制作规则以及B。如果您查看A选项,您会看到此处的一个选项是减少Aab,这在这里是合理的,因为前瞻是b这正是您在展开ab后看到A后所期望的结果(注意有规则AaRb,所以任何递归扩展A之后会有b。所以这告诉你减少。另一方面,请查看B选项。如果您看到aab后跟b,那么您会想到“哦,那第二个b将会aabb,然后我会去减少Babb,因为这是我喜欢做的事情,因为我是LR(1)解析器。“所以这告诉你转移。那时,bam!你有一个转换/减少冲突,所以你几乎肯定不会有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)语法,如果我们查看表格,数据就支持证据。

那你怎么知道尝试呢?嗯,总的来说,这很难做到。对我来说,主要的提示是,解析器必须在某个时候猜测它是否需要AB,但它的抢先方式是b s的数量。解析器必须在某个时刻确定它是否喜欢ab并与A一起使用,或者它是否喜欢abb并与B一起使用,但它可以在做出决定之前,不要看到b两个。这让我觉得我们想找到某种冲突,我们已经看到足够的知道发生了一些递归(以便尾随b会引起问题)并找到一个地方递归在两个生产规则之间会有所不同。