安装IDEA 插件
1、安装 antlr v4 插件
2、编写 Expr.g4 文件
3、测试
输入表达式进行测试
预期效果
将
static short[] data={1,2,3}
翻译成
static string data="\u001\u002\u003"
即 将一个short数组翻译成16进制字符串。
1、编写批处理文件
编写.g4格式的语法文件
-
ArrayInit必须和文件名ArrayInit.g4匹配。
-
语法分析器的规则必须以小写字幕开头,词法分析器的规则必须大写开头。
//语法文件以grammar开头
//ArrayInit必须和文件名ArrayInit.g4匹配
grammar ArrayInit;
//init规则:匹配一对花括号中的、逗号分隔的value
init : '{' value (',' value)* '}';
//value可以是嵌套的花括号结构,也可以是一个简单整数,即INT词法符号
value : init
| INT
;
//语法分析器的规则必须以小写字幕开头,词法分析器的规则必须大写开头
//词法符号INT,由一个或者多个数字组成
INT : [0-9]+;
//定义词法规则空白符号,丢弃
WS : [\t\r\n]+ -> skip;
测试预览
2、生成代码
右键-> 选择 Generate ANTLR ...
生成的代码如下:
简单介绍一下生成的文件:
- ArrayInitParser.java:包含一个
语法分析器类的定义
,用来识别语法ArrayInit。 - ArrayInitLexer.java:包含一个
词法分析器类的定义
,识别语法中的词法规则和文法规则。 - ArrayInit.tokens:ANTLR会对每个词法符号指定
数字类型
,这个关系保存在该文件中。有时候ANTLR会对一个大的语法切割,生成许多小语法,这个文件可以同步所有小语法的词法符号。 - ArrayInitListener.java ArrayInitBaseListener.java:我们输入的文本会被ANTLR语法分析器转换成一棵语法分析树。遍历这些语法分析树时,遍历器可以触发一系列回调事件。前者是回调事件的
定义
,后者是实现
。后者的好处在于我们可以只重写我们感兴趣的回调。
3、拷贝生成的代码到一个安装包
4、编写处理代码
添加依赖包
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4</artifactId>
<version>4.13.1</version>
</dependency>
因此我们需要重写之前说过的ArrayInitBaseListener类,也就是回调函数实现类:
@Override public void enterInit(ArrayInitParser.InitContext ctx) {
// 将{翻译成"
System.out.print('"');
}
@Override public void exitInit(ArrayInitParser.InitContext ctx) {
// 将 } 翻译成"
System.out.print('"');
}
@Override public void enterValue(ArrayInitParser.ValueContext ctx) {
//将value翻译成位16进制形式
//假定不存在嵌套结构
int value=Integer.valueOf(ctx.INT().getText());
System.out.printf("\\u%04x",value);
}
5、编写主程序
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import java.io.IOException;
public class ArrayInitMain {
public static void main(String[] args) throws IOException {
//新建CharStream,从标准输入读取数据
ANTLRInputStream input = new ANTLRInputStream("{1,2,3}");
//新建词法分析器,处理输入的CharStream
ArrayInitLexer lexer = new ArrayInitLexer(input);
//新建词法符号缓冲区,存储词法分析器生成的词法符号
CommonTokenStream tokens = new CommonTokenStream(lexer);
//新建语法分析器,处理词法符号缓冲区内容
ArrayInitParser parse = new ArrayInitParser(tokens);
//针对init规则,开始语法分析
ParseTree tree = parse.init();
//新建一个能够触发回调函数的语法分析树遍历器
ParseTreeWalker walker=new ParseTreeWalker();
//遍历语法分析过程中生成的语法分析树,触发回调
walker.walk(new ArrayInitBaseListener(),tree);
System.out.println();
}
}
输出结果如下: