Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boolean expression parser in java

Tags:

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.

like image 855
javamonkey79 Avatar asked Aug 30 '12 18:08

javamonkey79


People also ask

What is Java expression parser?

JEP is a Java API for parsing and evaluating mathematical expressions. With this library you can allow your users to enter an arbitrary formula as a string, and instantly evaluate it. JEP supports user defined variables, constants, and functions. A number of common mathematical functions and constants are included.

How do you simplify Boolean expressions in Java?

To simplify boolean expression is to reduce complexity of this expression, with preserving the meaning. has the same meaning but it's a little bit shorter. To simplify more complex examples you can use truth tables or Karnaugh maps.

How do you combine Boolean expressions in Java?

In Java, the boolean operator "and" is represented by &&. The && operator is used to combine two boolean values. The result is also a boolean value. The result is true if both of the combined values are true, and the result is false if either of the combined values is false.


2 Answers

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

like image 192
Dev Avatar answered Sep 19 '22 07:09

Dev


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

like image 27
Jean-Marc Astesana Avatar answered Sep 23 '22 07:09

Jean-Marc Astesana