antlr4使用

一、antlr的简介以及相关的准备处理

antlr是指可以根据输入自动生成语法树并可视化的显示出来的开源语法分析器。简洁点说,antlr是用来解决编译、解释等相关的问题的。比如你要新定义一门语言,不管这语言复杂还是简单,都可以通过antlr来写这门语言的编译器以及解释器。

话不多说,使用antlr需要的准备工作有:

1.安装插件

在IDEA里Preference->Plugins里搜索antlr,下载ANTLR V4 gammar plugin插件,并重启IDEA。

2.添加依赖

在项目pom.xml文件中添加antlr的依赖。

代码块

<dependency>
            <groupId>org.antlr</groupId>
            <artifactId>antlr4-runtime</artifactId>
            <version>4.7.1</version>
</dependency>

二、正式使用antlr

1.编写antlr独有的g4文件

g4文件是antlr用来定义语法的文件,一个g4文件例子如下:

2.生成visitor等java类

在IDEA里右键g4文件,弹出的选项中有两个选项:

a.Configure Antlr:这个选项是用来设置要生成的java文件的地址以及包名等等

记得勾选generate parse tree visitor!

b.Generate Antlr Recognizer:这个选项是生成按钮,点击则自动生成

生成完之后会在你设置的包那里出现很多类:

2.编写visitor的实现类

现在需要实现一个calBaseVisitor的子类(calBaseVistor是自动生成的一个实现calVisitor的子类,也可以在这个类上直接去写自己的实现)

下面是calBaseVisitor类的代码:

然后发现现在的每个visit方法带上的标识就是之前写g4文件的#带的标签。实现这些方法就能实现遇到特定标签时需要做的特定事情。返回值则为这个处理之后的表达式的值。

实现一个calBaseVisitor的子类:

完整代码如下:

代码块

package com.qieqie.springboot.antlr;

import com.qieqie.springboot.antlr.gen.CalBaseVisitor;
import com.qieqie.springboot.antlr.gen.CalParser;

import java.util.HashMap;
import java.util.Map;

public class CalMyVisitor extends CalBaseVisitor {
    private Map<Integer,Double> indexValueMap = new HashMap<>();


    @Override
    public Object visitProg(CalParser.ProgContext ctx) {
        return super.visitProg(ctx);
    }

    @Override
    public Object visitIF(CalParser.IFContext ctx) {
        if((Boolean)visit(ctx.bool())){
            return visit(ctx.expr(0));
        }else {
            return visit(ctx.expr(1));
        }
    }

    @Override
    public Object visitNUMBER(CalParser.NUMBERContext ctx) {
        String index = ctx.getText();
        Double number = Double.valueOf(index.substring(1,index.length()));
        return number;
    }

    @Override
    public Object visitParens(CalParser.ParensContext ctx) {
        return visit(ctx.expr());
    }

    @Override
    public Object visitMulDiv(CalParser.MulDivContext ctx) {
        Double left=(Double)visit(ctx.expr(0));
        Double right=(Double)visit(ctx.expr(1));
        if(ctx.op.getType()==CalParser.DIV){
            if(right == 0.0){
                System.out.println("divided by zero");
                return 0;
            }else {
                return left/right;
            }
        }
        else
            return left*right;
    }

    @Override
    public Object visitAddSub(CalParser.AddSubContext ctx) {
        Double left=(Double)visit(ctx.expr(0));
        Double right=(Double)visit(ctx.expr(1));
        if(ctx.op.getType()==CalParser.ADD)
            return left+right;
        else
            return left-right;
    }

    @Override
    public Object visitINDEX(CalParser.INDEXContext ctx) {
        String index = ctx.getText();
        Integer indexId = Integer.valueOf(index.substring(1,index.length()));
        return indexValueMap.get(indexId);
    }

    @Override
    public Object visitSimpleCompareE(CalParser.SimpleCompareEContext ctx) {
        Double left = (Double)visit(ctx.expr(0));
        Double right = (Double)visit(ctx.expr(1));
        if(ctx.op.getType() == CalParser.GREATEREQUALS){
            if(left>=right){
                return true;
            }
            return false;
        }else if(ctx.op.getType() == CalParser.SMALLEREQUALS){
            if(left<=right){
                return true;
            }
            return false;
        }else {
            if(left == right){
                return true;
            }
            return false;
        }
    }

    @Override
    public Object visitSimpleCompare(CalParser.SimpleCompareContext ctx) {
        Double left = (Double)visit(ctx.expr(0));
        Double right = (Double)visit(ctx.expr(1));
        if(ctx.op.getType() == CalParser.GREATER){
            if(left>right){
                return true;
            }
            return false;
        }else {
            if(left<right){
                return true;
            }
            return false;
        }
    }

    @Override
    public Object visitAND(CalParser.ANDContext ctx) {
        for(CalParser.BoolContext bool:ctx.bool()){
            if(! (Boolean)visit(bool)){
                return false;
            }
        }
        return true;
    }

    public Map<Integer, Double> getIndexValueMap() {
        return indexValueMap;
    }

    public void setIndexValueMap(Map<Integer, Double> indexValueMap) {
        this.indexValueMap = indexValueMap;
    }
}

这样就能把各种情况需要的各种处理给实现完了。

3.使用自定义的visitor来解释一个示例:“IF(#2>@24,#2+@10*#3,#3)”

运行结果:

符合需要的结果。大功告成。

猜你喜欢

转载自blog.csdn.net/fxjwj1997518/article/details/86678457