首页 > 其他分享 >解析自定义逻辑表达式2

解析自定义逻辑表达式2

时间:2023-02-27 23:13:14浏览次数:39  
标签:right 自定义 ContextStatus token context currentRes 解析 contextStatus 表达式

  自定义逻辑表达式,关键字:= 等于,& 与,| 或, !非, ( , ) ,<> 包含,>< 不包含, # 不等于。

  表达式支持括号标识作用域。

  自动机分析如下:

 

 

   JAVA 实现:

public class ConditionAnalysis2 {
    //  终止符号
    Set<Character> signSet;

    ConditionAnalysis2() {
        this.signSet = new HashSet<Character>();
        signSet.add(' ');
        signSet.add('=');
        signSet.add('(');
        signSet.add(')');
        signSet.add('#');
        signSet.add('<');
        signSet.add('>');
        signSet.add('&');
        signSet.add('|');
    }public boolean analysis(String expression) {
        if (null == expression || expression.length() == 0) return false;
        if (expression.charAt(0) != '(') expression = "(" + expression + ")";
        Res res = this.getRes(expression, 0, new Context(ContextStatus.START), false);
        return res.res;
    }

    private Res getRes(String expression, int left, Context context, boolean isOppo) {
        int len = expression.length(), right = left;
        while (right < len) {
            char c = expression.charAt(right);
            if (c == ' ') {
                right++;
                continue;
            }
            // 回归
            if (')' == c) {
                if (isOppo) context.currentRes = !context.currentRes;
                Res res = new Res(context.currentRes, left, right + 1);
                System.out.println(expression.substring(isOppo ? left - 2 : left - 1, right + 1) + " : " + res.res);
                return res;
            }
            // 递归
            if (c == '(' || (c == '!' && right + 1 < len && expression.charAt(right + 1) == '(')) {
                Res partRes = null;
                if (c == '(') partRes = this.getRes(expression, right + 1, new Context(ContextStatus.WAIT_RES), false);
                else partRes = this.getRes(expression, right + 2, new Context(ContextStatus.WAIT_RES), true);
                if (null == partRes) throw new RuntimeException("error at " + right);
                if (null == context.currentRes) context.currentRes = partRes.res;
                else {
                    if (context.contextStatus == ContextStatus.AND) {
                        context.currentRes = context.currentRes & partRes.res;
                    } else if (context.contextStatus == ContextStatus.OR) {
                        context.currentRes = context.currentRes | partRes.res;
                    }
                }
                context.contextStatus = ContextStatus.RES;
                right = partRes.right;
                continue;
            }
            // 顺序
            if (c == '&') {
                context.contextStatus = ContextStatus.AND;
                right++;
                continue;
            }
            if (c == '|') {
                context.contextStatus = ContextStatus.OR;
                right++;
                continue;
            }
            Res partRes = this.getPartRes(expression, right);
            if (context.contextStatus == ContextStatus.WAIT_RES) {
                context.currentRes = partRes.res;
            } else if (context.contextStatus == ContextStatus.AND) {
                context.currentRes = context.currentRes & partRes.res;
            } else if (context.contextStatus == ContextStatus.OR) {
                context.currentRes = context.currentRes | partRes.res;
            }
            context.contextStatus = ContextStatus.RES;
            right = partRes.right;
        }
        if (isOppo) context.currentRes = !context.currentRes;
        return new Res(context.currentRes, left, right);
    }

