antler4-语法规则
语法规则
注释
单行、多行、javadoc风格;
javadoc风格只能在开头使用
/** This grammar is an example illustrating the three kinds
 * of comments.
 */
grammar T;
/* a multi-line
  comment
*/
/** This rule matches a declarator for my language */
decl : ID ; // match a variable name
标识符
符号(Token)名大写开头
解析规则(Parser rule)名小写开头
后面可以跟字母、数字、下划线
ID, LPAREN, RIGHT_CURLY // token names/rules
expr, simpleDeclarator, d2, header_file // rule names
允许使用Unicode字符
使用Unicode解析和词法规则名称时,需要使用下面的规则
ID : a=NameStartChar NameChar*
     {  
	     if ( Character.isUpperCase(getText().charAt(0)) ) setType(TOKEN_REF);
	     else setType(RULE_REF);
     }  
   ;
规则NameChar识别有效的标识符
规则NameStartChar是可以开始标识符的字符列表,用于(rule, token, or label name)
如果不是utf-8需要在ANTLER Tool中添加-encoding选项
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'
   ;
常量
不区分字符、字节:单引号'',不包括正则表达式
识别unicode编码:\uXXXX,后面为16进制
字符中能够识别:\n、\r、\t、\b、\f
生成的识别器假定包含所有的Unicode字符
grammar Foreign;
a : '外' ;
Actions
用目标语言写的代码块,大括号括起来的
嵌入代码可以放在@header和@members命名的action中、parser和lexer规则
关键字
import, fragment, lexer, parser, grammar, returns,
locals, throws, catch, finally, mode, options, tokens
语法结构
语法结构
grammar是一个grammar声明,加上一个规则列表
/** Optional javadoc style comment */
grammar Name; ①
options {...}
import ... ;
tokens {...}
channels {...} // lexer only
@actionName {...}
rule1 // parser and lexer rules, possibly intermingled
...
ruleN
语法是x,文件命名为x.g4
可以指定:options、imports、token描述、actions
所有的参数是可选的, 除了头和至少一个rule,Rule基本形式如下
ruleName : alternative1 | ... | alternativeN ;
没有前缀的,可以词法或者语法,只解析parser规则,可以使用
parser grammar Name;
...
只解析lexer规则可以使用
lexer grammar Name;
...
只有lexer语法可以包含mode描述和channel描述
channels {
	WHITESPACE_CHANNEL,
	COMMENTS_CHANNEL
}
channels之后就可以像枚举一样使用
WS : [ \r\t\n]+ -> channel(WHITESPACE_CHANNEL) ;
Imports
把语法拆成逻辑的和可重用的块,antler测试import语法非常像米啊你想对象语言的父类,语法继承所有的rule、tokens、actions,在main语法里的覆盖继承的语法内容;
import可看作一个智能的include,已经存在的不会引入,生成代码的时候并不知道有import的存在;
像下面的例子

像下面的多级应用,顺序是:Nested, G1, G3, G2.

引用限制:
- Lexer只能引用Lexer
- Parsers只能引用Parsers
- Combined语法可以引用lexers或者parsers
Tokens段
定义语法需要的tokens类型,没有相关的lexical规则
基本的语法如下
tokens { Token1, ..., TokenN }
大部分时候,tokens section用来定义token类型
// 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);
    ...
}};
}
定义的token set会加入到全局set中
$ 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
当前有两个定义的actions:header和members,之前注入的代码
ANTLR注入actions到parser和lexer,使用@parser::name or @lexer::name
grammar Count;
@header {
package foo;
}
@members {
int count = 0;
}
list
@after {System.out.println(count+" ints");}
: INT {count++;} (',' INT {count++;} )*
;
INT : [0-9]+ ;
WS : [ \r\t\n]+ -> skip ;
语法本身在foo,不使用-o时,所以ANTLR在foo中生成代码
$ 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
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号