Java 来自 Github 的针对 ANTLR4 和 C# 目标的语法

Java Grammar from Github for ANTLR4 and C# target

我已经放弃将 C# 语法从 ANTLR3.2 版本修复到 ANTLR4 版本,现在我想制作 Java Parser 和 Visitor。 从 Github 下载的 ANTLR4 的 Java 语法:https://github.com/antlr/grammars-v4/blob/master/java/Java.g4 是为任何目标语言编写的,但有些代码是针对 Java 目标的,它不适用于 C#。我说的是这些 lexar 规则:

fragment
JavaLetter
:   [a-zA-Z$_] // these are the "java letters" below 0xFF
|   // covers all characters above 0xFF which are not a surrogate
    ~[\u0000-\u00FF\uD800-\uDBFF]
   // {Character.isJavaIdentifierStart(_input.LA(-1))}?
|   // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
    [\uD800-\uDBFF] [\uDC00-\uDFFF]
    //{Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char) _input.LA  (-1)))}?
;

fragment
JavaLetterOrDigit
:   [a-zA-Z0-9$_] // these are the "java letters or digits" below 0xFF
|   // covers all characters above 0xFF which are not a surrogate
    ~[\u0000-\u00FF\uD800-\uDBFF]
   // {Character.isJavaIdentifierPart(_input.LA(-1))}?
|   // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
    [\uD800-\uDBFF] [\uDC00-\uDFFF]
    //{char.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
;

我已经评论了以{Character.isJavaIdentifier...}开头的目标代码,现在可以了。我想知道为什么它在那里!?如果之前的标记或之前的 2 个标记(如果是 LA(-2))是 IdentifierPart,我认为它 returns 是正确的,但是操作代码是做什么用的?在 C# 中 Char 对象不支持静态方法 isIdentifierPart 或类似的东西...

我的问题是: 如果我取消操作代码,解析器在解析 Java 输入代码期间是否会在特定标识符名称上失败? 如果是,我如何用它代替 C# 目标?

感谢回复! PK

Java Language Specification §3.8中,根据Characterclass.[=19=中的两个静态方法定义了一个标识符 ]

Identifier:
  IdentifierChars but not a Keyword or BooleanLiteral or NullLiteral

IdentifierChars:
  JavaLetter {JavaLetterOrDigit}

JavaLetter:
  any Unicode character that is a "Java letter"

JavaLetterOrDigit:
  any Unicode character that is a "Java letter-or-digit"

A "Java letter" 是方法 Character.isJavaIdentifierStart(int) returns 为真的字符。

A "Java letter-or-digit" 是方法 Character.isJavaIdentifierPart(int) returns 为真的字符。

语法以特定方式实现这一点,旨在最大限度地提高预期输入的性能。特别是,集合 [a-zA-Z0-9_$](正则表达式语法)中最著名的字符由语法直接处理。语言规范保证此集合将始终被视为标识符字符。

ANTLR 4 不会缓存 U+007F 以上的 UTF-16 代码单元的 DFA 转换,因此前面描述的集合之外的任何内容无论如何都在词法分析器的 "slow" 路径上。这些字符并没有使状态机的大小膨胀,而是使用干净简单的语义谓词来处理。

如果您的源代码不使用 U+007F 以上的代码点作为 Unicode 标识符,那么您可以安全地将语法简化为以下内容:

fragment
JavaLetter
  :   [a-zA-Z$_] // these are the "java letters" below 0xFF
  ;

fragment
JavaLetterOrDigit
  :   [a-zA-Z0-9$_] // these are the "java letters or digits" below 0xFF
  ;

否则,为了获得完整支持,您可以使用 C# 目标中的 Java-LR.g4 语法(在使用前重命名为 Java.g4)。