java-在ANTLR中,如何使用生成的Listener代码

测试基本环境

  1. windows 10
  2. java 19
  3. antlr 4.13.1

使用场景

实现ParseTreeListener 的接口实现自己的业务逻辑,在通过Listener遍历,从而构建自己的程序。

Listener概要

  1. 生成java代码后,会有两个listener的类,HelloListener是接口,HelloBaseListener是实现。

D:\源码\kafka-2.1\antlr\gen\HelloBaseListener.java
D:\源码\kafka-2.1\antlr\gen\HelloListener.java

  1. HelloBaseListener和HelloListener是根据定义的语法生成的,其中HelloListener继承ParseTreeListener。
public class HelloBaseListener implements HelloListener {

public interface HelloListener extends ParseTreeListener {

  1. 要触发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的CharStream
        CharStream 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();

        @Override
        public void enterLine(HelloParser.LineContext ctx) {
            s.append("{");
        }

        @Override
        public void exitLine(HelloParser.LineContext ctx) {
            s.append("},");
            System.out.println(s.toString().replaceAll(",}","}").substring(0,s.toString().replaceAll(",}","}").length()-1));
        }

        @Override
        public 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}。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值