Grammar Structure

翻译:原文
语法本质上是一个语法声明,后面是规则列表,但具有以下一般形式:

/** Optional javadoc style comment */
grammar Name; ①
options {...}
import ... ;
    
tokens {...}
channels {...} // lexer only
@actionName {...}
     
rule1 // parser and lexer rules, possibly intermingled
...
ruleN

包含语法X的文件名必须称为X.g4。您可以按任何顺序指定选项,导入,令牌规范和操作。选项,导入和令牌规范中最多可以有一个。所有这些元素都是可选的,但标题①和至少一个规则除外。规则采用基本形式:

ruleName : alternative1 | ... | alternativeN ;

解析器规则名称必须以小写字母开头,而词法分析器规则必须以大写字母开头。

在语法标头上没有前缀定义的语法是可以包含词汇规则和解析器规则的组合语法。要创建仅允许解析器规则的解析器语法,请使用以下标头。

parser grammar Name;
...

而且,自然的,纯词法语法看起来像这样:

lexer grammar Name;
...

只有词法分析器语法可以包含mode specifications。

只有词法分析器语法可以包含自定义channels specifications。

channels {
  WHITESPACE_CHANNEL,
  COMMENTS_CHANNEL
}

然后可以将这些通道像词法分析器规则中的枚举一样使用:

WS : [ \r\t\n]+ -> channel(WHITESPACE_CHANNEL) ;

第15.5节“ Lexer规则”和第15.3节“解析器规则”包含有关规则语法的详细信息。第15.8节“选项”描述了语法选项,而第15.4节“actions和attributes”提供了有关grammar-level动作的信息。

Grammar Imports

语法imports使您可以将语法分为逻辑块和可重用块,如在导入语法中所见。 ANTLR对待导入的语法非常类似于面向对象的编程语言对待超类。语法从导入的语法继承所有规则,标记规范和命名操作。 “主语法”中的规则会覆盖导入语法中的规则以实现继承。

将导入更像是一个聪明的include语句(其中不包含已经定义的规则)。所有导入的结果是一个单一的组合语法; ANTLR代码生成器看到了完整的语法,却不知道有导入的语法。

要处理主语法,ANTLR工具会将所有导入的语法加载到从属语法对象中。然后,它将规则,标记类型和命名操作从导入的语法合并到主语法中。在下图中,右侧语法说明了MyELang语法导入ELang语法的效果。



MyELang继承规则stat,WS和ID,但覆盖规则expr并添加INT。这是一个示例构建和测试运行,显示MyELang可以识别整数表达式,而原始ELang无法识别。第三个错误的输入语句触发一条错误消息,该错误消息还表明解析器正在寻找MyELang的expr而非ELang的表达式。

$ antlr4 MyELang.g4
$ javac MyELang*.java
$ grun MyELang stat
=>  34;
=>  a;
=>  ;
=>  EOF
<=  line 3:0 extraneous input ';' expecting {INT, ID}

如果主语法或任何导入的语法中存在模式,则导入过程将导入这些模式并在不覆盖它们的情况下合并其规则。如果任何模式变为空,因为其所有规则都已被该模式之外的规则覆盖,则该模式将被丢弃。

如果有任何令牌规范,则主要语法将合并令牌集。如果有任何通道规范,则主要语法将合并通道集。任何已命名的动作(例如@members)都将被合并。通常,应避免在导入的语法中使用命名动作和规则中的动作,因为这样做会限制重用。 ANTLR还忽略导入语法中的任何选项。

导入的语法也可以导入其他语法。 ANTLR以深度优先的方式学习所有导入的语法。如果两个或多个导入的语法定义了规则r,则ANTLR将选择找到的r的第一个版本。在下图中,ANTLR按照嵌套,G1,G3,G2的顺序检查语法。



嵌套包含来自G3的r规则,因为它可以在G2中的r之前看到该版本。

并非每种语法都可以导入其他每种语法:

词法分析器语法可以导入词法分析器,包括包含模式的词法分析器。
解析器可以导入解析器。
组合语法可以导入没有模式的解析器或词法分析器。
ANTLR在主词法语法中将导入的规则添加到规则列表的末尾。这意味着主语法中的词法分析器规则优先于导入的规则。例如,如果主语法定义了规则IF:'if';导入的语法定义了规则ID:[a-z] +; (也可以识别),导入的ID不会隐藏主语法的IF token定义。

Tokens Section
tokens section的目的是定义没有相关词汇规则的语法所需的标记类型。基本语法为:

tokens { Token1, ..., TokenN }

大多数时候,tokens section用于定义语法中的动作所需的tokens section,如第10.3节“识别关键字未固定的语言”中所示:

// explicitly define keyword token types to avoid implicit definition warnings
tokens { BEGIN, END, IF, THEN, WHILE }
 
@lexer::members { // keywords map used in lexer to assign token types
Map<String,Integer> keywords = new HashMap<String,Integer>() {{
    put("begin", KeywordsParser.BEGIN);
    put("end", KeywordsParser.END);
    ...
}};
}

tokens section实际上只是定义了一组token,以添加到整个集合中。

$ cat Tok.g4
grammar Tok;
tokens { A, B, C }
a : X ;
$ antlr4 Tok.g4
warning(125): Tok.g4:3:4: implicit definition of token X in parser
$ cat Tok.tokens
A=1
B=2
C=3
X=4
Actions at the Grammar Level

当前,在语法规则之外仅使用了两个已定义的命名操作(用于Java目标):header和members。前者将代码注入到识别器类定义之前的生成的识别器类文件中,后者将代码作为字段和方法注入到识别器类定义中。

对于组合语法,ANTLR将动作同时注入解析器和词法分析器。要将操作限制为生成的解析器或词法分析器,请使用@parser::name或@lexer::name。

这是一个示例,其中语法为生成的代码指定了一个包:

$ cd foo
$ antlr4 Count.g4 # generates code in the current directory (foo)
$ ls
Count.g4        CountLexer.java CountParser.java
Count.tokens    CountLexer.tokens
CountBaseListener.java CountListener.java
$ javac *.java
$ cd ..
$ grun foo.Count list
=>  9, 10, 11
=>  EOF
<=  3 ints

Java编译器期望软件包foo中的类位于目录foo中。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容