翻译简易逻辑表达式

 

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

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

  自动机分析如下:

 

   JAVA 代码实现:

public class ConditionAnalysis {
    public static void main(String[] args) {
        String expression = "(1=1&(1=2|1=1) )";
        ConditionAnalysis conditionAnalysis = new ConditionAnalysis();
        Context context = conditionAnalysis.new Context(ContextStatus.WAIT);
        Res res = conditionAnalysis.analysis(expression, 0, context);
        System.out.println(res.data);
    }

    //  终止符号
    Set<Character> signSet;

    ConditionAnalysis() {
        this.signSet = new HashSet<Character>();
        signSet.add(' ');
        signSet.add('=');
        signSet.add('(');
        signSet.add(')');
        signSet.add('#');
        signSet.add('<');
        signSet.add('>');
        signSet.add('&');
        signSet.add('|');
    }

    public Res analysis(String expression, int left, Context context) {
        int len = expression.length(), right = left;
        while (right < len) {
            char c = expression.charAt(right);
            if (c == ' ') {
                right++;
                continue;
            }
            // 回归条件
            if (c == ')') {
                right++;
                Res res = new Res(context.currentRes, left, right);
                System.out.println(expression.substring(left - 1, right) + " >>>>>> " + context.currentRes);
                return res;
            }
            // 关键字处理
            if (c == '&') {
                if (context.innerStatus != ContextStatus.RES) throw new RuntimeException("error at point:" + right);
                context.innerStatus = ContextStatus.AND;
                right++;
                continue;
            } else if (c == '|') {
                if (context.innerStatus != ContextStatus.RES) throw new RuntimeException("error at point:" + right);
                context.innerStatus = ContextStatus.OR;
                right++;
                continue;
            } else if (c == '=') {
                context.innerStatus = ContextStatus.EQ;
                right++;
                continue;
            } else if (c == '#') {
                context.innerStatus = ContextStatus.NOTEQ;
                right++;
                continue;
            } else if (c == '<') {
                if (context.innerStatus == ContextStatus.TOKEN) context.innerStatus = ContextStatus.XYW;
                else if (context.innerStatus == ContextStatus.DYW) context.innerStatus = ContextStatus.NOTCON;
                right++;
                continue;
            } else if (c == '>') {
                if (context.innerStatus == ContextStatus.TOKEN) context.innerStatus = ContextStatus.DYW;
                else if (context.innerStatus == ContextStatus.XYW) context.innerStatus = ContextStatus.CON;
                right++;
                continue;
            }
            // 内部作用域处理
            if (c == '(') {
                Res res = analysis(expression, right + 1, new Context(ContextStatus.WAIT));
                // 重要!内部作用域计算完成,外部作用域此时的状态是没有跟上计算的
                context.outerStatus = context.innerStatus;
                context.innerStatus = ContextStatus.RES;
                if (null == context.currentRes) context.currentRes = res.data;
                else if (context.outerStatus == ContextStatus.AND) context.currentRes = context.currentRes && res.data;
                else if (context.outerStatus == ContextStatus.OR) context.currentRes = context.currentRes || res.data;
                right = res.right;
                continue;
            }
            // 线性处理,拿 token
            Token token = this.getToken(expression, right);
            if (context.innerStatus == ContextStatus.WAIT) {
                context.innerStatus = ContextStatus.TOKEN;
                context.leftToken = token;
                right = token.right;
                continue;
            }
            if (context.innerStatus == ContextStatus.AND || context.innerStatus == ContextStatus.OR) {
                context.leftToken = token;
                context.outerStatus = context.innerStatus;
                context.innerStatus = ContextStatus.TOKEN;
                right = token.right;
                continue;
            }
            //  token 拿在计算线性局部结果的节点上
            Res res = null;
            if (context.innerStatus == ContextStatus.EQ) {
                res = new Res(context.leftToken.data.equals(token.data), left, token.right);
            } else if (context.innerStatus == ContextStatus.NOTEQ) {
                res = new Res(!context.leftToken.data.equals(token.data), left, token.right);
            } else if (context.innerStatus == ContextStatus.CON) {
                res = new Res(context.leftToken.data.contains(token.data), left, token.right);
            } else if (context.innerStatus == ContextStatus.NOTCON) {
                Boolean currentRes = !context.leftToken.data.contains(token.data);
                res = new Res(currentRes, left, token.right);
            } else if (context.innerStatus == ContextStatus.XYW) {
                res = new Res(Integer.valueOf(context.leftToken.data) < Integer.valueOf(token.data), left, token.right);
            } else if (context.innerStatus == ContextStatus.DYW) {
                res = new Res(Integer.valueOf(context.leftToken.data) > Integer.valueOf(token.data), left, token.right);
            }
            context.leftToken = null;
            context.rightToken = null;
            context.innerStatus = ContextStatus.RES;
            if (null == context.currentRes) context.currentRes = res.data;
            else if (context.outerStatus == ContextStatus.AND) context.currentRes = context.currentRes && res.data;
            else if (context.outerStatus == ContextStatus.OR) context.currentRes = context.currentRes || res.data;
            context.outerStatus = null;
            right = res.right;
        }
        return new Res(context.currentRes, left, right);
    }

    private Token getToken(String expression, int left) {
        int len = expression.length(), right = left;
        if (right >= len) throw new RuntimeException("left:" + left + " out of length:" + len);
        StringBuilder sb = new StringBuilder();
        char c = expression.charAt(right);
        while (right < len && !this.signSet.contains(c)) {
            sb.append(c);
            right++;
            c = expression.charAt(right);
        }
        Token reToken = new Token(sb.toString(), left, right);
        return reToken;
    }

    // 作用域的上下文
    class Context {
        ContextStatus innerStatus;
        ContextStatus outerStatus;
        Boolean currentRes;

        Token leftToken;
        Token rightToken;

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

    class Res {
        Boolean data;
        int left;
        int right;

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

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

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

    // 自动机状态
    private enum ContextStatus {
        WAIT, TOKEN,
        EQ, NOTEQ,
        XYW, DYW,
        CON, NOTCON,
        RES,
        AND, OR,
        DONE
    }
}

 

posted @ 2023-02-24 19:59  牛有肉  阅读(48)  评论(0编辑  收藏  举报