4. ANTLR语法细节

1. 注释、命名规范、保留字
  • 注释:支持单行、多行、Javadoc风格的注释。Javadoc风格注释只能出现在语法和任意规则的开头。
  • 标识符:词法符号和词法规则名以大写字母开头,语法规则以小写字母开头。后面的字符可以是大小写字符、数字、下划线。
  • 文件命名:文件第一行命名语法名字X,包含语法X的文件必须被命名为X.g4
  • 文本常量:ANTLR不区分字符常量和字符串常量,所有文本常量都是由单引号括起来的字符串。文本常量不支持正则表达式,可以包含\uXXXX形式的Unicode转义序列。
  • 保留字:import 、fragment、lexer、parser、grammar、returns、locals、throws、catch、finally、mode、options、tokens,rule不是关键字但也需要避免。另外不使用目标语言中的关键字作为标识符。
2. 文件结构
  • 语法声明:不带前缀的语法声明时混合语法,可同时包含词法规则和文法规则,如grammar Name;;只允许文法规则出现使用 parser grammar Name;;值允许词法规则出现则使用 lexer grammar Name;

  • options、import、tokens:这些声明可以以任何次序出现,可有可无,最多出现一次。

    • options

      可以理解为一些特定的参数设定。可通过ANTLR语法在文件中提前设定。
      语法形式:options { name1=value1; ......nameN=valueN;}
      superClass: 设定生成的语法分析器或词法分析器的父类。混合语法设定的是语法分析器的父类
      language: 可行则生成指定语言的代码。否则报错
      tokenVocab: ANTLR会为每个语法生成一个".tokens"文件,这个选项可以指定其他语法生成的tokens文件,最后会也会生成进当前语法的tokens文件中。
      TokenLabelType: ????

    • tokens

      定义了一份语法所需,但没有在本语法中列出对应规则的词法符号。
      基本的语法:tokens {<<Token1>>, ... , <<TokenN>>}

    • import

      导入其他的词法或者语法文件,例如 import SelectClauseParser, FromClauseParser, IdentifiersParser;

  • 动作:动作是使用目标语言编写的代码块,可在语法中很多位置使用,格式是由花括号包围的任意文本。内嵌代码可以出现在以@header、@members命名的动作、词法和语法规则、指定异常捕获区、语法规则的属性区域(返回值、参数以及局部变量)以及一些规则元素的选项。

  • 语法、词法规则

3. 通用规则
  • 语法导入: 一个语法会从其导入的语法中继承所有的规则、词法符号声明和具名的动作。位于主语法中的规则将会覆盖其导入的语法中的规则,词法符号和具名动作如@members会被合并;被导入语法中的所有选项 options会被忽略;
    并非每种类型的语法都能导入其他类型语法:词法语法能导入词法语法、句法语法能导入句法语法、混合语法能导入词法语法或者句法语法
  • 动作相关规则:对于JAVA目标语言而言只有 headers 和 members两种动作。
    headers用于将代码注入生成的识别类中的类声明之前(例如package xxx.xxxx.xxx或者import java类)
    members用于将代码注入为识别类的字段和方法
    对于混合语法,ANTLR会同时将这些代码注入到词法分析器和语法分析器中,如果只需出现在特定分析器中,使用@parser::name或者@lexer::name
4. 文法规则
文法名 : 备选分支1      # Return   // #后面的是备选分支的标签,为了获得更加精确的语法分析器监听器事件。
	  | 备选分支2
	  ; 

注意事项

  • 对于一个规则的备选分支,要么全都带上标签,要么全都不带。标签无须位于行尾,#后面的空格不必须, ANTLR为每个标签生成一个规则上下文类
  • ANTLR为每个规则引用生成上下文对象的访问方法。
    对于只包含一条规则引用的规则,例如:inc : e '++';, ANTLR生成无参方法。
    对于包含多条规则引用的规则,例如:field : e '.' e;,ANTLR生成单参数方法,其参数是访问第i个规则时的索引值。另外还生成一个返回该规则对应的所有上下文对象列表的方法。
  • 可以使用 = 符号给规则元素增加标签,以此为规则上限文对象增加字段。
    例如:stat : 'return' value=e ';' value就是规则e的返回值
  • 当需要匹配除了一个/一组词法符号之外的任何东西时,使用 ~ "非"运算符。例如 ~INT ~',' ~(INT|ID)匹配除INT或ID以外的任何词法符号。
  • 4种子规则,子规则被包括在圆括号内
    (x|y|z) : 匹配该子规则内的任意备选分支一次
    (x|y|z)?:匹配子规则内的备选分支或者不匹配任何东西
    (x|y|z)*:匹配该子规则内的备选分支零次或多次
    (x|y|z)+:匹配该子规则内的备选分支一次或多次
    可以在 ? * + 后面加上?表示非贪婪运算符
  • 想要修改单条规则的异常处理机制,可以在规则定义后指定一个异常,如果有即使异常发生也需要执行的动作代码放入finally语句中
    例如:
r : ...
  ;
  catch[RecognitionException e] { throw e;}
  finally { System.out.println(); }
5. 词法规则
6. 嵌入动作、属性等
  • 嵌入动作
    动作:使用目标语言编写的、放置在{…}中的任意代码块。
    一些语言类应用程序需要在语法分析的过程中执行自身的逻辑代码,为了达到这个目的需要将代码片段注入到ANTLR生成的代码中。
    例1:
@parser::members {
  Map<String, Integer> memory = new HashMap<String, Integer>();
}
stat : e NEWLINE		{System.out.println($e.v);}
	 | ID '=' e NEWLINE {memory.put($ID.text, $e.v);}
	 | NEWLINE
	 ;

动作出现在备选分支的末尾,因此它们会在语法分析器匹配到整个语句之后被执行。
动作代码中的 $x.y是指元素x的y属性,x可以是词法符号引用或者规则引用。$e.v指的是调用规则e的返回值,$ID.text指的是ID词法符号匹配到的文本。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值