首页 > 编程语言 >java处理逻辑表达式计算问题

java处理逻辑表达式计算问题

时间:2023-04-27 15:45:54浏览次数:32  
标签:逻辑 false pop public java true stack 表达式

在处理SQL的where条件时,发现逻辑运算表达式不是那么简单,并不是一种线型计算结构。

但是表达式树的计算又是SQL查询引擎的核心,SQL的抽象语法树最终还是要转换为表达式树来处理。

所以基于原来的表达式案例,进行简单的升级,写了一个简单的逻辑表达式处理器。

首先我们的逻辑表达式的操作数只有两种true,false,

操作符也只有三种,and(与),or(或),!(非)

我们先写一个antlr的语法文件

grammar LExpr;
@header{package com.example.listeners.expr2;}
s : e ;

e : '(' e ')'       # Atom
  | NOT e           # Not
  | e AND e         # And
  | e OR e             # Or
  | BOOL            # Bool
  ;

AND: 'and' ;
OR : 'or' ;
NOT : '!';
BOOL : 'true' |'false' ;
WS : [ \t\n]+ -> skip ;

基于这个语法文件,我们就得到了基本的词法分析器和语法分析树。

接下来就是如何解析表达式,我们模拟栈机用一个stack来存储操作数

public class TestExpression {

    public static class Evaluator extends LExprBaseListener {
        Stack<Boolean> stack = new Stack<Boolean>();


        @Override
        public void exitNot(LExprParser.NotContext ctx) {
            Boolean pop = stack.pop();
            stack.push(!pop);
        }

        @Override
        public void exitOr(LExprParser.OrContext ctx) {
            Boolean left = stack.pop();
            Boolean right = stack.pop();
            stack.push(left || right);
        }

        @Override
        public void exitBool(LExprParser.BoolContext ctx) {
            String text = ctx.getText();
            if (text.equals("true")) {
                stack.push(true);
            } else {
                stack.push(false);
            }
        }

        @Override
        public void exitAnd(LExprParser.AndContext ctx) {
            Boolean left = stack.pop();
            Boolean right = stack.pop();
            stack.push(left && right);
        }
    }

    public static void main(String[] args) throws Exception {
        String sdl = "! (false or true) and false";
        CodePointCharStream input = CharStreams.fromString(sdl);
        LExprLexer lexer = new LExprLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        LExprParser parser = new LExprParser(tokens);
        parser.setBuildParseTree(true);      // tell ANTLR to build a parse tree
        ParseTree tree = parser.s(); // parse
        // show tree in text form
        System.out.println(tree.toStringTree(parser));

        ParseTreeWalker walker = new ParseTreeWalker();
        TestExpression.Evaluator eval = new TestExpression.Evaluator();
        walker.walk(eval, tree);
        System.out.println("stack result = " + eval.stack.pop());
    }
}

输出:

(s (e (e ! (e ( (e (e false) or (e true)) ))) and (e false)))
stack result = false

 除此之外,还可以使用访问者模式来遍历表达式树,或者用Map存储树的每个节点的值,最终的结果都是一样的。

标签:逻辑,false,pop,public,java,true,stack,表达式
From: https://www.cnblogs.com/wangbin2188/p/17359105.html

相关文章

  • JSON数据和JAVA对象之间的转换
    转:https://blog.csdn.net/qq_39975542/article/details/123947872方法1:利用阿里巴巴开源的fastjson包进行JAVA对象和JSON字符串进行转换。C++中的结构体在JAVA中用对象表示,目录结构如下: Peron类内容如下,对应C++中的Person结构体:packagecom.company;publicclassPerson{......
  • vue3 ts 写搜索联系人功能逻辑
    vue3ts写搜索联系人功能vue<inputtype="text"v-model="search"placeholder="Searchcontacts"><templatev-for="(item,index)infilteredData":key="index">ts!search.value表示如果search.value为空或......
  • 【SWITCH】java中的switch,一直没发现的错误
    关于switch-case的的使用误区先看一段代码Integerbb=1;switch(bb){case1:System.out.println(1);case2:System.out.println(2);default:System.out.println(3);}会打印什么呢?只打印1,还是会打印123呢?答案是:123我......
  • 软件测试选择学习java还是python?
     你好,我是小牛。当你学完软件测试基本理论,掌握业务测试流程,功能测试可以搞定,数据库和linux玩的也很溜时,接下来想进一步进阶,那么学习一门编程语言必不可少。同时,学习一门编程语言也是你成为自动化测试工程师乃至测试开发工程师的基本准入门槛。目前,编程语言五花八门,比如很多人大学......
  • JavaScript把数字转为汉字数字的function
    functionnumberToChinese(num){vardigits=["","一","二","三","四","五","六","七","八","九"];varunits=["","十",&quo......
  • java 格式化输出当前时间
    /***打印当前时间**@return*/publicstaticvoidprintCurrentTime(Stringparam){SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss");//关键所在TimeZonegmt=TimeZone.getTimeZone("GMT+8");sdf.setTimeZone(gmt);......
  • Java学习笔记(七)
    1、继承的注意事项子类继承父类时,没有继承父类的构造方法当一个类没有使用extends指定继承哪个父类时,则系统默认继承Object类在Java中,Object类是所有类的父类也叫做超类子类继承了父类,就继承了父类的方法和属性。Java不支持多继承,但支持多层继承2、对方法重写的理解方......
  • Java对象组成部分
    节选自《深入理解JAVA虚拟机》:在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(InstanceData)和对齐填充(Padding)。HotSpot虚拟机的对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有......
  • Java的初始化块
    三种初始化数据域的方法:在构造器中设置值在声明中赋值初始化块(initializationblock)初始化块在一个类的声明中,可以包含多个代码块。只要构造类的对象,这些块就会被执行。classEmployee{privatestaticintnextId;privateintid;privateStringname;......
  • java获取当前年份、月份和日期
    创建一个Calendar类的实例对象,Calendar类属于java.util包Calendarcalendar=Calendar.getInstance();获SimpleDateFormatformat=newSimpleDateFormat(“yyyy-MM-dd”);//获取当月第一天calendar=Calendar.getInstance();calendar.add(Calendar.MONTH,0);calendar......