自定义java计算器语法解析

当前文章内容有两点

1.输入字符串中包含计算符号与数值,例如(1+3)*(3+2),通过java程序对这个字符串进行解析,并定制化开发得出正确结果

2.输入字符串,包含自定义函数进行计算

( ( 1 + pow(2,4) ) >= 12 )& ( true | ( 3 > count($a) ) )

,通过解析得出正确结果,支持函数嵌套

 

内容1: 代码入下

import com.param.branch.CalcType;

import java.util.Stack;

/**
 * 计算器语法解析
 */
public class GrammarUtil {
    private Stack<String> dataStack;//数据栈
    private Stack<Character> symbolStack;//符号栈

    public GrammarUtil() {
        dataStack = new Stack<>();
        symbolStack = new Stack<>();
        dataStack = new Stack<>();
        dataStack = new Stack<>();
    }

    /**
     * 栈是否为空,为空异常
     *
     * @param stack
     * @param msg
     * @param <T>
     * @throws Exception
     */
    public <T> void checkStackIsNull(Stack<T> stack, String msg) throws Exception {
        if (stack.empty()) {
            throw new Exception(msg);
        }

    }

    /**
     * 弹栈,单独提为方法的目的是可以加日志,查看弹出的数据是什么
     *
     * @param tStack
     * @param <T>
     * @return
     */
    public <T> T pop(Stack<T> tStack) {
        T pop = tStack.pop();
        return pop;

    }

    /**
     * 单独提为方法的目的是可以加日志,查看入栈的数据是什么
     *
     * @param tStack
     * @param data
     * @param <T>
     */
    public <T> void push(Stack<T> tStack, T data) {
        tStack.push(data);

    }

    /**
     * 存放数据
     *
     * @param data
     */
    public void pushData(String data) {
        push(this.dataStack, data);
    }

    /**
     * 存放符号,并返回是否需要弹栈
     *
     * @param data
     * @return
     */
    public void pushSymbol(Character data) throws Exception {
        if (')' == data) {//弹栈
            while (true) {
                checkStackIsNull(this.symbolStack, "缺少对应的括号 '('");
                Character pop = pop(this.symbolStack);
                if ('(' == pop) {//找到去括号,退出循环
                    return;
                } else {
                    //不是回括号,弹出两个值
                    checkStackIsNull(this.dataStack, "括号内缺少对应的数值");
                    String two = pop(this.dataStack);
                    checkStackIsNull(this.dataStack, "括号内缺少对应的数值");
                    String one = pop(this.dataStack);
                    Double result = exec(one, two, pop);
                    push(this.dataStack, String.valueOf(result));
                }
            }
        } else {
            Integer priority = priority(data);
            Integer lastSymbol;
            if (this.symbolStack.empty()) {
                lastSymbol = null;
            } else {
                Character pop = pop(this.symbolStack);
                lastSymbol = priority(pop);
                push(this.symbolStack, pop);
            }
            if (lastSymbol == null || priority == null || priority > lastSymbol) {
                push(this.symbolStack, data);
                return;
            }
            if (!this.symbolStack.empty()) {
                Character pop = pop(this.symbolStack);
                this.symbolStack.push(data);
                String two = pop(this.dataStack);
                checkStackIsNull(this.dataStack, "括号内缺少对应的数值");
                String one = pop(this.dataStack);
                Double result = exec(one, two, pop);
                push(this.dataStack, String.valueOf(result));
            }

        }
    }

    /**
     * 获取计算的最终结果
     *
     * @return
     * @throws Exception
     */
    public Double getResult() throws Exception {
        String two = pop(this.dataStack);
        if (this.symbolStack.empty()) {
            return Double.valueOf(two);
        }
        Character symbol = pop(this.symbolStack);
        String one = pop(this.dataStack);
        return exec(one, two, symbol);
    }

