语法词汇表

注释

// 这是单行注释
/* 这是
多行注释 */

标识符

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 grammarparser 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>
...

lexer规则元素