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.
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)=falseEvaluation sequence for :(T && T) || ( F && T )
(T && T)=true
(F && T)=false
((T && T)=true || (F && T)=false)=true
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
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.
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
.
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