zoukankan      html  css  js  c++  java
  • 关系表达式的计算

    近期在做一个项目,涉及到一些简单的规则匹配。规则的判定条件可以用关系表达式描述,形如(P1|P2)&(P3|P4)。其中&是与,|是或,P1-P4是Pattern,具体的匹配条件,返回值是True或者False。为计算此表达式的值,采用中序转后序再计算表达式的值。

    1. 后序表达式的生成

    中序表达式转后序表达式算法:

    1. 用&|()对原表达式进行拆分,得到List<String>。
    2. 从前往后遍历该List:
        (1)如果是一个pattern,则入栈。
        (2)如果是左括号(,也入栈。
        (3)如果是右括号:
            (a)如果此时栈为空,则表示表达式解析异常,报警并退出。
            (b)如果栈不为空,则依次pop栈顶元素,直到匹配到左括号(。如果没有左括号(的匹配,则表达式依次,报警并退出。
        (4)如果是&和|:
            (a)如果栈为空,直接入栈。
            (b)如果栈不为空,依次出栈直到匹配左括号(左括号不出栈)。再把操作符入栈。
    3、所有的pattern和操作符都入栈以后,把栈中所有元素依次出栈,就得到后序表达式。

    参考代码:

    List<String> postfix = new ArrayList<String>();
    Stack<String> stack = new Stack<String>();
    String delims = "&|()"; // 支持的操作符
    StringTokenizer st = new StringTokenizer(rule, delims, true);
    while (st.hasMoreTokens()) {
        String tk = st.nextToken();
        if (!delims.contains(tk)) {
            // pattern,直接入栈
            postfix.add(tk);
        } else if (tk.equals("(")) {
            // 左括号,入栈
            stack.push(tk);
        } else if (tk.equals(")")) {
            if (stack.empty()) {
                // 碰到右括号,如果栈为空,解析异常
                throw new RuleException("parseRule Error!");
            }
            String val = stack.pop();
            // 如果栈不为空,依次出栈直到匹配左括号
            while (!val.equals("(")) {
                postfix.add(val);
                if (!stack.empty()) {
                    val = stack.pop();
                } else
                    break;
            }
            if (stack.empty() && !val.equals("(")) {
                // 如果匹配不到左括号,解析异常
                throw new RuleException("parseRule Error!");
            }
        } else if (tk.equals("&") || tk.equals("|")) {
            if (stack.empty()) {
                // 碰到操作符,如果栈空,则直接入栈
                stack.push(tk);
            } else {
                // 如果栈不为空,依次出栈直到匹配左括号
                while (!stack.empty() && !stack.lastElement().equals("(")) {
                    postfix.add(stack.pop());
                }
                // 操作符入栈
                stack.push(tk);
            }
        }
    }
    
    // 所有的pattern和操作符匹配完毕,把堆栈中还有的数据依次出栈
    while (!stack.empty()) {
        postfix.add(stack.pop());
    }
    
    System.out.println("Original Rule:" + rule);
    System.out.println("Postfix Rule: " + postfix.toString());

    2. 后序表达式的计算

    后序表达式的计算算法:

    1. 从前往后遍历中序表达式:
        (1)如果是&|操作符,则pop两个字段r1和r2,计算r1&r2或r1|r2的值r3,并将r3入栈。
        (2)如果是pattern,则计算pattern的匹配结果True Or False,并将结果入栈。
    2、中序表达式便利完毕,栈中只有1个元素,即为表达式结果。

     参考代码:

    Stack<Boolean> stack = new Stack<Boolean>();
    for (String str : this.postfix) {
        if (str.equals("&")) {
            // pop两个pattern,计算
            boolean r1 = stack.pop();
            boolean r2 = stack.pop();
            stack.push(r1 && r2);
        } else if (str.equals("|")) {
            // pop两个pattern,计算
            boolean r1 = stack.pop();
            boolean r2 = stack.pop();
            stack.push(r1 || r2);
        } else {
            // 计算pattern的值,并push到stack
            Pattern ptn = this.patterns.get(str);
            stack.push(ptn.judge(fact));
        }
    }
    
    if (stack.size() == 1) {
        return stack.pop();
    } else {
        throw new RuleException("judge failed: postfix error!");
    }
  • 相关阅读:
    英语Lignaloes沉香木LIGNALOES单词
    英语chrismatite黄蜡石chrismatite单词
    英语cartialgenous鹿茸cartialgenous单词
    英语NanyangJade南阳玉NanyangJade独山玉
    单词chalchiguite硬玉chalchiguite英语
    英语_金丝楠是紫楠(phoebeSheareri)的别名
    英语AquilariaCrassna奇楠沉香
    英语LIGNALOO沉香lignaloo单词
    iOS批量添加SDK自动打包GUI工具
    如何做一个跨平台的游戏App?
  • 原文地址:https://www.cnblogs.com/simplestupid/p/4771892.html
Copyright © 2011-2022 走看看