强大的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
    }
相关推荐
Code额8 分钟前
Python 连接 DeepSeek API,OpenAI 对话方式总结
后端·python·ai·ai编程
星火10249 分钟前
【LangChain4j系列10】Guardrails 安全护栏
人工智能·后端
四千岁10 分钟前
稀疏向量BM25Retriever不支持中文怎么办?jieba来帮忙
前端·javascript·后端
用户69190268133912 分钟前
Docker基本概念
后端·docker·容器
颜进强14 分钟前
14 - OpenSpec 老页面改造骨架:定位 + 增量 + 回归三件套
前端·后端·ai编程
唐青枫15 分钟前
别只把 switch 当成多路 if:Zig 模式匹配、状态机与 Tagged Union 实战
后端
步行cgn19 分钟前
MyBatis 错误 Result Maps collection does not contain value for ... 详解与解决方案
后端
用户2506949216122 分钟前
Cordis 从入门到实战:插件卸载后,别留下一地鸡毛
后端
Elastic 中国社区官方博客29 分钟前
Elasticsearch:什么是向量数据库?
大数据·运维·数据库·人工智能·elasticsearch·搜索引擎·ai
SomeB1oody35 分钟前
【RustyML入门】5.3. 聚类指标
开发语言·后端·机器学习·rust·教程