《ANTLR 4权威指南》笔记15 - 语法参考
语法词汇表⌗
注释⌗
// 这是单行注释
/* 这是
多行注释 */
标识符⌗
token(词法单元)和lexer rule(词法规则)由大写字母开头。
ID, LPAREN, RIGHT_CURLY
parser rule(语法规则)由小写字母开头。
expr, simpleDeclarator, d2, header_file
标识符支持Unicode,标识符根据Java判断函数Character.isUpperCase(getText().charAt(0))
为true
的是词法规则,否则是语法规则。
字面量(literals)⌗
ANTLR不区分character和string,所有的字面量string都用单引号表示,特殊字符需要转义,支持Unicode转义。
';', 'if', '>='
'\u00E8'
'\n', '\r', '\t', '\b', '\f'
动作(actions)⌗
目标语言的任意代码块,写在{}
中间。如果代码中包含对称的{}
,则不需要转义,否则需要转义{\{}}
。
可以嵌入代码的地方有:
@header
,named action@members
,named action- 语法规则
- 词法规则
- 异常捕获
- 语法规则的属性区域(returns、arguments、locals)
- 某些规则的
option
和语义谓词中。
关键字⌗
保留字:
import
fragment
lexer
parser
grammar
returns
locals
throws
catch
finally
mode
options
tokens
非保留字(避免使用):
rule
目标语言的关键字,比如if、else
语法结构⌗
grammar Name; // 必须
options {
...
}
import ... ;
tokens {
...
}
@actionName {
...
}
rule1 : ...;
RULE_N : ...;
语法规则文件
parser grammar Name;
词法规则文件,只有词法规则文件可以包含mode定义
lexer grammar Name;
混合规则文件
grammar Name;
规则选择
ruleName
: alternative1
| alternative2
| alternativeN
;
语法导入⌗
grammar MyElang;
import ELang;
...
继承被导入文件中的所有规则、tokens、named actions。可以重写(override)被导入的语法。可以导入多个文件,如果导入的多个文件都定义了规则r
,根据导入的顺序和深度优先规则查找。
lexer grammar
只能导入lexer grammar
,parser grammar
只能导入parser grammar
,混合语法可以同时导入二者。
tokens⌗
例子:
tokens {
BEGIN,
END,
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);
...
}};
}
选择规则标签⌗
grammar AltLabels;
stat: 'return' e ';' # Return
| 'break' ';' # Break
;
e :e '*' e # BinaryOp
| e '+' e # BinaryOp
| INT # Int
;
要么没有标签,要么每一个选择都有标签,标签可以重复!
规则上下文对象⌗
例子:
inc : e '++' ;
生成的代码:
public static class IncContext extends ParserRuleContext {
public EContext e() { ... } // return context object associated with e
...
}
例子,如果包含多个相同的规则:
field : e '.' e ;
s : field
{
List<EContext> x = $field.ctx.e();
...
}
;
生成的代码会包含两个方法,根据index获取第i个context对象,以及获取所有context对象的列表:
public static class FieldContext extends ParserRuleContext {
public EContext e(int i) { ... }
// get ith e context
public List<EContext> e() { ... }
// return ALL e contexts
...
}
规则元素标签⌗
单个元素标签:
stat: 'return' value=e ';' # Return
| 'break'
';' # Break
;
生成的context对象:
public static class ReturnContext extends StatContext {
public EContext value;
...
}
list标签:
array : '{' el+=INT (',' el+=INT)* '}' ;
elist : exprs+=e (',' exprs+=e)* ;
生成的context对象:
public static class ArrayContext extends ParserRuleContext {
public List<Token> el = new ArrayList<Token>();
...
}
规则元素⌗
T
'literal'
r
r[args]
{action}
{predicate}?
~(T1|T2|T3)
子规则⌗
(x|y|z)
(x|y|z)?
(x|y|z)*
(x|y|z)+
(x|y|z)??
(x|y|z)*?
(x|y|z)+?
标签:
ids+=INT+
捕获异常⌗
r : ...
;
catch[FailedPredicateException fpe] { ... }
catch[RecognitionException e] { ... }
finally { ... }
异常列表
- RecognitionException
- NoViableAltException
- LexerNoViableAltException
- InputMismatchException
- FailedPredicateException
规则属性⌗
ruleName [args] returns [retvals] locals [localvars]
@init {
...
}
@after {
...
}
: ... ;
例子:
add[int x] returns [int result]
: '+=' INT { $result = $x + $INT.int }
起始规则和EOF⌗
语法文件中的任意规则都可以作为起始规则。
file : element* EOF
token属性⌗
attribute | type | description |
---|---|---|
text | String | |
type | int | |
line | int | |
pos | int | |
index | int | |
channel | int | |
int | int | $INT.int |
语法规则属性⌗
attribute | type | description |
---|---|---|
text | String | |
start | Token | |
stop | Token | |
ctx | ParserRuleContext |
Lexer规则⌗
fragment⌗
INT : DIGIT+ ;
fragment DIGIT : [0-9] ;
词法模式(modes)⌗
<rules default mode>
...
mode MODE1;
<rules in mode1>
...
mode MODEN;
<rules in mode n>
...