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

时间:2013-12-19 14:01:50

标签: parsing compiler-construction bison lr

我对来自维基百科的以下quote感到困惑:

  

换句话说,如果一种语言足够合理,可以允许   有效的一次通过解析器,它可以用LR(k)语法描述。   而且这种语法总是可以机械地转化为一种语法   等效(但更大)LR(1)语法。所以LR(1)解析方法是,   从理论上讲,它足以处理任何合理的语言。在   实践,许多编程语言的自然语法是   接近LR(1)。[需要引证]

这意味着解析器生成器(如bison)非常强大(因为它可以处理LR(k)语法),如果能够将LR(k)语法转换为{LR(1)语法1}}语法。有一些这方面的例子,或者如何做到这一点的方法?我想知道这个,因为我的语法中有一个shift / reduce冲突,但我认为这是因为它是一个LR(2)语法,并希望将它转换为LR(1)语法。旁边的问题:C++是一种不合理的语言,因为我读过,bison - 生成的解析器无法解析它。

1 个答案:

答案 0 :(得分:1)

有关通用算法的参考资料,以查找LR(1)语法的覆盖LR(k)语法,请参阅Real-world LR(k > 1) grammars?

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

一个例子:Is C#'s lambda expression grammar LALR(1)?

在不了解有关语法的更多细节的情况下,我无法提供更多帮助。

关于C ++,使解析变得棘手的事情是预处理器和解析(和lexing)模板实例化的一些极端情况。表达式的解析依赖于符号的“种类”(不是类型)(在符号出现的上下文中)这一事实使得对野牛的精确解析变得复杂。 [1]“不合理”是一种我不太习惯的价值判断;当然,工具支持(如准确的语法着色器和制表符完成程序)使用不同的语法会很简单,但有证据表明编写(甚至读取)优秀的C ++代码并不困难。


注意:

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

更具C ++特色的问题是:x<y>(z)(或x<y<z>>(3))根据x是否为模板命名而对其进行不同的分析(并且可以说是标记)。