强大的ANTLR4语法解析器入门demo

前言

最近在寻觅搜索查询中可以对查询语句进行解析的一个工具,然后偶然就发现了这个ANTLR4 (语法用到了正则,有多个语言的支持,你常用的很多SQL的解析都用到他了)。当然语法解析我是一窍不通的,本篇只是简单的通过一个demo来说下简单的使用。官方示例

简单的回顾下正则

因为ANTLR4语法用到了正则

  • | 表示或(多个可以匹配的条件)
    • 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 *
  • ? 配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 ?。
    • 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。
  • ~ 表示取反
  • 范围运算符:.. 或者 -,比如小写字母的表示:'a'..'z' 或者 [a-z]

工具的简单使用

1.IDEA中安装插件

2.简单的分析个查询解析的demo

  • 1.查询单词
  • 2.-是排除特定的单词
  • 3.site:是限定某个范围
  • 4.复杂点的可能就看不懂了,因为各种变量定义到处都是的只不过不妨碍入门(工具嘛先会拿来用
txt 复制代码
//必填项
//文件名为SearchQuery.g4
grammar SearchQuery;

//注意下面定义了很多变量声明
//其实就是定义别名数据、然后使用

//必填项
// 整个查询语句由多个 term 构成 (term为空格隔开的单词)
searchQuery
 : searchTerm* EOF
 ;
 
//匹配的查询内容 必须项
//这里意思每个term可以是site开头的限定域;
//也可以是-开头的排除数据
//每个term是一个单词
searchTerm
 : SITE_INCLUDE
 | SITE_EXCLUDE
 | WORD
 ;

// 匹配包含 site: 但不以 - 开头的项 => 表示包含
//site: 开头后接一个或多个字母、数字、点、冒号、斜杠、减号或下划线的字符串,用于识别类似网站地址的标记。
SITE_INCLUDE
 : 'site:' [a-zA-Z0-9.:/\-_]+
 ;

// 匹配 -site: 开头的项 => 表示排除
SITE_EXCLUDE
 : '-'[a-zA-Z0-9.:/\-_]+
 ;

// 普通词
//因为ANTLR4 不支持\S 所以写成了下面的这种方式
WORD
 : ~[ \t\r\n]+
 ;

// 空格忽略
WS
 : [ \t\r\n]+ -> skip
 ;

3.用安装的插件(ANTLR4)可以进行查看语法树和对写的文件进行一个验证

4.用安装的ANTLR4插件可以进行代码生成

  • 需要填些生成文件的路径和报名

5.实现自己的逻辑

  • 这里生成代码例子是我在网上找的两个个计算器的例子。生成的代码文件名都是固定的

  • 生成代码后,我们还需要要实现自己的逻辑处理(继承后实现自己的逻辑,生成的是默认)

  • ((下面图片右边的东西,可以不指定(就是我们写的变量名)也可以前面是表达式后面用#指定

  • 重写的方法就是上图右侧的四个方法

typescript 复制代码
public class MyCalculatorVisitor extends CalculatorBaseVisitor<Object> {
    @Override
    public Object visitParenExpr(CalculatorParser.ParenExprContext ctx) {
        return visit(ctx.expr());
    }
 
    @Override
    public Object visitMultOrDiv(CalculatorParser.MultOrDivContext ctx) {
        Object obj0 = ctx.expr(0).accept(this);
        Object obj1 = ctx.expr(1).accept(this);
 
        if ("*".equals(ctx.getChild(1).getText())) {
            return (Float) obj0 * (Float) obj1;
        } else if ("/".equals(ctx.getChild(1).getText())) {
            return (Float) obj0 / (Float) obj1;
        }
        return 0f;
    }
 
    @Override
    public Object visitAddOrSubstract(CalculatorParser.AddOrSubstractContext ctx) {
        Object obj0 = ctx.expr(0).accept(this);
        Object obj1 = ctx.expr(1).accept(this);
 
        if ("+".equals(ctx.getChild(1).getText())) {
            return (Float) obj0 + (Float) obj1;
        } else if ("-".equals(ctx.getChild(1).getText())) {
            return (Float) obj0 - (Float) obj1;
        }
        return 0f;
    }
 
    @Override
    public Object visitFloat(CalculatorParser.FloatContext ctx) {
        return Float.parseFloat(ctx.getText());
    }
}

 public static void main(String[] args) {
        String query = "3.1 * (6.3 - 4.51) + 5 * 4";
        //创建一个词法分析器,用于将输入转换为标记
        CalculatorLexer lexer = new CalculatorLexer(new ANTLRInputStream(query));
        // 创建一个解析器,用于将标记转换为AST
        CalculatorParser parser = new CalculatorParser(new CommonTokenStream(lexer));
        // 创建一个AST遍历器,用于计算表达式的值
        CalculatorVisitor visitor = new MyCalculatorVisitor();
        System.out.println(visitor.visit(parser.expr()));  // 25.549
    }
相关推荐
2302_809798321 小时前
【JavaWeb】Docker项目部署
java·运维·后端·青少年编程·docker·容器
zhojiew2 小时前
关于akka官方quickstart示例程序(scala)的记录
后端·scala
sclibingqing2 小时前
SpringBoot项目接口集中测试方法及实现
java·spring boot·后端
JohnYan3 小时前
Bun技术评估 - 03 HTTP Server
javascript·后端·bun
周末程序猿3 小时前
Linux高性能网络编程十谈|C++11实现22种高并发模型
后端·面试
ZHOU_WUYI3 小时前
Flask与Celery 项目应用(shared_task使用)
后端·python·flask
IT_陈寒4 小时前
Element Plus 2.10.0 重磅发布!新增Splitter组件
前端·人工智能·后端
有梦想的攻城狮5 小时前
spring中的@RabbitListener注解详解
java·后端·spring·rabbitlistener