C# 和 Java 语法是 LALR(x) 吗?

Are C# and Java Grammars LALR(x)?

提问人:TonySalimi 提问时间:12/5/2011 最后编辑:TonySalimi 更新时间:12/20/2011 访问量:3721

问:

我想知道 C# 和 Java 语法是否是 LALR(x)?如果是,x 的值是多少?

编辑:

在接受了真实的答案之后,我认为最好这样改变Q:

是否有任何 LALR(x) 解析器可以解析当前版本的 Java(版本 7)或 C#(版本 4)?如果是,x 的值是多少?

C# Java 解析 LALR

评论

3赞 Ira Baxter 12/5/2011
我看到一些建议来结束这个问题。我无法理解其中的道理;这个问题很清楚。

答:

5赞 dbf 12/5/2011 #1

至少对于 Java(版本 1.0),它是: http://java.sun.com/docs/books/jls/first_edition/html/19.doc.html

14赞 templatetypedef 12/5/2011 #2

Java 语法(1.0 版)已知为 LALR(1);本网站提供了一个语法,并以以下通知开头

语法已经过机械检查,以确保它是 LALR(1)。

我不确定 C# 是否是 LALR(1),但这里有一个bison 编写的 C# 解析器,这表明它可能是 LALR(1)(假设您允许优先级声明)。

就其价值而言,通常 LALR(1) 是唯一使用的 LALR 解析器。如果你需要使用 LALR(2) 之类的东西来处理语法,通常最好使用具有显式优先级消歧的 LALR(1) 解析器,或者更强大的解析器,比如 GLR 解析器。

希望这有帮助!

评论

2赞 TonySalimi 12/5/2011
谢谢,但我认为引用的文档属于 Java 的早期版本。你确定新的 java 语言规范(包括泛型等)仍然是 LALR(1) 吗?
0赞 Lukasz Madon 12/5/2011
C# 规范中添加了 C# 语法。
1赞 Ira Baxter 12/5/2011
“C# 规范”?你是说ECMA规范吗?那不是 C# 4.0,MS 无论如何都没有实现该规范。
16赞 Ira Baxter 12/5/2011 #3

如果不首先为语言指定特定的语法,你就不能问这个问题,因为有些语法可能是,有些可能不是。

也许您的意思是在最近的 Java 规范中发布的 Java 语法。你是说 Java 7 吗?

我不确定您能否为 C# 指定特定的语法,至少不是 Microsoft 的语法,尤其是 C# 4.0;我不相信他们已经出版了语法。

我可以告诉你,我不认为 C# 可以是 LALR(x),因为它有一些看起来像标识符的元素,但在某些上下文中可以是关键字。这要求词法分析器知道解析器期望什么,以决定类似标识符的标记是关键字,还是只是和标识符。因此,必须有从解析器到词法分析器的反馈,或者词法分析器必须生成两个标记并将它们传递给解析器以决定它想要哪个。LALR 解析器在没有任何反馈的令牌流上定义,并且每个输入令牌只有一个解释。

我也不认为 Java 是从 Java 1.5 及更高版本开始的,当时 enum 被引入为具有自己关键字的特殊类型。这是因为,要使 Java 1.5 编译器处理使用 enum 作为变量名称的现有 Java 1.4 程序,必须将 enum 在某些上下文中视为关键字,而在另一些上下文中则被视为变量名称。因此,Java 1.5 解析器具有与 C# 相同的问题。

实际上,没有真正的语言是 LALR(1) [第一版 Java 可能是一个例外],任何构建真正的解析器(尤其是 LALR)的人都必须进行某种黑客攻击来解决这个问题。(GCC长期以来一直使用LALR解析器解析C++,因此它可以区分标识符作为变量和标识符作为typedef实例之间的区别。它现在有某种手动实现的递归下降解析器,但我认为可怕的黑客仍然存在)。所以我不确定回答你的问题的价值。

我们的语言前端系列的 C# 4.0 和 Java 7 成员都使用 GLR 解析器解析语言,并通过反馈功能和处理同一令牌的两种解释的能力进行了扩展。GLR 使 LALR(x) 的问题变得毫无意义,反馈和多种解释让我们能够处理许多超出纯 GLR 能力的语言。

编辑:经过一番思考,可能有一种非常丑陋的方法可以使两种语法在上下文中处理它们的关键字。我们以 Java 的枚举为例。实际上必须有语法规则:

  type = 'enum' '{'  enum_members '}' ;

但是我们还需要允许“enum”作为标识。我们可以通过将终端令牌标识符替换为非终端来做到这一点:

  identifier = IDENTIFIER | 'enum' ;

并坚持认为 IDENTIFIER 是词法分析器产生的终端。现在,至少词法分析器不必决定如何处理枚举;解析器可以。但是你指定的语法必须像这样,才有机会成为 LALR(x)。

我们的解析器过去常常这样做,以允许某些关键字有时用作标识符。如前所述,我们更改了解析引擎,现在不再这样做了。

评论

0赞 TonySalimi 12/5/2011
感谢艾拉的丰硕回答。参考您的枚举示例,现在我确定 LALR(x) 解析器无法解析 Java 7 和 c# 4 语言。
1赞 Ira Baxter 12/5/2011
@hsalimi:正确的解释是你不能用纯 LALR(x) 解析器来解析它们。人们通过采用他们拥有的任何解析技术来制作工作解析器,构建一个尊重解析技术局限性的语法(基本上对此别无选择),然后在词法分析器/解析器中破解某些内容以使其工作。
0赞 TonySalimi 12/5/2011
再次感谢艾拉的回答和评论。此外,我也相信真相在细节中。:-)
0赞 chrylis -cautiouslyoptimistic- 1/31/2014
需要注意的是,在合规级别 1.5 或更高版本运行的 Java 编译器不允许用作标识符,并且在 1.5 引入之后必须重写大量库。相反,编译器在不同的语法之间进行选择。enumenum
0赞 xaxxon 10/6/2016
@IraBaxter,与贵公司产品的链接如何增强这个答案呢?