    /**
     * 原理,采用后续遍历的方式计算
     *
     * @param data
     * @return
     */
    private Double decompose(String data) throws Exception {
        char[] c = data.toCharArray();
        StringBuffer tmp = new StringBuffer();//记录当前元素
        for (int i = 0; i < c.length; i++) {
            char current = c[i];
            if (current == ' ') {
                if (tmp.length() == 0) {
                    continue;
                }
                pushData(tmp.toString());
                tmp.setLength(0);
                continue;
            }
            if (CalcType.allSymbol.contains(current)) {
                if (tmp.length() != 0) {
                    pushData(tmp.toString());
                    tmp.setLength(0);
                }
                pushSymbol(current);
                continue;
            }
            tmp.append(current);
        }
        if (tmp != null && tmp.length() != 0) {
            pushData(tmp.toString());
            tmp.setLength(0);
        }
        return getResult();
    }

    /**
     * 根据符号个数据进行数值逻辑计算
     *
     * @param one    第一个参数
     * @param two    第二个参数
     * @param symbol 计算符号
     * @return
     * @throws Exception
     */
    public Double exec(String one, String two, Character symbol) throws Exception {
        switch (symbol) {
            case CalcType.Add://加法
                return DataUtil.add(one, two);
            case CalcType.Subtract://减法
                return DataUtil.subtract(one, two);
            case CalcType.Multiply://乘法
                return DataUtil.multiply(one, two);
            case CalcType.Divide://除法
                return DataUtil.divide(one, two);
            default:
                throw new Exception(String.format("不支持的计算,符号 %s", symbol));
        }
    }

    /**
     * 获取当前符号的计算优先级
     *
     * @param symbol
     * @return
     */
    public Integer priority(Character symbol) {
        if ((symbol == CalcType.Add || symbol == CalcType.Subtract)) {//优先级为加与减的优先级为1
            return 1;
        }
        if ((symbol == CalcType.Multiply || symbol == CalcType.Divide)) {//优先级为乘与除优先级为2
            return 2;
        }
        return null;
    }

    public static void main(String[] args) throws Exception {
        String data = "((2+1))* (3*(2+1))";
        Double decompose = new GrammarUtil().decompose(data);//字符串分解
        System.out.println(decompose);
    }

}

内容2: 代码入下

自定义内置算法并支持嵌套的的逻辑解析

项目包位置:

   

Const:

package grammar.param;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 常量
 */
public class Const {
    public static String empty = " ";//空字符

    /**
     * 计算符号
     */
    public static class CalcSymbol {
        public final static String greater = ">";//大于
        public final static String less = "<";//小于
        public final static String equal = "==";//等于
        public final static String greaterEqual = ">=";//大于等于
        public final static String lessEqual = "<=";//小于等于
        public final static String notEqual = "!=";//不等于
        public final static String add = "+";
        public final static String minus = "-";
        public final static String multi = "*";
        public final static String divide = "/";
        public final static String and = "&";
        public final static String or = "|";
        public final static String remainder = "%";
        public final static String pow = "^";
        public final static String comma = ",";
        public final static Set<String> calcSymbolSet = new HashSet<>(Arrays.asList(new String[]{",", ">", "<", "=", "!", "+", "-", "*", "/", "|", "&", "%", "^"}));
    }

    /**
     * 计算优先级
     * 计算优先级集合,级别数字越小,越优先计算
     */
    public static class CalcLevel {
        //1级
        public final static Set<String> calcLevelOne = new HashSet<>(Arrays.asList(new String[]{"*", "/"}));
        //2级
        public final static Set<String> calcLevelTwo = new HashSet<>(Arrays.asList(new String[]{">", "<", "=", "!", "+", "-", "|", "&", "%", "^"}));
        //3级
        public final static Set<String> calcLevelThree = new HashSet<>(Arrays.asList(new String[]{","}));
    }

    /**
     * 括号
     */
    public static class Bracket {
        public static final String leftBracket = "(";
        public static final String rightBracket = ")";
        public static final Set<String> bracketSymbolSet = new HashSet<>(Arrays.asList(new String[]{"(", ")"}));
    }

    /**
     * 自定义函数
     */
    public static class Func {
        public static final String pow = "pow";//pow(2,4) 2^4 = 16
        public static final String count = "count";//count([1,2,1,2,1]) = 5
    }
}

LogicalCalc:

package grammar.param;


import java.util.*;
import java.util.regex.Pattern;

/**
 * 自定义函数与基本数据计算的实现代码
 */
public class LogicalCalc {

    /**
     * 基本数据计算
     */
    public static class MathCalc {

