antlr是 another tool for language recongnition,用于 词法、语法和语义分析。如果大家仔细看一些开源项目的lib包,会经常看到其包含有antlr.jar文件。
2、使用场景:
设想一个运算的场景,“1+3”为多少,如果通过程序解析这个字符串,可以尝试使用拆解字符串的方法,识别其中的运算符“+”,然后将结果输出,感觉很简单。但是,如果场景变化呢?“1+3-6/2”这个样子的呢,也得改程序?是不是有些头大呢?那么antlr就可以帮助你来解决这个头大的问题。
3、主要内容:
antlr重要包含三个重要的内容,分别是 词法分析、语法分析、语义分析,其各个部分的用途主要如下所示:
词法分析 : (识别出 “1”,“+”,“3”)
(1)逐个字符读取公式源文件
(2)识别公式源文件中的词法单元(Token)
(3)将词法单元传递给语法分析器
(4)词法分析器又叫扫描器(Scanner)
语法分析:(识别1+3)
(1)从词法分析器获得词法单元
(2)利用文法定义验证词法单元组合
(3)构造语法分析树
(4)将语法分析树传递给下一阶段
(5)语法分析器又叫解析器(Parser)
语义分析:(计算结果)
(1)完成语义动作定义
(2)一般在语法分析器中完成语义分析
大致各部分的含义就是,首先 识别出 输入的字符是否正确,其次检验字符之间的运算关系,然后计算得出相关的结果。
4、主要工作:
需要写两个.g的文件,分别是 Expr.g和Eval.g文件,前者生成词法、语法分析相关的java文件,通过编译生成ExprLexer.java、ExprParser.java 和 Expr.tokens文件,后者生成语义分析文件,分别为Eval.java和Eval.tokens文件。
相关的编译方法为:java org.antlr.Tool Expr.g
5、开发环境搭建:
1、配置java环境变量
2、将antlr的相关jar包添加到环境变量中
3、运行 java org.antlr.Tool 进行验证
6、简单代码展示,用于计算简答的加减运算
1)、expr.g
grammar Expr;
options {
language=Java;
output=AST;
ASTLabelType=CommonTree; // type of $stat.tree ref etc...
}
@header {
package test.tool;
}
prog: ( stat {/* System.out.println($stat.tree.toStringTree()); */})+ ;
stat
: expr NEWLINE -> expr
| NEWLINE ->
;
expr: multExpr (('+' ^|'-' ^) multExpr)* ;
multExpr
: atom (('/' ^|'*' ^) atom)*
;
atom
: INT
| DOUBLE
| ID
| '(' ! expr ')' !
;
ID : ('N'|'R'|'A'|'C'|'I'|'D')'B'('S'|'H');
INT : '0'..'9'+ ;
WS : (' '|'\t')+ {skip();} ;
NEWLINE:'\r'? '\n' ;
DOUBLE : (('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9')*) '.' (('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') ('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9')*);
2)Eval.g
tree grammar Eval;
options {
tokenVocab=Expr; // read token types from Expr.tokens file
ASTLabelType=CommonTree; // what is Java type of nodes?
}
@header {
package fanxiqian.tool;(可在此处添加 package和import等相关信息)
}
@members {
…………(可在此处添加java方法)
}
prog: stat+ ;
stat: expr+;
expr returns [double value]
: ^('+' a=expr b=expr) {$value = a+b;} //此处定义了 相关运算符的含义
| ^('-' a=expr b=expr) {$value = a-b;}
| ^('*' a=expr b=expr) {$value = a*b;}
| ^('/' a=expr b=expr) {$value=a/b;}
| INT {$value = Integer.parseInt($INT.text);}
| DOUBLE {$value = Double.parseDouble($DOUBLE.text);}
;
3)通过编译命令,生成相关的java文件
java org.antlr.Tool Expr.g
java org.antlr.Tool Eval.g
4)编写相关的测试类
public class Test
{
public static void main(String[] args) throws Exception
{
ANTLRStringStream input;
ExprLexer lexer;
CommonTokenStream tokens;
ExprParser parser;
String formula="1+3";
//开始解析
formula += "\n";
input = new ANTLRStringStream(formula);
lexer = new ExprLexer(input);
tokens = new CommonTokenStream(lexer);
parser = new ExprParser(tokens);
ExprParser.prog_return r = parser.prog();
// walk resulting tree
CommonTree t = (CommonTree)r.getTree();
CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
Eval walker = new Eval(nodes);
System.out.println(walker.expr());
// }
7,总结
antlr是个强大的公式解析工具,本文只是简单的一个小结,以后遇到相关的使用继续补充吧,欢迎大家补充添加吧。