本文主要是介绍java-在ANTLR中,如何使用生成的Listener代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
测试基本环境
- windows 10
- java 19
- antlr 4.13.1
使用场景
主要是通过实现ParseTreeListener 的接口实现自己的业务逻辑,从而构建自己的程序。
Listener概要
- 生成java代码后,会有两个listener的类,HelloListener是接口,HelloBaseListener是实现。
D:\源码\kafka-2.1\antlr\gen\HelloBaseListener.java
D:\源码\kafka-2.1\antlr\gen\HelloListener.java
- HelloBaseListener和HelloListener是根据定义的语法生成的,其中HelloListener继承ParseTreeListener。
public class HelloBaseListener implements HelloListener {public interface HelloListener extends ParseTreeListener {
- 要触发Listener的事件,需要使用ParseTreeWalker对树进行遍历。
十进制转十六进制样例
这个样例主要是将字符串中的数字转换为16进制,然后按格式原样输出。如何生成ANTLR的java代码过程忽略了,可以参考之前的文章
https://blog.csdn.net/m0_60688978/article/details/141937659
Hello.g4文件
这是对字符串5{42,43,{32,3,5},44}ddd中的花括号里面的进行转换,
grammar Hello;
line:'{' value(','value)* '}';
value:INT| line;
INT:[0-9]+;
其实写成这样也没有问题?
grammar Hello;
line:'{' value(','value)* '}';
value:INT| line;
INT:[0-9]+;
main文件
这里需要继承HelloBaseListener,继承后你可以只需要重写enterLine、exitLine、enterValue就可以了,其他的方法根据情况来。代码如下:
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;public class main {public static void main(String[] args) {//需要分析的语句String inputStr="5{42,43,{32,3,5},44}ddd";//将字符串转换为ANTLR的CharStreamCharStream input = CharStreams.fromString(inputStr);//使用词法分析器分析转换后的输入Lexer lexer = new HelloLexer(input);//新建一个词法符号的缓冲区,存储生成的词法符号CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);//使用语法分析器处理缓冲区的内容HelloParser helloParser = new HelloParser(commonTokenStream);//对第一个line规则进行语法分析ParseTree parseTree = helloParser.line();//获取树的子数目int childCount = parseTree.getChildCount();//打印LISP风格的树System.out.println(parseTree.toStringTree());//循环打印出子节点for (int i = 0; i < childCount; i++) {System.out.println("child "+i+":"+parseTree.getChild(i).toStringTree());}catToDog cc=new catToDog();ParseTreeWalker walker=new ParseTreeWalker();walker.walk(cc,parseTree);}public static class catToDog extends HelloBaseListener {StringBuilder s=new StringBuilder();@Overridepublic void enterLine(HelloParser.LineContext ctx) {s.append("{");}@Overridepublic void exitLine(HelloParser.LineContext ctx) {s.append("},");System.out.println(s.toString().replaceAll(",}","}").substring(0,s.toString().replaceAll(",}","}").length()-1));}@Overridepublic void enterValue(HelloParser.ValueContext ctx) {if(null!=ctx.INT()){System.out.println("enterValue:"+ctx.INT().getText());s.append(Integer.toHexString(Integer.parseInt(ctx.INT().getText()))+",");}}}
}
打印结果
line 1:0 extraneous input '5' expecting '{'
line 1:20 token recognition error at: 'd'
line 1:21 token recognition error at: 'd'
line 1:22 token recognition error at: 'd'
([] 5 { ([5] 42) , ([7] 43) , ([7] ([16 7] { ([5 16 7] 32) , ([7 16 7] 3) , ([7 16 7] 5) })) , ([7] 44) })
child 0:5
child 1:{
child 2:([5] 42)
child 3:,
child 4:([7] 43)
child 5:,
child 6:([7] ([16 7] { ([5 16 7] 32) , ([7 16 7] 3) , ([7 16 7] 5) }))
child 7:,
child 8:([7] 44)
child 9:}
enterValue:42
enterValue:43
enterValue:32
enterValue:3
enterValue:5
{2a,2b,{20,3,5}
enterValue:44
{2a,2b,{20,3,5},2c}
可以看到,没有在花括号里面的d字母有提示没有识别到,最后成功的将字符串5{42,43,{32,3,5},44}ddd中花括号的十进制原格式转换为了十六进制{2a,2b,{20,3,5},2c}。
这篇关于java-在ANTLR中,如何使用生成的Listener代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!