        /**
         * 分支计算
         *
         * @param symbol 分割符号
         * @param one    变量1
         * @param two    变量2
         * @return
         * @throws Exception
         */
        public static Object exec(String symbol, Object one, Object two) throws Exception {
            Object result;
            switch (symbol) {
                case Const.CalcSymbol.comma:
                    result = MathCalc.comma(one, two);
                    break;
                case Const.CalcSymbol.add:
                    result = MathCalc.add(one, two);
                    break;
                case Const.CalcSymbol.minus:
                    result = MathCalc.minus(one, two);
                    break;
                case Const.CalcSymbol.multi:
                    result = MathCalc.multi(one, two);
                    break;
                case Const.CalcSymbol.divide:
                    result = MathCalc.divide(one, two);
                    break;
                case Const.CalcSymbol.pow:
                    result = MathCalc.pow(one, two);
                    break;
                case Const.CalcSymbol.remainder:
                    result = MathCalc.remainder(one, two);
                    break;
                case Const.CalcSymbol.and:
                    result = MathCalc.and(one, two);
                    break;
                case Const.CalcSymbol.or:
                    result = MathCalc.or(one, two);
                    break;
                case Const.CalcSymbol.greater:
                    result = MathCalc.greater(one, two);
                    break;
                case Const.CalcSymbol.less:
                    result = MathCalc.less(one, two);
                    break;
                case Const.CalcSymbol.equal:
                    result = MathCalc.equal(one, two);
                    break;
                case Const.CalcSymbol.greaterEqual:
                    result = MathCalc.greaterEqual(one, two);
                    break;
                case Const.CalcSymbol.lessEqual:
                    result = MathCalc.lessEqual(one, two);
                    break;
                case Const.CalcSymbol.notEqual:
                    result = MathCalc.notEqual(one, two);
                    break;
                default:
                    throw new Exception(String.format("计算符号%s未实现", symbol));
            }
            System.out.println("计算" + one + " " + symbol + " " + two + " = " + result);
            return result;
        }

        /**
         * 字符串拼接
         *
         * @param one
         * @param two
         * @return
         */
        private static Object comma(Object one, Object two) {
            if (two instanceof LinkedList) {
                LinkedList index = (LinkedList) two;
                if (index.size() > 2) {
                    index.addFirst(one);
                    return index;
                }
            }
            LinkedList<Object> index = new LinkedList<>(Arrays.asList(new Object[]{one, two}));
            return index;
        }


        /**
         * 计算二者的和
         *
         * @param one
         * @param two
         * @return
         */
        public static Double add(Object one, Object two) {
            Double oneDouble = Double.valueOf(String.valueOf(one));
            Double twoDouble = Double.valueOf(String.valueOf(two));
            return oneDouble + twoDouble;
        }

        /**
         * 计算二者的差
         *
         * @param one
         * @param two
         * @return
         */
        public static Double minus(Object one, Object two) {
            Double oneDouble = Double.valueOf(String.valueOf(one));
            Double twoDouble = Double.valueOf(String.valueOf(two));
            return oneDouble - twoDouble;
        }


        /**
         * 计算二者的积
         *
         * @param one
         * @param two
         * @return
         */
        public static Double multi(Object one, Object two) {
            Double oneDouble = Double.valueOf(String.valueOf(one));
            Double twoDouble = Double.valueOf(String.valueOf(two));
            return oneDouble * twoDouble;
        }

        /**
         * 计算二者的商
         *
         * @param one
         * @param two
         * @return
         */
        public static Double divide(Object one, Object two) {
            Double oneDouble = Double.valueOf(String.valueOf(one));
            Double twoDouble = Double.valueOf(String.valueOf(two));
            return oneDouble / twoDouble;
        }

