JAVA动态表达式:Antlr4 G4 模板 + 读取字符串表达式结构树

安装antlr4插件

创建一个后缀是g4的文件

grammar Expr;

expression :
             '(' expression ')'          # parens
            | expression 'and' expression # andOp
            | expression 'or' expression  # orOp
            | '@' VARNAME comparison_op NUMBER # comparison
            | '@' VARNAME comparison_op STRING # comparison
            | '@' NUMBER comparison_op NUMBER # comparison
            | '@' STRING comparison_op STRING # comparison
            | '@' VARNAME comparison_op VARNAME # comparison
            | '@' VARNAME contains_op VARNAME # comparison
            | '@' VARNAME contains_op NUMBER # comparison
            | '@' VARNAME contains_op STRING # comparison
            | '@' STRING contains_op STRING # comparison
            |  VARNAME comparison_op NUMBER # comparison
            |  VARNAME comparison_op STRING # comparison
            |  NUMBER comparison_op NUMBER # comparison
            |  STRING comparison_op STRING # comparison
            |  VARNAME comparison_op VARNAME # comparison
            |  VARNAME contains_op VARNAME # comparison
            |  VARNAME contains_op NUMBER # comparison
            |  VARNAME contains_op STRING # comparison
            |  STRING contains_op STRING # comparison
            ;

comparison_op : '<' | '<=' | '>' | '>=' | '==' | '!=';
contains_op: 'contains' | 'notcontains';

