boolean expression parser in java

我怕爱的太早我们不能终老 提交于 2019-11-26 12:17:33

问题


Are there any java libraries or techniques to parsing boolean expressions piecemeal?

What I mean is given an expression like this:

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

It could be broken down into a expression tree to show which token caused the \'F\' value, like so (maybe something like this):

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

I am trying to communicate boolean expression evaluations to non-programmers. I have poked around with Anlr, but I couldn\'t get it to do much (it seems to have a bit of a learning curve).

I\'m not opposed to writing it myself, but I\'d rather not reinvent the wheel.


回答1:


I've coded this using Javaluator.
It's not exactly the output you are looking for, but I think it could be a start point.

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 ();
  }
}

Here is the ouput:

Evaluation sequence for :T && ( F || ( F && T ) )
(F && T)=false
(F || (F && T)=false)=false
(T && (F || (F && T)=false)=false)=false

Evaluation sequence for :(T && T) || ( F && T )
(T && T)=true
(F && T)=false
((T && T)=true || (F && T)=false)=true




回答2:


You could do this with MVEL or JUEL. Both are expression language libraries, examples below are using MVEL.

Example:

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

Prints: false

If you literally want to use 'T' and 'F' you can do this:

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));

Prints: false




回答3:


I recently put together a library in Java specifically to manipulate boolean expressions: jbool_expressions.

It includes a tool too parse expressions out of string input:

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

You can also do some fairly simple simplification:

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

gives

(A & B)

If you wanted to step through the assignment then, you could assign values one by one. For the example here,

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

shows

B

and you could resolve it by assigning B.

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

shows

true

Not 100% what you were asking for, but hope it helps.




回答4:


Check out BeanShell. It has expression parsing that accepts Java-like syntax.

EDIT: Unless you're trying to actually parse T && F literally, though you could do this in BeanShell using the literals true and false.




回答5:


mXparser handles Boolean operators - please find few examples

Example 1:

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

Result 1:

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

Example 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());

Result 2:

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

For more details please follow mXparser tutorial.

Best regards



来源:https://stackoverflow.com/questions/12203003/boolean-expression-parser-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!