LR解析如何在此语法中解析单词“ a b”:S-> a b |在 ; T-> a

问题描述

假设我有语法

S -> a b | a T
T -> a

很明显,语法接受{aa,ab}。但是我很困惑LR解析如何解析单词“ a b”。天真的,它可以这样工作,方法是将第一个“ a”减少为T,然后卡住或不得不回溯。

a a => T a => stuck or backtrack

LR解析器如何知道它不应该将第一个“ a”减少为T?

解决方法

在这种情况下,解析器将永远不会尝试减少T,因为生产T → a并未处于从S到达的任何状态。初始状态包含以下项目:

S → • a b
S → • a T

,在此状态下,唯一可能的动作是带有标记a的移位动作。由于a实际上是下一个输入字符,因此我们进行了转移到项目集为

的状态的转换。
S → a • b
S → a • T
T → • a

此状态也没有减少动作,它有两个不同的移位动作:一个在b上,另一个在a上。由于下一个输入是b,因此将执行该移位操作,从而导致项目集为

的状态
S → a b •

其中只有一个减少项。

一个更有趣的情况是语法非常相似

S → a b
S → T a
T → a

在此,初始状态的项目集确实包含T的生产:

S → • a b
S → • T a
T → • a

在初始状态下唯一可用的动作仍然是移a,但现在进行移位之后,我们发现自己处于项集为的状态:

S → a • b
T → a •

,现在我们有两个可能的操作:b的移位和T → a的减小。在这里,解析器需要使用其功能来展望未来的令牌(假设它是LR(1)解析器)。

但是要这样做,我们需要做一些小的调整。在构造解析自动机之前,始终对语法进行“增强”。增强语法通过添加唯一的输入结束字符(也可以参与超前检查)来添加对输入结束的显式识别。增强语法为:

S'→ S $
S → a b
S → T a
T → a

在此语法中,我们可以看到非终结符T后面只能加上符号a,并且此事实被编码到状态转换表中,其中项集中的每个项实际上是带有一组可能的先行注释。 (在表的构建过程中,所有项目都带有注释,但是在计算法律诉讼时,仅考虑减少的先行;减少是•末尾的项目。)

使用此修改,移a后到达的项目集为:

S → a • b
T → a •    [ lookahead: { a } ]

和前瞻性使您完全清楚应选择哪个操作。如果下一个输入是b,则将其移位。如果下一个输入是a,则会减少T

这种精度在LR(0)解析中不可用,其中不使用超前。正是由于您提到的原因,修改后的语法不是LR(0):它无法决定是否减少T。这个问题经常出现,这就是为什么LR(0)在实践中很少有用的原因。

,

给出示例输入“ a b” ...读取“ a”后,解析器处于以下各项的状态:

    S -> a . b
    S -> a . T
    T -> . a

由于这些项目在生产的最后都没有点号,因此该状态不要求执行任何减少动作。唯一可用的操作是移位,因此解析器将读取下一个符号。无需提前。