antlr学习笔记

本文详细解读了ANTLR文法规则与动作的使用方法,包括语法、标签、上下文、预测、重写规则等核心概念,以及如何通过设置选项和动作来优化文法解析过程。涵盖了从基础到高级的ANTLR文法编写技巧,帮助开发者更高效地处理语言解析任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、VT_CONDITION[$value]带中括号的含义?
condition_key
: {validateIdentifierKey("condition")||validateIdentifierKey("when")}? value=LITERAL
-> VT_CONDITION[$value]
含义为:为VT_CONDITION设置此token的行号和列号为$value的行号和列号,另外还可以设置此虚拟token的text属性值。
如:VT_CONDITION[$value,"condition"]

2、重写的时候只能对目前的语法中的值进行组装,无法修改?
AST的作用:
a)记录输入tokens的含义,且仅仅是token的含义。
b)编码,去掉不必要的token。
c)易于计算机识别和定位。

3、parser和treewalker如何分工?

4、上下文相关看第13章:Semantic Predicates语义判断
expr : {<<lookahead(1) is function>>}? functionCall
| {<<lookahead(1) is type>>}? ctorTypecast
;
上句的意思是:如果前面上下文判定为函数则匹配functionCall,前面上下文判定为类型则匹配类型强制转换。
此处的关键点为{java代码,结果为布尔值}?
5、综合预测看第14章:syntactic predicate
stat : (declaration)=> declaration
| expression
;
上句的意思是:如果declaration能匹配则优先匹配declaration。
6、文法编写的优先级需要特别注意
优先级低的放前面,优先级高的放后面,这和LL的深度优先处理是有很大关系的,要认真体会。
7、文法中规则的引用最终转换成方法的引用,字token最终转换成match(token)的调用。
8、EOF在unix下要按ctrl+d键,windows下按ctrl+z键。
9、->为语法规则重写,语法重写仅仅能够改变token的顺序,或者减少token,但不能进行语义的增加。
10、^在语法规则中使用时,放在作用的字(token)的后面,表示前面的字(token)为树的根节点。在语法规则重写中使用时,放在作用的字(token)的前面,表示后面的字(token)为树的根节点
11、!在语法规则中使用时,放在作用的字(token)的后面,表示前面的字(token)不作为树的一部分。
12、WS没有用为啥还要配上?
好像默认是有用的。

13、antlr规则语法
/** comment */
access-modifier rule-name[<<arguments>>] returns [<<return-values>>]
<<throws-spec>>
<<options-spec>>
<<rule-attribute-scopes>>
<<rule-actions>>
: <<alternative-1 >> -> <<rewrite-rule-1 >>
| <<alternative-2 >> -> <<rewrite-rule-2 >>
...
| <<alternative-n>> -> <<rewrite-rule-n>>
;
<<exceptions-spec>>
14、使用+=时,必须要有output选项
options {output=AST;} // or output=template
elist: e+=expr (',' e+=expr)* ;
15、规则可以带多个参数,也可以返回多个参数,但是如何传参和返回?
r[int a, String b] returns [int c, String d] return value.
: ... {$c=$a; $d=$b;}
调用时传参
s : ... v=r[3,"test"] {System.out.println($v.d);}
;
16、全局范围属性,主要用于规则之间变量共享
method
@scope {
String name;
}
: 'void' ID {$method::name = $ID.text;} '(' args ')' body
;
atom: ID {System.out.println("ref "+$ID.text+" in "+$method::name);}
;
17、模板使用
expr: ^(CALL c=expr args=exprList) -> call(m={$c.st},args={$args.st})
| ^(INDEX a=expr i=expr) -> index(list={$a.st},e={$i.st})
| primary -> {$primary.st} // return ST computed in primary
;
上面使用到的模板定义:
call(m,args) ::= "<m>(<args>)"
index(list,e) ::= "<list>[e]"
18、手动调用emit( )可以让一个token输出多个token,但是注意CommonTokenStream类不支持多个token输出。
INDENT token at a time.
: // turn on rule only if at left edge
{getCharPositionInLine()==0}?=>
(' ' |'\t' )+ // match whitespace
{
if ( <<indentation-bigger-than-before>> ) {
// can only indent one level at a time
emit(<<INDENT-token>>);
<<track increased indentation>>
}
else if ( <<indentation-smaller-than-before>> ) {
int d = <<current-depth >> - <<previous-depth >>;
// back out of d code blocks
for (int i=1; i<=d; i++) {
emit(<<DEDENT-token>>);
}
<<reduce indentation>>
}
}
;
19、在规则级别可以设置如下选项:
backtrack当匹配需要回溯时采用,经常和memoize配合使用。
memoize当匹配需要回溯时,不用对以前分析过的规则重新进行分析,提高匹配效率。
k为能回溯的最大深度
decl
options {
memoize=true;
}
: type ID (',' ID)*
;
20、tokens语法,主要用于虚拟树节点。
tokens {
token-name1 ;
token-name2 = 'string-literal' ;
...
}
注意如下用法:别名
grammar T;
tokens {
MOD='%' ; // alias MOD to '%'
}
expr : INT (MOD INT)* ;
21、全局scope语法,主要用于规则之间的变量共享,与规则@scope的区别?
scope name {
type1 attribute-name1 ;
type2 attribute-name2 ;
...
}
scope SymbolScope {
List symbols;
}
22、action语法
@action-name { ... }
@action-scope-name::action-name { ... }
注意:
如果@header {...}不带action-scope-name,默认表示为 @parser::header{...}
23、语法级选项
options {
name1 = value1 ;
name2 = value2 ;
...
}
language选项:最终antlr会根据此选项,按照文法生成对应语言(比如java)的实现。antlr会根据CLASSPATH查找org/antlr/
codegen/templates/Java进行JAVA代码的生成。

