1. 引言
1.1 什么是 ANTLR
ANTLR(Another Tool for Language Recognition)是一个强大的解析器生成器,用于构建语言解析器、编译器和解释器。
1.2 ANTLR 的历史与发展
ANTLR 由 Terence Parr 创建,最初发布于 1995 年。经过多次版本更新,ANTLR 已成为构建解析器的首选工具之一。
1.3 ANTLR 的应用场景
- 编译器开发:构建自定义编程语言的编译器。
- DSL(领域特定语言):解析和处理特定领域的语言。
- 配置文件解析:解析各种配置文件格式。
- 脚本解释器:构建脚本解释器。
2. 安装与配置
2.1 安装 ANTLR 工具
下载并安装 ANTLR 工具。
# 下载 ANTLR JAR 文件
curl -O https://www.antlr.org/download/antlr-4.9.3-complete.jar
# 将 JAR 文件添加到 PATH
export CLASSPATH=".:/path/to/antlr-4.9.3-complete.jar:$CLASSPATH"
alias antlr4='java -jar /path/to/antlr-4.9.3-complete.jar'
alias grun='java org.antlr.v4.gui.TestRig'
2.2 配置开发环境
使用 IDE(如 IntelliJ IDEA 或 Eclipse)配置 ANTLR 插件。
2.3 创建第一个 ANTLR 项目
创建一个新的 ANTLR 项目并编写简单的文法。
mkdir antlr-example
cd antlr-example
touch Calculator.g4
3. 基本概念
3.1 词法分析器(Lexer)
词法分析器负责将输入字符串分解为一系列词法单元(tokens)。
3.2 语法分析器(Parser)
语法分析器负责根据词法单元生成抽象语法树(AST)。
3.3 抽象语法树(AST)
抽象语法树是一种树状结构,表示输入字符串的语法结构。
4. 编写 ANTLR 文法
4.1 词法规则
定义词法规则,将输入字符串分解为词法单元。
// Calculator.g4
grammar Calculator;
expr: expr ('*' | '/') expr # MulDiv
| expr ('+' | '-') expr # AddSub
| INT # Int
| '(' expr ')' # Parens
;
INT : [0-9]+ ;
WS : [ \t\r\n]+ -> skip ;
4.2 语法规则
定义语法规则,生成抽象语法树。
// Calculator.g4
grammar Calculator;
expr: expr ('*' | '/') expr # MulDiv
| expr ('+' | '-') expr # AddSub
| INT # Int
| '(' expr ')' # Parens
;
INT : [0-9]+ ;
WS : [ \t\r\n]+ -> skip ;
4.3 示例:简单的计算器语言
编写一个简单的计算器语言文法。
// Calculator.g4
grammar Calculator;
expr: expr ('*' | '/') expr # MulDiv
| expr ('+' | '-') expr # AddSub
| INT # Int
| '(' expr ')' # Parens
;
INT : [0-9]+ ;
WS : [ \t\r\n]+ -> skip ;
5. 生成解析器代码
5.1 使用 ANTLR 工具生成代码
使用 ANTLR 工具生成解析器代码。
antlr4 Calculator.g4
5.2 生成的代码结构
生成的代码包括词法分析器和语法分析器类。
CalculatorLexer.java
CalculatorParser.java
CalculatorBaseListener.java
CalculatorListener.java
CalculatorBaseVisitor.java
CalculatorVisitor.java
5.3 示例:生成计算器解析器代码
生成计算器解析器代码并查看生成的类。
antlr4 Calculator.g4
6. 实现解析器
6.1 加载和解析输入
加载输入字符串并使用解析器生成抽象语法树。
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class CalculatorTest {
public static void main(String[] args) throws Exception {
String input = "3 + 5 * (10 - 4)";
CalculatorLexer lexer = new CalculatorLexer(CharStreams.fromString(input));
CommonTokenStream tokens = new CommonTokenStream(lexer);
CalculatorParser parser = new CalculatorParser(tokens);
ParseTree tree = parser.expr();
System.out.println(tree.toStringTree(parser));
}
}
6.2 遍历抽象语法树
遍历抽象语法树并执行计算。
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class CalculatorVisitor extends CalculatorBaseVisitor<Integer> {
@Override
public Integer visitMulDiv(CalculatorParser.MulDivContext ctx) {
int left = visit(ctx.expr(0));
int right = visit(ctx.expr(1));
if (ctx.op.getType() == CalculatorParser.MUL) {
return left * right;
} else {
return left / right;
}
}
@Override
public Integer visitAddSub(CalculatorParser.AddSubContext ctx) {
int left = visit(ctx.expr(0));
int right = visit(ctx.expr(1));
if (ctx.op.getType() == CalculatorParser.ADD) {
return left + right;
} else {
return left - right;
}
}
@Override
public Integer visitInt(CalculatorParser.IntContext ctx) {
return Integer.parseInt(ctx.INT().getText());
}
@Override
public Integer visitParens(CalculatorParser.ParensContext ctx) {
return visit(ctx.expr());
}
}
6.3 示例:实现计算器解析器
实现计算器解析器并执行计算。
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
public class CalculatorTest {
public static void main(String[] args) throws Exception {
String input = "3 + 5 * (10 - 4)"