        /**
         * n次方计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object pow(Object one, Object two) {
            Double oneDouble = Double.valueOf(String.valueOf(one));
            Double twoDouble = Double.valueOf(String.valueOf(two));
            return Math.pow(oneDouble, twoDouble);
        }

        /**
         * 取余计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object remainder(Object one, Object two) {
            Double oneDouble = Double.valueOf(String.valueOf(one));
            Double twoDouble = Double.valueOf(String.valueOf(two));
            return oneDouble % twoDouble;
        }


        /**
         * 与计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object and(Object one, Object two) {
            return ("true".equals(String.valueOf(one)) && "true".equals(String.valueOf(two))) ? true : false;
        }

        /**
         * 或计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object or(Object one, Object two) {
            return ("true".equals(String.valueOf(one)) || "true".equals(String.valueOf(two))) ? true : false;
        }

        /**
         * 大于计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object greater(Object one, Object two) {
            if (Util.isNumber(one) && Util.isNumber(two)) {
                return Double.valueOf(String.valueOf(one)) > Double.valueOf(String.valueOf(two));
            } else {
                return String.valueOf(one).compareTo(String.valueOf(two)) > 0;
            }
        }

        /**
         * 小于计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object less(Object one, Object two) {
            if (Util.isNumber(one) && Util.isNumber(two)) {
                return Double.valueOf(String.valueOf(one)) < Double.valueOf(String.valueOf(two));
            } else {
                return String.valueOf(one).compareTo(String.valueOf(two)) < 0;
            }
        }

        /**
         * 等于计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object equal(Object one, Object two) {
            if (Util.isNumber(one) && Util.isNumber(two)) {
                return Double.valueOf(String.valueOf(one)) == Double.valueOf(String.valueOf(two));
            } else {
                return String.valueOf(one).compareTo(String.valueOf(two)) == 0;
            }
        }

        /**
         * 大于等于计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object greaterEqual(Object one, Object two) {
            if (Util.isNumber(one) && Util.isNumber(two)) {
                return Double.valueOf(String.valueOf(one)) >= Double.valueOf(String.valueOf(two));
            } else {
                return String.valueOf(one).compareTo(String.valueOf(two)) >= 0;
            }
        }

        /**
         * 小于等于计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object lessEqual(Object one, Object two) {
            if (Util.isNumber(one) && Util.isNumber(two)) {
                return Double.valueOf(String.valueOf(one)) <= Double.valueOf(String.valueOf(two));
            } else {
                return String.valueOf(one).compareTo(String.valueOf(two)) <= 0;
            }
        }

        /**
         * 不等于计算
         *
         * @param one
         * @param two
         * @return
         */
        private static Object notEqual(Object one, Object two) {
            if (Util.isNumber(one) && Util.isNumber(two)) {
                return Double.valueOf(String.valueOf(one)) != Double.valueOf(String.valueOf(two));
            } else {
                return String.valueOf(one).compareTo(String.valueOf(two)) != 0;
            }
        }
    }


    /**
     * 函数计算
     */
    public static class FuncCalc {

        /**
         * @param func  函数名称
         * @param param 函数参数,多个参数的组合为链表
         * @return
         * @throws Exception
         */
        public static Object exec(String func, Object param) throws Exception {
            Object result;
            switch (func) {
                case Const.Func.pow:
                    result = pow(param);
                    break;
                case Const.Func.count:
                    result = count(param);
                    break;
                default:
                    throw new Exception(String.format("自定义方法%s未实现", func));
            }
            System.out.println("计算自定义方法:" + func + "(" + param + ") = " + result);
            return result;
        }


        /**
         * 次方计算
         *
         * @param param
         * @return
         * @throws Exception
         */
        public static Object pow(Object param) throws Exception {
            LinkedList index = (LinkedList) param;
            if (index.size() != 2) {
                throw new Exception(String.format("方法参数数量异常,pow(a,b) -> pow(%s)", index));
            }
            Object one = index.getFirst();
            Object two = index.getLast();
            Double oneDouble = Double.valueOf(String.valueOf(one));
            Double twoDouble = Double.valueOf(String.valueOf(two));
            return Math.pow(oneDouble, twoDouble);
        }

        /**
         * 统计集合长度
         *
         * @param param
         * @return
         */
        private static Object count(Object param) {
            if (param instanceof Collection) {
                return ((Collection) param).size();
            }
            if (param == null) {
                return 0;
            }
            return 1;
        }
    }


    /**
     * 内部工具类
     */
    private static class Util {
        private final static String pattern = "^[0-9]+(\\.[0-9]+)?(E\\-?[0-9]+)?$";//转化为double的数值计算

