【问题标题】:boolean expression parser in javajava中的布尔表达式解析器
【发布时间】:2012-08-30 18:14:06
【问题描述】:

是否有任何 java 库或技术可以分段解析布尔表达式?

我的意思是这样的表达:

T && ( F || ( F && T ) )

它可以分解成一个表达式树,以显示哪个标记导致了“F”值,就像这样(也许是这样的):

T &&               <- rhs false
    ( F ||         <- rhs false
        ( F && T ) <- eval, false
    )

我正在尝试将布尔表达式评估传达给非程序员。我已经在 Anlr 上四处寻找过,但我无法让它做很多事情(它似乎有一点学习曲线)。

我不反对自己写,但我宁愿不重新发明轮子。

【问题讨论】:

    标签: java parsing boolean-expression


    【解决方案1】:

    我最近用 Java 编写了一个专门用于处理布尔表达式的库:jbool_expressions

    它包含一个工具,可以从字符串输入中解析表达式:

    Expression<String> expr = ExprParser.parse("( ( (! C) | C) & A & B)")
    

    你也可以做一些相当简单的简化:

    Expression<String> simplified = RuleSet.simplify(expr);
    System.out.println(expr);
    

    给予

    (A & B)
    

    如果你想逐步完成赋值,你可以一个一个地赋值。对于此处的示例,

    Expression<String> halfAssigned = RuleSet.assign(simplified, Collections.singletonMap("A", true));
    System.out.println(halfAssigned);
    

    表演

    B
    

    你可以通过分配B来解决它。

    Expression<String> resolved = RuleSet.assign(halfAssigned, Collections.singletonMap("B", true));
    System.out.println(resolved);
    

    表演

    true
    

    不是 100% 满足您的要求,但希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      您可以使用MVELJUEL 执行此操作。两者都是表达式语言库,下面的例子都是使用 MVEL。

      例子:

      System.out.println(MVEL.eval("true && ( false || ( false && true ) )"));
      

      打印: 假的

      如果你真的想使用“T”和“F”,你可以这样做:

      Map<String, Object> context = new java.util.HashMap<String, Object>();
      context.put("T", true);
      context.put("F", false);
      System.out.println(MVEL.eval("T && ( F || ( F && T ) )", context));
      

      打印: 假的

      【讨论】:

        【解决方案3】:

        试试这个。

        static boolean parseBooleanExpression(String s) {
            return new Object() {
        
                int length = s.length(), index = 0;
        
                boolean match(String expect) {
                    while (index < length && Character.isWhitespace(s.charAt(index)))
                        ++index;
                    if (index >= length)
                        return false;
                    if (s.startsWith(expect, index)) {
                        index += expect.length();
                        return true;
                    }
                    return false;
                }
        
                boolean element() {
                    if (match("T"))
                        return true;
                    else if (match("F"))
                        return false;
                    else if (match("(")) {
                        boolean result = expression();
                        if (!match(")"))
                            throw new RuntimeException("')' expected");
                        return result;
                    } else
                        throw new RuntimeException("unknown token");
                }
        
                boolean term() {
                    if (match("!"))
                        return !element();
                    else
                        return element();
                }
        
                boolean factor() {
                    boolean result = term();
                    while (match("&&"))
                        result &= term();
                    return result;
                }
        
                boolean expression() {
                    boolean result = factor();
                    while (match("||"))
                        result |= factor();
                    return result;
                }
        
                boolean parse() {
                    boolean result = expression();
                    if (index < length)
                        throw new RuntimeException(
                            "extra string '" + s.substring(index) + "'");
                    return result;
                }
            }.parse();
        }
        

        public static void main(String[] args) {
            String s = "T && ( F || ( F && T ) )";
            boolean result = parseBooleanExpression(s);
            System.out.println(result);
        }
        

        输出:

        false
        

        语法是

         expression = factor { "||" factor }
         factor     = term { "&&" term }
         term       = [ "!" ] element
         element    = "T" | "F" | "(" expression ")"
        

        【讨论】:

          【解决方案4】:

          我已使用 Javaluator 对此进行了编码。
          这并不完全是您正在寻找的输出,但我认为这可能是一个起点。

          package test;
          
          import java.util.ArrayList;
          import java.util.Iterator;
          import java.util.List;
          
          import net.astesana.javaluator.*;
          
          public class TreeBooleanEvaluator extends AbstractEvaluator<String> {
            /** The logical AND operator.*/
            final static Operator AND = new Operator("&&", 2, Operator.Associativity.LEFT, 2);
            /** The logical OR operator.*/
            final static Operator OR = new Operator("||", 2, Operator.Associativity.LEFT, 1);
              
            private static final Parameters PARAMETERS;
          
            static {
              // Create the evaluator's parameters
              PARAMETERS = new Parameters();
              // Add the supported operators
              PARAMETERS.add(AND);
              PARAMETERS.add(OR);
              // Add the parentheses
              PARAMETERS.addExpressionBracket(BracketPair.PARENTHESES);
            }
          
            public TreeBooleanEvaluator() {
              super(PARAMETERS);
            }
          
            @Override
            protected String toValue(String literal, Object evaluationContext) {
              return literal;
            }
                  
            private boolean getValue(String literal) {
              if ("T".equals(literal) || literal.endsWith("=true")) return true;
              else if ("F".equals(literal) || literal.endsWith("=false")) return false;
              throw new IllegalArgumentException("Unknown literal : "+literal);
            }
              
            @Override
            protected String evaluate(Operator operator, Iterator<String> operands,
                Object evaluationContext) {
              List<String> tree = (List<String>) evaluationContext;
              String o1 = operands.next();
              String o2 = operands.next();
              Boolean result;
              if (operator == OR) {
                result = getValue(o1) || getValue(o2);
              } else if (operator == AND) {
                result = getValue(o1) && getValue(o2);
              } else {
                throw new IllegalArgumentException();
              }
              String eval = "("+o1+" "+operator.getSymbol()+" "+o2+")="+result;
              tree.add(eval);
              return eval;
            }
                  
            public static void main(String[] args) {
              TreeBooleanEvaluator evaluator = new TreeBooleanEvaluator();
              doIt(evaluator, "T && ( F || ( F && T ) )");
              doIt(evaluator, "(T && T) || ( F && T )");
            }
              
            private static void doIt(TreeBooleanEvaluator evaluator, String expression) {
              List<String> sequence = new ArrayList<String>();
              evaluator.evaluate(expression, sequence);
              System.out.println ("Evaluation sequence for :"+expression);
              for (String string : sequence) {
                System.out.println (string);
              }
              System.out.println ();
            }
          }
          

          这是输出:

          :T && ( F || ( F && T ) )的求值序列
          (F && T)=假
          (F || (F && T)=false)=false
          (T && (F || (F && T)=false)=false)=false

          :(T && T) 的求值序列|| ( F && T )
          (T && T)=真
          (F && T)=假
          ((T && T)=true || (F && T)=false)=true

          【讨论】:

          • 酷,我会尽快尝试并接受它是否是我想要做的。 +1
          • 我修复了一些错误,但总体而言,想法就在那里。谢谢!
          【解决方案5】:

          查看BeanShell。它具有接受类 Java 语法的表达式解析。

          编辑:除非您尝试实际解析 T &amp;&amp; F 字面意思,但您可以在 BeanShell 中使用文字 truefalse 来执行此操作。

          【讨论】:

            【解决方案6】:

            mXparser 处理布尔运算符 - 请查找一些示例

            示例 1:

            import org.mariuszgromada.math.mxparser.*;
            ...
            ...
            Expression e = new Expression("1 && (0 || (0 && 1))");
            System.out.println(e.getExpressionString() + " = " + e.calculate());
            

            结果 1:

            1 && (0 || (0 && 1)) = 0.0
            

            示例 2:

            import org.mariuszgromada.math.mxparser.*;
            ...
            ...
            Constant T = new Constant("T = 1");
            Constant F = new Constant("F = 0");
            Expression e = new Expression("T && (F || (F && T))", T, F);
            System.out.println(e.getExpressionString() + " = " + e.calculate());
            

            结果 2:

            T && (F || (F && T)) = 0.0
            

            更多详情请关注mXparser tutorial

            最好的问候

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-08-04
              • 1970-01-01
              • 1970-01-01
              • 2012-02-01
              • 2021-12-09
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多