强大的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
    }
相关推荐
geovindu5 小时前
CSharp: Observer Pattern
开发语言·后端·观察者模式·设计模式·c#·.netcore·行为模式
Flynt6 小时前
把公司项目迁到 Spring Boot 4.0:编译通过只是开始
java·spring boot·后端
IT_陈寒6 小时前
Redis误用keys命令把生产环境搞崩了,血的教训
前端·人工智能·后端
她的男孩6 小时前
多租户和数据权限怎么共存?扒完拦截器注册链路,我找到 4 个隐蔽的坑
java·后端·架构
用户8356290780517 小时前
使用 Python 设置 Excel 页眉和页脚
后端·python
步行cgn7 小时前
IoC 控制反转:从概念到 Spring 的实现
后端
爱勇宝7 小时前
没有 Fn 键关触控板?我做了一个双击即用的 Windows 小工具
前端·后端·程序员
2601_962077987 小时前
Python是一门什么样的语言?
python·编程语言·解释器·编译型·解释型
沙湖遇雨7 小时前
8.ByteBuf 的数据模型、生命周期和内存分配
后端