        /**
         * 是否是数字
         *
         * @param str
         * @return
         */
        public static boolean isNumber(Object str) {
            return Pattern.matches(pattern, String.valueOf(str));
        }
    }
}
Decompose:
package grammar;

import com.alibaba.fastjson.JSONObject;
import grammar.param.Const;
import java.util.ArrayList;
import java.util.List;

/**
 * 语法分解
 */
public class Decompose {
    /**
     * 将计算表达式进行分割成单个元素组成的集合
     *
     * @param data
     * @return
     */
    public List<DataTypeStructure> paramCut(String data) {
        char[] chars = data.toCharArray();
        StringBuilder sbr = new StringBuilder();//整体字符串
        List<DataTypeStructure> arr = new ArrayList<>();
        String last = Const.empty;
        String charString;
        for (char aChar : chars) {
            if (aChar == ' ') continue;//跳过空格
            charString = String.valueOf(aChar);
            if (Const.CalcSymbol.calcSymbolSet.contains(charString)) {//如果是符号
                if (Const.CalcSymbol.calcSymbolSet.contains(last)) {//如果上一个也是符号
                    sbr.append(charString);
                    last = charString;
                    continue;
                }
                DataTypeStructure.Type type = sbr.length() > 0 && sbr.charAt(0) == '$' ? DataTypeStructure.Type.Index : DataTypeStructure.Type.Number;//检查是否有引用
                cacheRecord(sbr, arr, type);//flush缓存
                sbr.append(charString);
                last = charString;
                continue;
            }
            if (Const.Bracket.bracketSymbolSet.contains(charString)) {//如果是括号
                if (Const.Bracket.rightBracket.equals(charString)) {
                    DataTypeStructure.Type type = sbr.length() > 0 && sbr.charAt(0) == '$' ? DataTypeStructure.Type.Index : DataTypeStructure.Type.Number;//检查是否有引用
                    cacheRecord(sbr, arr, type);//回括号:必须flush缓存
                }
                if (Const.CalcSymbol.calcSymbolSet.contains(last)) {
                    cacheRecord(sbr, arr, DataTypeStructure.Type.Symbol);//上一个是符号:必须flush缓存
                }
                sbr.append(charString);
                cacheRecord(sbr, arr, DataTypeStructure.Type.Symbol);//flush缓存
                last = Const.empty;
                continue;
            }
            //当前为数据
            if (Const.CalcSymbol.calcSymbolSet.contains(last)) {//如果上一个是符号
                cacheRecord(sbr, arr, DataTypeStructure.Type.Symbol);//flush缓存
            }
            sbr.append(charString);
            last = charString;
        }
        DataTypeStructure.Type type = sbr.length() > 0 && sbr.charAt(0) == '$' ? DataTypeStructure.Type.Index : DataTypeStructure.Type.Number;//检查是否有引用
        cacheRecord(sbr, arr, type);//flush缓存
        return arr;
    }

    /**
     * 将缓存中的数据当成一个整体写入集合
     *
     * @param sbr  缓存数据
     * @param arr  当前集合
     * @param type 当前数据的类型  分为符号类型,引用类型,数值类型
     */
    private void cacheRecord(StringBuilder sbr, List<DataTypeStructure> arr, DataTypeStructure.Type type) {
        if (sbr.length() != 0) {
            DataTypeStructure dataTypeStructure = new DataTypeStructure();
            dataTypeStructure.setDataType(type);
            dataTypeStructure.setDataContent(sbr.toString());
            this.addData(arr, dataTypeStructure);
            sbr.setLength(0);
        }
    }

    /**
     * 添加数据
     */
    private void addData(List<DataTypeStructure> arr, DataTypeStructure line) {
        arr.add(line);
    }


    /**
     * 符号与数据记录的数据结构
     */
    public static class DataTypeStructure {
        /**
         * 数据类型
         */
        public enum Type {
            Symbol,//符号
            Number,//数值
            Index,//引用变量
        }


        private Type dataType;//数据类型 符号,数据
        private Object dataContent;//数据内容

        public Type getDataType() {
            return dataType;
        }

        private void setDataType(Type dataType) {
            this.dataType = dataType;
        }

        public Object getDataContent() {
            return dataContent;
        }

        public void setDataContent(Object dataContent) {
            this.dataContent = dataContent;
        }

