ANTLR 入门(未完待续)

ANTLR是什么

ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files. It’s widely used to build languages, tools, and frameworks. From a grammar, ANTLR generates a parser that can build and walk parse trees.

简单的说就是一个语言识别器,什么时候会用到呢?当你想构建自己的DSL(Domain Specific Language)就会用到了.编译语言的前面的步骤就是词法分析,和语法分析.而ANTLR就能帮助我们简化这个过程,通过简单的配置就能生成词法分析器和语法分析器,极大提高了效率.

快速开始

安装和简单入门都很简单,官网有详细介绍

最重要的资源是他们的官方的例子,模仿是学习新东西很好的一个手段.除了这些我还推荐一个超级好用的插件,一个IntelliJ Idea的插件,貌似也是官方的,地址在这里

练习

我之前写过一个简单的四则运算的解析器,现在我们尝试用ANTLR实现一个最简单的加减运算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
grammar Calculator;

// SKIP
SPACE: [ \t\r\n]+ -> channel(HIDDEN);

expr: atom (op atom)*
;

atom:
INT
;
op
: ADD|SUB
;

ADD : '+' ;
SUB : '-' ;
INT : [0-9]+ ;

完成后生成Java代码,然后实现一个CalculatorBaseListener,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package Calculator;

import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

/**
* Created by charles on 2017-十二月-1.
*/
public class MyHandler extends CalculatorBaseListener {


private Integer result = null;
private String op = null;


@Override
public void exitAtom(CalculatorParser.AtomContext ctx) {
Integer atom = Integer.valueOf(ctx.getText());
if (null == result) {
result = atom;
} else if (op != null) {
switch (op) {
case "+":
result += atom;
break;
case "-":
result -= atom;
break;
default:
break;

}
}
}

@Override
public void exitOp(CalculatorParser.OpContext ctx) {
op = ctx.getText();
}

@Override
public void exitExpr(CalculatorParser.ExprContext ctx) {
System.out.println("result:" + result);
}

public static void main(String[] args) {
String cal = "1+2+3-3-2+5+2+3";
CharStream input = CharStreams.fromString(cal);
CalculatorLexer lexer = new CalculatorLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CalculatorParser parser = new CalculatorParser(tokens);
MyHandler handler = new MyHandler();
ParseTreeWalker.DEFAULT.walk(handler, parser.expr());
}


}

运行一下试试,虽然例子非常简单,但是还是把最核心的展示出来了.