Parsing LR(k)到LR(1)语法转换

Parsing LR(k)到LR(1)语法转换,parsing,compiler-construction,bison,lr,Parsing,Compiler Construction,Bison,Lr,我对维基百科的以下内容感到困惑: 换句话说,如果一种语言足够合理,允许 高效的单通道解析器,可以用LR(k)语法来描述。 这种语法总是可以机械地转换成 等效(但较大)LR(1)语法。因此,LR(1)解析方法是, 理论上,它足够强大,可以处理任何合理的语言。在里面 实际上,许多编程语言的自然语法是 接近LR(1)。[需要引用] 这意味着,如果能够将LR(k)语法转换为LR(1)语法,那么解析器生成器(如bison)就非常强大(因为它可以处理LR(k)语法)。是否有一些这样的例子,或者如何做到这一点

我对维基百科的以下内容感到困惑:

换句话说,如果一种语言足够合理,允许 高效的单通道解析器,可以用LR(k)语法来描述。 这种语法总是可以机械地转换成 等效(但较大)LR(1)语法。因此,LR(1)解析方法是, 理论上,它足够强大,可以处理任何合理的语言。在里面 实际上,许多编程语言的自然语法是 接近LR(1)。[需要引用]


这意味着,如果能够将
LR(k)
语法转换为
LR(1)
语法,那么解析器生成器(如
bison
)就非常强大(因为它可以处理
LR(k)
语法)。是否有一些这样的例子,或者如何做到这一点的配方?我想知道这一点,因为我的语法中存在移位/减少冲突,但我认为这是因为它是
LR(2)
语法,并且希望将其转换为
LR(1)
语法。附带问题:
C++
是一种不合理的语言吗,因为我已经读过,
bison
生成的解析器无法解析它。

有关为
LR(k)
语法查找覆盖
LR(1)
语法的通用算法的参考,请参阅

通用算法产生相当大的语法;事实上,我非常确定生成的PDA与
LR(k)
PDA的大小相同。但是,在特定情况下,可以提出更简单的解决方案。不过,一般原则是适用的:您需要通过无条件地进行移位来推迟移位/缩减决策,直到可以使用单个前瞻令牌做出决策为止

一个例子:

如果不知道你语法的更多细节,我真的帮不了你

关于C++,使解析复杂的是预处理程序和解析(和词表)模板实例化中的一些角落情况。表达式的解析取决于符号的“种类”(而不是类型)(在符号出现的上下文中)这一事实使得bison的精确解析变得复杂。[1] “不合理”是一种我不愿意做出的价值判断;当然,工具支持(如精确的语法着色器和Tab完成器)可能是简单的,语法不同,但证据是,编写(甚至读取)好的C++代码并不难。


注:

[1] 经典的棘手解析(也适用于C)是
(a)*b
,如果
a
表示一个类型,则它是一个解引用的类型转换,否则就是一个乘法。如果您在上下文中编写它:
c/(a)*b
,很明显,在不知道它是铸件还是产品的情况下,无法构建AST,因为这会影响AST的形状

一个更为C++特有的问题是:
x(z)
(或
x(3)
),它根据
x
是否命名模板而进行不同的解析(和标记化)