        @Override
        public String toString() {
            JSONObject result = new JSONObject();
            result.put("dataType", dataType);
            result.put("dataContent", dataContent);
            return result.toJSONString();
        }
    }
}

StackCalc:

package grammar;


import grammar.param.Const;
import grammar.param.LogicalCalc;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;


/**
 * 后续表达式解析计算逻辑
 */
public class StackCalc {
    private Stack<Object> dataStack;//数据栈
    private Stack<String> symbolStack;//符号栈
    private Map<String, Object> cache;//缓存引用数据

    public StackCalc() {
        this.dataStack = new Stack<>();
        this.symbolStack = new Stack<>();
        this.cache = new HashMap<>();
    }

    /**
     * 引用赋值,可以在表达式中使用 "$变量名" 获取变量值
     *
     * @param key   变量名称
     * @param value 变量值
     */
    public void setKV(String key, Object value) {
        this.cache.put(key, value);
    }

    /**
     * 获取引用数据
     *
     * @param key 变量名称
     * @return
     */
    private Object getV(String key) {
        return this.cache.get(key);
    }


    /**
     * 弹栈,单独提为方法的目的是可以加日志,查看弹出的数据是什么
     *
     * @param tStack
     * @param <T>
     * @return
     */
    private <T> T pop(Stack<T> tStack) {
        T pop = tStack.pop();
//        System.out.println(String.format("弹栈 %s", pop));
        return pop;

    }

    /**
     * 单独提为方法的目的是可以加日志,查看入栈的数据是什么
     *
     * @param tStack
     * @param data
     * @param <T>
     */
    private <T> void push(Stack<T> tStack, T data) {
//        System.out.println(String.format("入栈 %s", data));
        tStack.push(data);
    }

    /**
     * 数据入栈弹栈逻辑
     *
     * @param dataTypeStructures
     * @return
     * @throws Exception
     */
    public Object stackCalc(List<Decompose.DataTypeStructure> dataTypeStructures) throws Exception {
        for (Decompose.DataTypeStructure structure : dataTypeStructures) {
            switch (structure.getDataType()) {
                case Symbol:
                    String symbol = String.valueOf(structure.getDataContent());//入栈符号
                    this.pushSymbol(symbol);
                    break;
                case Index:
                    String index = String.valueOf(structure.getDataContent());
                    String key = index.substring(1);
                    structure.setDataContent(this.getV(key));
                case Number:
                    Object value = structure.getDataContent();//入栈数据
                    this.push(this.dataStack, value);
                    break;
            }
        }
        while (true) {//全部弹出为止
            if (this.symbolStack.empty()) {
                break;
            }
            exec();
        }
        return this.pop(this.dataStack);
    }

    /**
     * 符号入栈
     * @param symbol
     * @throws Exception
     */
    private void pushSymbol(String symbol) throws Exception {
        //如果是回括号,一直弹栈到去括号为止,回括号最高优先级
        if (Const.Bracket.rightBracket.equals(symbol)) {
            this.rightBracket();
            return;
        }
        //如果不是回括号,比较计算的优先级计算数值
        if (this.symbolStack.empty() || symbol.endsWith(Const.Bracket.leftBracket)) {//空符号或者左括号结尾,直接存入
            this.push(this.symbolStack, symbol);
            return;
        }
        //如果队列中有符号,比较优先级
        String popSymbol = this.symbolStack.peek();//弹出符号
        if (popSymbol.endsWith(Const.Bracket.leftBracket)) {//上一个是括号.直接跳过
            this.push(this.symbolStack, symbol);//存入符号
            return;
        }
        //比较优先级
        int popStatus = getLevel(popSymbol);//获取优先级别
        int pushStatus = getLevel(symbol);
        if (popStatus < pushStatus) {//上一个符号是高优先级,下一个符号是低优先级都会计算
            this.exec();//高优先级计算
            this.push(this.symbolStack, symbol);//存入符号
            return;
        }
        this.push(this.symbolStack, symbol);//下一个符号优先级更高,不计算
    }