    private Res getPartRes(String expression, int left) {
        int len = expression.length(), right = left;
        Context currentContext = new Context(ContextStatus.WAIT_TOKEN);
        Token leftToken = null;
        boolean isOppo = false;
        Res res = null;
        while (right < len) {
            char c = expression.charAt(right);
            if (c == ' ') {
                right++;
                continue;
            }
            if (c == '!') {
                if (currentContext.contextStatus == ContextStatus.WAIT_TOKEN || currentContext.contextStatus == ContextStatus.WAIT_OPPO2) {
                    currentContext.contextStatus = ContextStatus.WAIT_OPPO2;
                    isOppo = !isOppo;
                    right++;
                    continue;
                }
                throw new RuntimeException("error ! at " + right);
            }
            if (c == '=' || c == '#' || c == '<' || c == '>') {
                if (c == '=') currentContext.contextStatus = ContextStatus.EQ;
                else if (c == '#') currentContext.contextStatus = ContextStatus.NOT_EQ;
                else if (c == '<' && currentContext.contextStatus == ContextStatus.TOKEN)
                    currentContext.contextStatus = ContextStatus.XYW;
                else if (c == '<' && currentContext.contextStatus == ContextStatus.DYW)
                    currentContext.contextStatus = ContextStatus.NOT_CON;
                else if (c == '>' && currentContext.contextStatus == ContextStatus.TOKEN)
                    currentContext.contextStatus = ContextStatus.DYW;
                else if (c == '>' && currentContext.contextStatus == ContextStatus.XYW)
                    currentContext.contextStatus = ContextStatus.CON;
                right++;
                continue;
            }
            Token token = this.getToken(expression, right);
            if (currentContext.contextStatus == ContextStatus.WAIT_TOKEN || currentContext.contextStatus == ContextStatus.WAIT_OPPO2) {
                leftToken = token;
                currentContext.contextStatus = ContextStatus.TOKEN;
                right = token.right;
                continue;
            } else {
                Boolean currentRes = null;
                if (currentContext.contextStatus == ContextStatus.EQ) {
                    currentRes = token.token.equals(leftToken.token);
                } else if (currentContext.contextStatus == ContextStatus.NOT_EQ) {
                    currentRes = !token.token.equals(leftToken.token);
                } else if (currentContext.contextStatus == ContextStatus.CON) {
                    currentRes = leftToken.token.contains(token.token);
                } else if (currentContext.contextStatus == ContextStatus.NOT_CON) {
                    currentRes = !leftToken.token.contains(token.token);
                } else if (currentContext.contextStatus == ContextStatus.XYW) {
                    currentRes = Long.valueOf(leftToken.token) < Long.valueOf(token.token);
                } else if (currentContext.contextStatus == ContextStatus.DYW) {
                    currentRes = Long.valueOf(leftToken.token) > Long.valueOf(token.token);
                }
                if (null == currentRes) throw new RuntimeException("res is null! error at " + right);
                right = token.right;
                if (isOppo) currentRes = !currentRes;
                res = new Res(currentRes, left, right);
                break;
            }
        }
        System.out.println("   " + expression.substring(left, right) + " : " + res.res);
        return res;
    }

    private Token getToken(String expression, int left) {
        int len = expression.length(), right = left;
        char c = expression.charAt(right);
        StringBuilder stringBuilder = new StringBuilder();
        while (right < len && !this.signSet.contains(c)) {
            stringBuilder.append(expression.charAt(right));
            right++;
            if (right < len) c = expression.charAt(right);
        }
        return new Token(stringBuilder.toString(), left, right);
    }

    class Res {
        Boolean res;
        int left, right;

        public Res(Boolean res, int left, int right) {
            this.res = res;
            this.left = left;
            this.right = right;
        }
    }

    class Token {
        String token;
        int left;
        int right;

        Token(String token, int left, int right) {
            this.token = token;
            this.left = left;
            this.right = right;
        }
    }

    class Context {
        ContextStatus contextStatus;
        Boolean currentRes;

        Context(ContextStatus contextStatus) {
            this.contextStatus = contextStatus;
        }
    }

    public enum ContextStatus {
        // 外层状态
        START,
        WAIT_OPPO, WAIT_OPPO2,
        WAIT_RES, WAIT_RES2,
        RES,
        AND, OR,
        DONE,
        // 内层状态
        WAIT_TOKEN,
        TOKEN,
        EQ, NOT_EQ, XYW, DYW,
        CON, NOT_CON
    }
}

 

标签:right,自定义,ContextStatus,token,context,currentRes,解析,contextStatus,表达式
From: https://www.cnblogs.com/niuyourou/p/17162305.html

相关文章