这个博客,讲得很细了:
http://codemany.com/blog/reading-notes-the-definitive-antlr4-reference-part1/
ANTLR v4是一款强大的语法分析器生成器,可以用来读取,处理,执行和转换结构化文本或二进制文件。通过文法文件,ANTLR可以自动生成词法分析器、语法分析树和树遍历器。
两种。词法和语法。词法是大写的,语法是小写的。类似正则表达式的方式进行组合。
比如下面的,s是语法,ID是词法。
grammar Hello; // 定义文法的名字
s : ‘hello’ ID ; // 匹配关键字hello,后面跟着一个标志符
ID : [a-z]+ ; // 匹配小写字母标志符
WS : [ \t\r\n]+ -> skip ; // 跳过空格、制表符、回车符和换行符
可以生成 HelloLexer、HelloParser、HelloVisitor、HelloListener 这几个java文件,来进行处理。
Visitor的方式,通过extends自动生成的基类,在里面实现自己想要的功能。通过context.rule_name(),context.op,context.sign 等方式,获得想要的内容。并且,提供了visitRuleName()的方法,只需重载它们即可实现自己想要的操作。返回的也是 T ,可以实现类似四则运算的功能。
比如下面,是其中一个rule(就是语法)的visit方式:
/** expr op=('*'|'/') expr */
@Override
public Integer visitMulDiv(CalcParser.MulDivContext ctx) {
int left = visit(ctx.expr(0)); // get value of left subexpression
int right = visit(ctx.expr(1)); // get value of right subexpression
if ( ctx.op.getType() == CalcParser.MUL ) return left * right;
return left / right; // must be DIV
}
而另一种方式,listener,暂时不明白怎么用。不需要像visitor这样
一些注意的地方:
各个语法是有顺序的,比如 rule : rule_a | rule_b ,这里如果 rule_a 符合,则不会进入到rule_b。
对于各个变量,比如开始日期写到的“每”“星期”等,这些最好不要直接出现在文法里(antlr会自动帮你生成对应的词法),不如自己优先定义好。
遇到另一个坑是,“十一期间”“十一月的时候”,这些节假日坑… 所以要首先对节假日进行处理。
另外,补下编译原理的事情。
自顶向下,LL(1)文法,对所给文法需计算FIRST、FOLLOW、SELECT集合。
自底向上, LR(0),做规约。
嗯。大概都忘了…
http://www.cnblogs.com/blacksword/archive/2012/01/09/2316835.html