    /**
     * 获取计算优先级
     * todo 这里优先级设置的比较简单,可以自己设置对应计算符号的优先级,
     * 括号不用比较,直接计算(出现括号走不到这个方法)
     * 1级优先级 乘除
     * 2级优先级,常用计算符号
     * 3级优先级,自定义方法中的逗号计算 用于拼接两个数据组成链表
     * 4级优先级,其他计算符号
     *
     * @return
     */
    private static int getLevel(String symbol) {
        if (Const.CalcLevel.calcLevelOne.contains(symbol)) {//1级优先级
            return 1;
        }
        if (Const.CalcLevel.calcLevelTwo.contains(symbol)) {//2级优先级
            return 2;
        }
        if (Const.CalcLevel.calcLevelThree.contains(symbol)) {//3级优先级
            return 3;
        }
        return 4;
    }

    /**
     * 计算表达式,并将表达式的结果存入到栈中
     */
    private void exec() throws Exception {
        String symbol = this.pop(this.symbolStack);
        Object two = this.pop(this.dataStack);
        Object one = this.pop(this.dataStack);
        this.push(this.dataStack, LogicalCalc.MathCalc.exec(symbol, one, two));
    }

    /**
     * 回括号计算逻辑
     */
    private void rightBracket() throws Exception {
        while (true) {//全部弹出为止
            String popSymbol = this.symbolStack.peek();
            if (popSymbol.endsWith(Const.Bracket.leftBracket)) {//找到回括号
                this.pop(this.symbolStack);
                if (popSymbol.length() != 1) {
                    Object pop = this.pop(this.dataStack);
                    Object result = LogicalCalc.FuncCalc.exec(popSymbol.substring(0, popSymbol.length() - 1), pop);
                    this.push(this.dataStack, result);
                }
                break;
            }
            exec();//计算表达式
        }
    }
}

Demo:

package grammar;

import java.util.Arrays;
import java.util.List;

/**
 * 测试入口
 */
public class Demo {
    public static void main(String[] args) throws Exception {
        String data = "( ( 1 + pow(2,4) ) >= 12 )& ( true | ( 3 > count($a) ) ) ";
        Decompose current = new Decompose();
        List<Decompose.DataTypeStructure> dataTypeStructures = current.paramCut(data);
        dataTypeStructures.stream().forEach(f-> System.out.println(f));
        StackCalc stackCalc = new StackCalc();
        stackCalc.setKV("a", Arrays.asList(new Double[]{1D, 2D, 3D}));//设置引用变量,表达式可以使用$a获取这个数值
        Object result = stackCalc.stackCalc(dataTypeStructures);//弹栈计算
        System.out.println("计算结果为:" + result);
    }
}

 

运行最终结果:

{"dataContent":"(","dataType":"Symbol"}
{"dataContent":"(","dataType":"Symbol"}
{"dataContent":"1","dataType":"Number"}
{"dataContent":"+","dataType":"Symbol"}
{"dataContent":"pow(","dataType":"Symbol"}
{"dataContent":"2","dataType":"Number"}
{"dataContent":",","dataType":"Symbol"}
{"dataContent":"4","dataType":"Number"}
{"dataContent":")","dataType":"Symbol"}
{"dataContent":")","dataType":"Symbol"}
{"dataContent":">=","dataType":"Symbol"}
{"dataContent":"12","dataType":"Number"}
{"dataContent":")","dataType":"Symbol"}
{"dataContent":"&","dataType":"Symbol"}
{"dataContent":"(","dataType":"Symbol"}
{"dataContent":"true","dataType":"Number"}
{"dataContent":"|","dataType":"Symbol"}
{"dataContent":"(","dataType":"Symbol"}
{"dataContent":"3","dataType":"Number"}
{"dataContent":">","dataType":"Symbol"}
{"dataContent":"count(","dataType":"Symbol"}
{"dataContent":"$a","dataType":"Index"}
{"dataContent":")","dataType":"Symbol"}
{"dataContent":")","dataType":"Symbol"}
{"dataContent":")","dataType":"Symbol"}
计算2 , 4 = [2, 4]
计算自定义方法:pow([2, 4]) = 16.0
计算1 + 16.0 = 17.0
计算17.0 >= 12 = true
计算自定义方法:count([1.0, 2.0, 3.0]) = 3
计算3 > 3 = false
计算true | false = true
计算true & true = true
计算结果为:true

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小钻风巡山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值