output选项:这个选项只能出现在combined,parser和tree三种文法中,并且在tree文法中,output选项只能为template,不能是AST。
此选项默认为不输出。注意只有output=AST时,才可以使用规则重写->(rewrite rules)和树构建操作符(^,!)。
另外如果规则没有定义返回值,且output没有设置的话,规则的返回值为void,否则都是有值的:
grammar T;
options {
output=AST;
}
decl : ID -> ^(DECL ID) ;
ID : 'a'..'z' + ;
public static class decl_return extends ParserRuleReturnScope {
Object tree;
public Object getTree() { return tree; }
};
public decl_return decl() throws RecognitionException {...}
如果设置为:output=template
public static class decl_return extends ParserRuleReturnScope {
public StringTemplate st;
/** To avoid unnecessary dependence on StringTemplate library,
* superclass uses Object not StringTemplate as return type.
*/
public Object getTemplate() { return st; }
};
public decl_return decl() throws RecognitionException {...}

backtrack选项:默认为false。
memoize选项:默认为false。
tokenVocab选项:导入token词汇,主要用于tree文法中,用于导入parser文法中的token,此选项默认不导入任何词汇。
rewrite选项:默认为false,只有output=template才有用,主要用于转换差别不大的文法是采用。
grammar T;
options {output=template; rewrite=true;}
decl: type ID ';' ; // no translation here
type: 'int' -> template() "Integer" // translate int to Integer
| ID // leave this alone
;
superClass选项:指定生成parser或代码的父类,默认为空。
filter选项:仅对lexer有用,默认为false,也就是不过滤,当为true时,如果lexer匹配不上token,将会过滤无法识别token,继续匹配后续token。
主要用于模糊匹配,只匹配关心的token。
ASTLabelType选项:设置tree标签,tree表达式目标语言的类型,默认为Object类型。
TokenLabelType选项:设置token标签,token表达式目标语言的类型,默认为接口Token类型。

24、语法动作
什么是动作,简单说来,只要放在{和}之中的语言(java)代码,就是动作。
25、预先定义的token属性
属性名称 属性类型 属性含义
text String token的值
type int token的类型
line int token所在的行号,从1开始算起。
pos int token所在行的偏移位置,从0算起。
index int 当前token在所有token流中的下表,从0算起。
channel int token所在的通道号,默认通道为Token.DEFAULT_CHANNEL其值为0,默认的隐藏通道为Token.HIDDEN_CHANNEL。
tree Object token所在的上一级树节点。

lexer grammar T;
R : a='c' b='hi' c=. {$a, $b.text, $c} ;
只有多于两个字符的才算token,否则就是字符,不能引用token的属性。

26、预先定义的parser规则属性
属性名称 属性类型 属性含义
text String rule对应的值,即规则匹配到的所有token。
start Token rule对应开始token,也就是第一个token。
stop Token rule对应结束token,也就是最后一个token,如果在当前规则中使用的话,一般只在after动作中才能使用。
tree Object rule的树节点,如果在当前规则中使用的话,一般只在after动作中才能使用。
st StringTemplate rule的模板,如果在当前规则中使用的话,一般只在after动作中才能使用。

27、预先定义的tree规则属性
text String rule对应开始树节点的值。
start Object rule对应开始树节点,也就是第一个树节点。
st StringTemplate rule的模板,如果在当前规则中使用的话,一般只在after动作中才能使用。

28、在动作中引用属性
使用$引用token或者规则属性,使用%引用模板表达式。

29、模板,既可以在parser中使用,也可以在tree文法中使用。
模板有两种定义方式,一种是嵌入定义方式:
-> template(<<attribute-assignment-list >>) "in-line-template"
如果多行则是这样:
... -> template(?attribute-assignment-list ?)
<<
?in-line-template-spanning-multiple-lines?
>>
另外一种是将模板定义在文件中:
group T;
assign(x,y) ::= "<x> := <y>;"

30、
semantic predicates有三种形式:
{布尔表达式}? 放在选项前面
{布尔表达式}? 放在选项后面,作验证之用。
{布尔表达式}?=> 放在选项前面,作开关之用。
31、
[\x80-\xff]{2} 可以匹配一个汉字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值