ANTLR4 如何编写语法文件之语法词汇

Posted @SmartSi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ANTLR4 如何编写语法文件之语法词汇相关的知识,希望对你有一定的参考价值。

ANTLR 中的词汇大多数程序员可能都熟悉,因为它遵循 C 语言及其派生语言的语法,此外还对语法进行了一些扩展。

1. 注释 Comments

ANTLR 支持单行、多行以及 Javadoc 风格的注释:

/** 这是说明三种注释的语法示例
 */
grammar T;
/*多行
* 注释
*/

/** 此规则匹配自定义语言中的一个声明 */
decl : ID ; // 匹配一个变量名

Javadoc 风格的注释不会被忽略,他们会被送入语法分析器,它们只能出现在语法和任意规则的开头

Javadoc 风格的注释是 Java 代码的一种注释风格,可以用 javadoc 命令生成 API 文档。

2. 标识符 Identifiers

词条 Token 名称以及词法解析器规则(词法规则)名称总是以大写字母开头,其中大写字母由 Java 的 Character.isUpperCase 方法定义。语法解析器规则(语法规则)名称总是以小写字母开头(Character.isUpperCase 方法返回 false)。首字母之后的字符可以是大写字母,也可以是小写字母,也可以是数字或者下划线。如下是简单的例子:

// 词条或者词法解析器规则名称
ID, LPAREN, RIGHT_CURLY
// 语法解析器规则名称
expr, simpleDeclarator, d2, header_file

词法规则名总是以大写字母开头;语法规则名总是以小写字母开头

与 Java 类似,ANTLR 也允 Unicode 字符出现在标识符中:

为了支持 Unicode 的词法解析器规则和语法解析器规则,ANTLR 使用如下规则:

ID : a=NameStartChar NameChar*
       
     if ( Character.isUpperCase(getText().charAt(0)) ) setType(TOKEN_REF);
     else setType(RULE_REF);
       
   ;

NameChar 规则标识可以作为标识符的有效字符,NameStartChar 规则标识可以作为标识符(规则、词条或者标签名称)首字母的字符列表。这些字符大致与 Java Character 类的 isJavaIdentifierPart 和 isJavaIdentifierStart 相对应:

fragment
NameChar
   : NameStartChar
   | '0'..'9'
   | '_'
   | '\\u00B7'
   | '\\u0300'..'\\u036F'
   | '\\u203F'..'\\u2040'
   ;
fragment
NameStartChar
   : 'A'..'Z' | 'a'..'z'
   | '\\u00C0'..'\\u00D6'
   | '\\u00D8'..'\\u00F6'
   | '\\u00F8'..'\\u02FF'
   | '\\u0370'..'\\u037D'
   | '\\u037F'..'\\u1FFF'
   | '\\u200C'..'\\u200D'
   | '\\u2070'..'\\u218F'
   | '\\u2C00'..'\\u2FEF'
   | '\\u3001'..'\\uD7FF'
   | '\\uF900'..'\\uFDCF'
   | '\\uFDF0'..'\\uFFFD'
   ;

如果语法文件不是 UTF-8 编码格式,请确保在 ANTLR 工具上使用 -encoding 选项,以便 ANTLR 正确的读取字符。

3. 文本常量 Literals

ANTLR 不像大多数语言那样区分字符常量和字符串常量。长度为一个或多个字符的文本字符串都使用单引号包裹,例如 ';''if''>=' 以及 '\\"(包含单引号字符的单字符字符串)。文本常量从不包含正则表达式。

文本常量可以包含形式为'\\uXXXX''\\UXXXXXX'的 Unicode 转义序列,其中’XXXX’是十六进制的 Unicode 字符值。例如,'\\u00E8' 是法语字母 è,而 \\u1F4A9 是著名的表情符号💩

ANTLR 还可以识别常见的特殊转义序列:'\\n'(换行符)、'\\r'(回车)、'\\t'(制表符)、'\\b'(退格)和'\\f'(换行)。你可以直接使用它们或者使用它们的 Unicode 转义序列:

grammar Foreign;
a : '外' ;

ANTLR 生成的识别器假设语法中的字符都是 Unicode 字符。ANTLR 运行时库对输入文件编码做出的假设取决于目标语言。对于 Java 目标语言,运行时库假设文件编码是 UTF-8 格式。使用 CharStreams 中的工厂方法,您可以指定不同的编码格式。

4. 动作 Actions

动作是使用目标语言编写的代码块。您可以在语法中的不同地方使用动作,但语法格式是一样的:用花括号括起来的任意文本。如果右花括号字符在字符串或注释中,则不需要转义: "" 或者 /**/。在花括号平衡的情况下,无需转义 ,例如 ...。其他情况下,额外的花括号需要使用反斜杠转义:\\\\。动作代码应该符合语言选项指定的目标语言的语法。

嵌入式代码可以出现在:@header@member 命名的动作、词法解析器规则和语法解析器规则、异常捕获区、语法解析器规则的属性部分(返回值、参数以及局部变量)以及一些规则元素的选项中。

5. 关键词

如下是 ANTLR 语法中保留关键字列表:

import, fragment, lexer, parser, grammar, returns,
locals, throws, catch, finally, mode, options, tokens

另外,尽管 rule 不是关键字,但不要使用 rule 作为规则名。此外,不要使用目标语言(例如,Java)中的任何关键字作为词条 Token、标签或者规则名。例如,if 规则将生成一个名为 if 的函数。这显然不能通过编译。

原文:Grammar Lexicon

以上是关于ANTLR4 如何编写语法文件之语法词汇的主要内容,如果未能解决你的问题,请参考以下文章

ANTLR4 如何编写语法文件之语法结构

ANTLR4 如何编写语法文件之语法结构

ANTLR4 如何编写语法文件之语法解析器规则

ANTLR4 如何编写语法文件之语法解析器规则

ANTLR4 词法分析器规则在 perl 语法上产生错误或冲突

ANTLR4权威指南 - 第5章 设计语法