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

use*_*108 6 compiler-construction parsing bison lr-grammar

我对维基百科的以下引用感到困惑:

换句话说,如果一种语言足够合理以允许高效的单遍解析器,则它可以由 LR(k) 语法来描述。并且该语法总是可以机械地转换为等效(但更大)的 LR(1) 语法。因此,从理论上讲,LR(1) 解析方法足以处理任何合理的语言。在实践中,许多编程语言的自然语法接近 LR(1)。[需要引用]

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

ric*_*ici 3

有关找到语法LR(1)的覆盖语法的通用算法的参考LR(k),请参阅现实世界 LR(k > 1) 语法?

通用算法产生相当大的语法;事实上,我非常确定最终的 PDA 与实际的 PDA 大小相同。LR(k)PDA 的尺寸相同。然而,在特定情况下,可以提出更简单的解决方案。不过,一般原则是适用的:您需要通过无条件移位来推迟移位/归约决策,直到可以使用单个前瞻标记做出决策。

举个例子:C# 的 lambda 表达式语法是 LALR(1) 吗?

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

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


笔记:

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

一个更特定于 C++ 的问题是:x<y>(z)(或x<y<z>>(3)) 根据是否x命名模板而进行不同的解析(并且可以说是标记化)。