STRING : '\'' ( '\\' . | '\\\'' | ~[\\'] )* '\'';
NUMBER : '-'? [0-9]+ ('.' [0-9]+)?;
VARNAME : [a-zA-Z_][a-zA-Z_0-9]*;
WS : [ \t\r\n]+ -> skip; // 忽略空白字符
fragment Letter: [a-zA-Z];
fragment Digit: [0-9];
fragment ChineseCharacter: [\u4e00-\u9fa5];

上面的文件可以直接解析如下格式的表达式:

@prices == 1 and (@val >=1 or @name<=4) and 1==1 and '2'=='3' and '1123' contains '1' and '23455' notcontains '5'

右键生成代码

 引入POM

 <!--动态表达式-->
        <dependency>
            <groupId>org.antlr</groupId>
            <artifactId>antlr4</artifactId>
            <version>4.10.1</version>
        </dependency>

 测试表达式结构

 @Test
    public  void  Test00(){
        // 构建字符流
        CodePointCharStream charStream = CharStreams.fromString("@prices == 1 and (@val >=1 or @name<=4) and 1==1 and '2'=='3' and '1123' contains '1' and '23455' notcontains '5'");

        // 从字符流分析词法, 解析为token
        ExprLexer lexer = new ExprLexer(charStream);

        // 从token进行分析
        ExprParser parser = new ExprParser(new CommonTokenStream( lexer) );

        // 使用监听器,遍历语法树,根据语法定义,prog为语法树的根节点
        ParseTree prog = parser.expression();

        // 创建监听器
        CustomerExprListener listener = new CustomerExprListener();


        // 遍历AST并使用监听器处理
        ParseTreeWalker walker = new ParseTreeWalker();
        walker.walk(listener, prog);

        // 打印生成的语法树
        //System.out.println( prog.toStringTree(parser));

    }

拿到表达式以后,就可以把结果处理成实际业务想要的对象了

package com.java.core.web.antlr4;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;

public class CustomerExprListener  extends ExprBaseListener{
    @Override
    public void enterEveryRule(ParserRuleContext ctx) {
        //System.out.println("Entering rule: " + ctx.getText());
    }

    @Override
    public void exitEveryRule(ParserRuleContext ctx) {
        //System.out.println("Exiting rule: " + ctx.getText());
    }

    @Override
    public void visitTerminal(TerminalNode node) {
        System.out.println("Visiting terminal: " + node.getText());
    }

    @Override
    public void visitErrorNode(ErrorNode node) {
        //System.out.println("Visiting error: " + node.getText());
    }
}

监听输出的内容


Visiting terminal: @
Visiting terminal: prices
Visiting terminal: ==
Visiting terminal: 1
Visiting terminal: and
Visiting terminal: (
Visiting terminal: @
Visiting terminal: val
Visiting terminal: >=
Visiting terminal: 1
Visiting terminal: or
Visiting terminal: @
Visiting terminal: name
Visiting terminal: <=
Visiting terminal: 4
Visiting terminal: )
Visiting terminal: and
Visiting terminal: 1
Visiting terminal: ==
Visiting terminal: 1
Visiting terminal: and
Visiting terminal: '2'
Visiting terminal: ==
Visiting terminal: '3'
Visiting terminal: and
Visiting terminal: '1123'
Visiting terminal: contains
Visiting terminal: '1'
Visiting terminal: and
Visiting terminal: '23455'
Visiting terminal: notcontains
Visiting terminal: '5'

可以把监控的类提取出来

/**
     * 遍历语法树节点
     * @param tree
     */
    public static RuleTest traverseTree(ParseTree tree, String name, RuleTest ruleTest) {
        //自定义变量
        // public String type; //类型 1-属性 2-值 (由比较操作符决定)
        // public String group; //组 0-不用添加组 1-需要添加组 (由连续小括号的数量决定,如果两个符号连续都是小括号,那么系统会认为是一个组)
        // public String bracket;//括号 判断是否是组 (小括号的数量记录)
        // public String isObject;//是否new object (条件对象 0-不创建 1-创建 由逻辑运算符决定 如 and/or)

        if (tree instanceof TerminalNode) {
            TerminalNode terminalNode = (TerminalNode) tree;
            //得到树节点
            String text = terminalNode.getText();
            //获取条件组
            List<Condition> list = ruleTest.getConditionList();
            //判断节点类型 (比较操作符/逻辑运算符号/小括号/中括号/@符)
            int res = CheckSymbolOptions.getNameOrValue(text);
            if (res == 1){ //比较操作符
                ruleTest.setType("2");
                ruleTest.setEndBracket("0");
                if (ruleTest.getGroup() == null || ruleTest.getGroup().equals("0")){
                    if (list.size()>0){
                        Condition condition = list.get(list.size()-1);
                        String symbolOptions = SymbolOptions.getNameOrValue(text);
                        condition.setCompareOperation(symbolOptions);//比较操作(操作符)
                    }
                }else{
                    Condition cond = list.get(list.size()-1);
                    List<Condition> conditionList = cond.getConditionList();
                    if (conditionList.size()>0){
                        Condition condition = conditionList.get(conditionList.size()-1);
                        String symbolOptions = SymbolOptions.getNameOrValue(text);
                        condition.setCompareOperation(symbolOptions);//比较操作(操作符)
                    }
                }

            }else if (res ==2){ //逻辑运算符
                if (ruleTest.getGroup() == null || ruleTest.getGroup().equals("0")){
                    //添加条件对象
                    Condition condition = addCondition(name,"symbol",text);
                    list.add(condition);
                    ruleTest.setIsObject("1");//需要添加条件对象  0-不添加 1-添加
                }else{
                    Condition cond = list.get(list.size()-1);
                    List<Condition> conditionList = cond.getConditionList();
                    //添加条件对象
                    Condition condition = addCondition(name,"symbol",text);
                    conditionList.add(condition);
                    ruleTest.setIsObject("1");//需要添加条件对象  0-不添加 1-添加
                }
            }else if (res==3){ //括号标识符
                if (text.equals("(")){
                    ruleTest.setType("1");
                    if (ruleTest.getBracket()==null || ruleTest.getBracket().equals("0")){
                        ruleTest.setBracket("1");
                    }else{
                        int va = Integer.valueOf(ruleTest.getBracket())+1;
                        ruleTest.setBracket(String.valueOf(va));
                        if (va==2){
                            if (list== null){
                                list = new ArrayList<>();
                            }
                            ruleTest.setGroup("1");
//                            if (list.size()==0){
//                                Condition condition = addCondition(name,"group",null);
//                                int endva = Integer.valueOf(ruleTest.getSubscript())+1;
//                                ruleTest.setSubscript(String.valueOf(endva));//记录下标
//                                condition.setTierIndex(String.valueOf(endva));
//                                list.add(condition);
//                                ruleTest.setConditionList(list);
//                            }
                            //创建对象
                            Condition condition = addCondition(name,"group",null);
                            condition.setDescribe(null);
                            int endva = Integer.valueOf(ruleTest.getSubscript())+1;
                            ruleTest.setSubscript(String.valueOf(endva));//记录下标
                            condition.setTierIndex(String.valueOf(endva));
                            list.add(condition);
                            ruleTest.setConditionList(list);
                            ruleTest.setIsObject("0");//添加对象后回复初始状态
                        }
                        ruleTest.setBracket("0");
                    }
                    if (ruleTest.getId()==null){
                        //设置rule属性
                        ruleTest.setId(generateId("rule"));//id需要自动生成 rule_xxxxxxxxxx(10位数)
                        ruleTest.setName(name);
                        ruleTest.setSubscript("1");//记录索引
                        ruleTest.setTierIndex("1");//层级索引 需要确定来源
                    }
                }
                if (text.equals(")")){
                    if (ruleTest.getEndBracket()==null || ruleTest.getEndBracket().equals("0")){
                        ruleTest.setEndBracket("1");
                    }else{
                        int endva = Integer.valueOf(ruleTest.getEndBracket())+1;
                        ruleTest.setEndBracket(String.valueOf(endva));
                    }
                    if (ruleTest.getEndBracket().equals("2")){
                        ruleTest.setGroup("0");
                    }
                }
            }else if (res ==4){ //@ 参数标识
                ruleTest.setType("1");
            }else {
                //初始化对象与集合
                if (list== null || list.size()==0){
                    list = new ArrayList<>();
                    Condition condition = addCondition(name,"single",null);
                    list.add(condition);
                    ruleTest.setConditionList(list);
                }
                if (ruleTest.getGroup() == null || ruleTest.getGroup().equals("0")){
                    if (ruleTest.getIsObject()!=null){
                        if (ruleTest.getIsObject().equals("1")){
                            //创建对象
//                            Condition condition = new Condition();
                            Condition condition = addCondition(name,"single",null);
                            list.add(condition);
                            ruleTest.setIsObject("0");//添加对象后回复初始状态
                        }
                    }
                }else{
                    if (ruleTest.getIsObject()!=null){
                        if (ruleTest.getIsObject().equals("1")) {
                            Condition cond = list.get(list.size()-1);
                            List<Condition> conditionList = cond.getConditionList();
                            //创建对象
                            Condition addCondition = addCondition(name,"single",null);
                            conditionList.add(addCondition);
                            ruleTest.setIsObject("0");//添加对象后回复初始状态
                        }
                    }
                }
                if (list.size()>0){
                    if (ruleTest.getGroup()== null || ruleTest.getGroup().equals("0") ){
                        //获取属性详情,判断属性是否存在,如果存在拿到属性名称、类型等信息
                        String type = DataType.getDataType("5000"); //此处需要替换
                        Condition condition = list.get(list.size()-1);
                        if (condition.getLeftOperatorExpression()==null || condition.getRightOperatorExpression()==null ){
                            if (ruleTest.getType().equals("1")){
                                //创建左边运算符表达式
                                LeftOperatorExpression left = addLeftOperatorExpression(type,text);
                                condition.setLeftOperatorExpression(left);
                                ruleTest.setType("0");
                            }
                            if (ruleTest.getType().equals("2")){
                                //创建右边运算符表达式
                                RightOperatorExpression right = addRightOperatorExpression(type,text);
                                condition.setRightOperatorExpression(right);
                                ruleTest.setType("0");
                                ruleTest.setBracket("0");
                            }
                        }
                    }else{
                        if (ruleTest.getGroup().equals("1")){
                            String type = DataType.getDataType("5000"); //此处需要替换
                            Condition cond = list.get(list.size()-1);
//                            Rule rule = cond.getRule();
                            List<Condition> conditionList = cond.getConditionList();
                            //初始化对象与集合
                            if (conditionList== null || conditionList.size()==0){
                                conditionList = new ArrayList<>();
                                Condition condition = addCondition(name,"single",null);
                                if (condition.getLeftOperatorExpression() == null || condition.getRightOperatorExpression() == null) {
                                    if (ruleTest.getType().equals("1")) {
                                        //创建左边运算符表达式
                                        LeftOperatorExpression left = addLeftOperatorExpression(type, text);
                                        condition.setLeftOperatorExpression(left);
                                        ruleTest.setType("0");
                                    }
                                    if (ruleTest.getType().equals("2")) {
                                        //创建右边运算符表达式
                                        RightOperatorExpression right = addRightOperatorExpression(type, text);
                                        condition.setRightOperatorExpression(right);
                                        ruleTest.setType("0");
                                        ruleTest.setBracket("0");
                                    }
                                }
                                conditionList.add(condition);
                                cond.setConditionList(conditionList);
                            }else{
                                Condition condition = conditionList.get(conditionList.size()-1);
                                if (condition.getLeftOperatorExpression() == null || condition.getRightOperatorExpression() == null) {
                                    if (ruleTest.getType().equals("1")) {
                                        //创建左边运算符表达式
                                        LeftOperatorExpression left = addLeftOperatorExpression(type, text);
                                        condition.setLeftOperatorExpression(left);
                                        ruleTest.setType("0");
                                    }
                                    if (ruleTest.getType().equals("2")) {
                                        //创建右边运算符表达式
                                        RightOperatorExpression right = addRightOperatorExpression(type, text);
                                        condition.setRightOperatorExpression(right);
                                        ruleTest.setType("0");
                                        ruleTest.setBracket("0");
                                    }
                                }
                            }

                        }

                    }
                }
            }
        }
        //递归 循环遍历
        for (int i = 0; i < tree.getChildCount(); i++) {
            traverseTree(tree.getChild(i),name,ruleTest);
        }
        return ruleTest;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/701065.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JS基础与高级应用: 性能优化

在现代Web开发中&#xff0c;性能优化已成为前端工程师必须掌握的核心技能之一。本文从URL输入到页面加载完成的全过程出发&#xff0c;深入分析了HTTP协议的演进、域名解析、代码层面性能优化以及编译与渲染的最佳实践。通过节流、防抖、重复请求合并等具体技术手段&#xff0…

人工智能GPT-4o?

对比分析 在讨论GPT-4o时&#xff0c;我们首先需要了解其前身&#xff0c;即GPT-4&#xff0c;以及其之前的版本。GPT系列从GPT-1到GPT-4经历了多次迭代&#xff0c;每一次都带来了显著的进步。 GPT-4 vs GPT-4o&#xff1a; 1. **参数规模&#xff1a;** GPT-4o在参数规模上…

Git仓库中文件的状态

0 Preface/Foreword 1 文件状态 文件包含以下4个状态&#xff1a; untracked&#xff0c;未跟踪&#xff0c;表示该文件在文件夹中&#xff0c;但是没有加入到git 仓库中进行版本管控。可以通过git add命令将该文件增加到git 仓库中。从untracked变为staged。unmodified&…

论文中表格跨页了做续表的正确方法

在上方加表格 粘贴即可 文章来源于论文中表格跨页了做续表的正确方法&#xff01;论文人快来学习_哔哩哔哩_bilibili 小姐姐用WPS弄的&#xff0c;微软的不理想&#xff0c;我试了试&#xff0c;觉得在上面增加格子再粘贴表头&#xff0c;效果还行

软件工程期末复习题

目录 选择 判断 选择 下列说法中正确的是 ( B )。 A、20 世纪50 年代提出了软件工程的概念摇 B、20 世纪60 年代提出了软件工程的概念 C、20 世纪70 年代出现了客户端/ 服务器技术 D、20 世纪80 年代软件工程学科达到成熟 软件危机的主要原因是 ( D )。 A、软件工具落后…

下载使用nginx发布html自定义页面

在浏览器搜索nginx.org&#xff0c;然后点击download&#xff0c;接着点击 stable and mainline 选择自己所使用系统对应的信息后点击&#xff08;我用的是CentOS&#xff0c;所以需要点击RHEL and derivatives&#xff09; vim /etc/yum.repos.d/nginx.repo [nginx-stable] n…

SpringCloud-面试篇(二十五)

&#xff08;1&#xff09;Sentinel与Hystix的线程隔离有什么差别&#xff1f; &#xff08;2&#xff09;Sentinel的限流与Gateway限流有什么差别 固定窗口计数器算法&#xff0c;可能再其他的时间两个窗口的交界内超过了请求阈值 &#xff0c;所以就有了滑动窗口算法 滑动窗…

Docker引起的漏洞问题

前言 测试环境上的中间件和java应用都是由docker进行部署的,但是因为docker的镜像访问有时候需要外网,由此引发了问题,在docker文件中 /usr/lib/systemd/system/docker.service 原有的配置为,可以看到进行了加密 ExecStart/usr/bin/dockerd --tlsverify --tlscacert/etc/docker…

上海斯歌荣获“2023年度杰出数字化转型方案提供商”奖项

为表彰上海斯歌在各行业的数字化转型事业中所做出的突出贡献&#xff0c;经CIO时代、新基建创新研究院专家组评审认定&#xff0c;授予上海斯歌“2023年度杰出数字化转型方案提供商”奖项。荣获该殊荣&#xff0c;不仅是业界对上海斯歌解决方案专业能力及落地实施能力的又一次认…

Java课程设计:基于ssm的旅游管理系统系统(内附源码)

文章目录 一、项目介绍二、项目展示三、源码展示四、源码获取 一、项目介绍 2023年处于信息科技高速发展的大背景之下。在今天&#xff0c;缺少手机和电脑几乎已经成为不可能的事情&#xff0c;人们生活中已经难以离开手机和电脑。针对增加的成本管理和操作,各大旅行社非常必要…

java多线程相关概念

在Java多线程编程中&#xff0c;有几个关键的术语需要理解&#xff1a; 1.线程(Thread)&#xff1a;线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程中的实际运作单位。 2.进程(Process)&#xff1a;进程是系统进行资源分配和调度…

Git使用-gitlab上面的项目如何整到本地的idea中

场景 一般我们在开发项目或者接手某个项目时&#xff0c;基本都要接触Git&#xff0c;比如上传项目代码&#xff0c;下载同事给你的交接代码等等。 这是一个基本功&#xff0c;小小整理一下日常操作中的使用。 第一步&#xff1a;在 GitLab 上找到你要克隆的项目&#xff0c;复…

PDF操作工具

PDF的转换、编辑、删除、文本识别、添加水印等等各种操作用的越来越多&#xff0c;相信很多朋友都有WPS等软件的会员、可是更多的朋友是没开通WPS等软件的会员的&#xff0c;那么怎么办呢&#xff0c;给你们推荐一款pdf操作的工具。 PDF24 Creator是一款免费且流行的 PDF 解决…

5 种技术,可用于系统中的大数据模型

文章目录 一、说明二、第一种&#xff1a;批量大小三、第二种&#xff1a;主动学习四、第三种&#xff1a;增加代币数量五、第四种&#xff1a; 稀疏激活六、第五种&#xff1a;过滤器和更简单的模型后记 一、说明 以下是本文重要观点的摘要。阅读它以获取更多详细信息/获取原…

在欧拉系统中搭建万里数据库MGR集群(图文详解)

在信创和国产化的大趋势下&#xff0c;将各个中间件进行国产化替换是当前非常重要的任务之一。下面将介绍如何在国产化欧拉系统中安装国产万里数据库。 0.MGR简介 MGR&#xff08;MySQL Group Replication&#xff09;&#xff1a;是MySQL官方提供的一种高可用性和容错性解决…

塔勒布作品集合风险共担来应对不确定性、风险、随机性的局限性

Nassim Nicholas Taleb 是一位著名的风险分析学者和作家&#xff0c;他的主要作品被合称为“Incerto”不确定性系列。这些书籍虽然可以独立阅读&#xff0c;但它们在主题和思想上紧密相连&#xff0c;共同探讨了不确定性、风险、随机性和人类在应对这些方面的局限性。 以下是 …

修改注册表默认端口号;telnet端口号失败、不通、没反应;访问另一机器端口不通

背景&#xff1a;在多集群项目中&#xff0c;发现访问其他机器不通。遂使用telnet命令试试&#xff0c;确实端口不通。也查看了防火墙策略等&#xff0c;最后尝试了修改注册表默认端口号。这样端口可通了。但并未实际解决问题&#xff0c;在实际项目中需要确认一下你实际项目中…

Keil MDK 下载安装相对应CPU的Software Packs

要下载MDK ARM的Software Packs&#xff0c;您可以按照以下步骤进行&#xff0c;这些步骤结合了参考文章中的信息并进行了适当的归纳和整理&#xff1a; 1. 访问Keil官网 打开浏览器&#xff0c;访问Keil的官方网站&#xff1a;www.keil.arm.com。 2. 进入Software Packs下载…

解析 Spring 框架中的三种 BeanName 生成策略

在 Spring 框架中&#xff0c;定义 Bean 时不一定需要指定名称&#xff0c;Spring 会智能生成默认名称。本文将介绍 Spring 的三种 BeanName 生成器&#xff0c;包括在 XML 配置、Java 注解和组件扫描中使用的情况&#xff0c;并解释它们如何自动创建和管理 Bean 名称。 1. Be…

STM32硬件接口I2C应用(基于MP6050)

目录 概述 1 STM32Cube控制配置I2C 1.1 I2C参数配置 1.2 使用STM32Cube产生工程 2 HAL库函数介绍 2.1 初始化函数 2.2 写数据函数 2.3 读数据函数 3 认识MP6050 3.1 MP6050功能介绍 3.2 加速计测量寄存器 ​编辑3.3 温度计量寄存器 3.4 陀螺仪测量寄存器 4 MP60…