提问人:TonySalimi 提问时间:12/5/2011 最后编辑:TonySalimi 更新时间:12/20/2011 访问量:3721
C# 和 Java 语法是 LALR(x) 吗?
Are C# and Java Grammars LALR(x)?
问:
我想知道 C# 和 Java 语法是否是 LALR(x)?如果是,x 的值是多少?
编辑:
在接受了真实的答案之后,我认为最好这样改变Q:
是否有任何 LALR(x) 解析器可以解析当前版本的 Java(版本 7)或 C#(版本 4)?如果是,x 的值是多少?
答:
至少对于 Java(版本 1.0),它是: http://java.sun.com/docs/books/jls/first_edition/html/19.doc.html
Java 语法(1.0 版)已知为 LALR(1);本网站提供了一个语法,并以以下通知开头
语法已经过机械检查,以确保它是 LALR(1)。
我不确定 C# 是否是 LALR(1),但这里有一个用 bison
编写的 C# 解析器,这表明它可能是 LALR(1)(假设您允许优先级声明)。
就其价值而言,通常 LALR(1) 是唯一使用的 LALR 解析器。如果你需要使用 LALR(2) 之类的东西来处理语法,通常最好使用具有显式优先级消歧的 LALR(1) 解析器,或者更强大的解析器,比如 GLR 解析器。
希望这有帮助!
评论
如果不首先为语言指定特定的语法,你就不能问这个问题,因为有些语法可能是,有些可能不是。
也许您的意思是在最近的 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)。
我们的解析器过去常常这样做,以允许某些关键字有时用作标识符。如前所述,我们更改了解析引擎,现在不再这样做了。
评论
enum
enum
评论