2012-08-30 33 views
15

¿Existen bibliotecas o técnicas de java para analizar expresiones booleanas por partes?analizador de expresiones booleanas en java

Lo que quiero decir es dada una expresión como la siguiente:

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

Podría ser desglosada en un árbol de expresión para mostrar cuáles de emergencia causada valor de la 'F', al igual que (quizá algo como esto):

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

Estoy tratando de comunicar las evaluaciones de expresiones booleanas a los no programadores. He hurgado con Anlr, pero no pude hacer que hiciera mucho (parece tener una curva de aprendizaje).

No me opongo a escribirlo yo mismo, pero prefiero no reinventar la rueda.

Respuesta

11

He codificado esto usando Javaluator.
No es exactamente el resultado que está buscando, pero creo que podría ser un punto de partida.

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

Aquí es que la salida:

secuencia de evaluación para: T & & (F || (F & & T))
(F & & T) = false
(F || (F & & T) = falso) = falso
(T & & (F || (F & & t) = falso) = falso) = false secuencia de evaluación

para: (T & & T) || (F & & T)
(T & & T) = true
(F & & T) = false
((T & & T) = true || (F & & t) = falso) = true

+0

Genial, lo intentaré pronto y acepto si es lo que estoy tratando de hacer. +1 – javamonkey79

+0

He corregido un par de errores, pero en general la idea está ahí. ¡Gracias! – javamonkey79

10

Puede hacer esto con MVEL o JUEL. Ambas son bibliotecas de lenguaje de expresión, los ejemplos a continuación usan MVEL.

Ejemplo:

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

Lienzo: falsa

Si literalmente desea utilizar 'T' y 'F' puede hacer esto:

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: falsa

1

Echa un vistazo BeanShell. Tiene un análisis de expresiones que acepta la sintaxis similar a Java.

EDIT: A menos que estés tratando de analizar T && F realidad, literalmente, aunque se puede hacer esto en BeanShell utilizando los literales true y false.

3

Recientemente armé una biblioteca en Java específicamente para manipular expresiones booleanas: jbool_expressions.

Incluye una herramienta demasiado analizar las expresiones de entrada de cadena:

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

También se puede hacer una cierta simplificación bastante simple:

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

da

(A & B) 

Si quería para pasar a través de la tarea, puede asignar valores uno por uno. Para el ejemplo aquí,

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

muestra

B 

y se podía resolver mediante la asignación de B.

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

muestra

true 
No

100% lo que eras preguntando, pero espero que ayude.

+0

ama tu biblioteca, ¡gracias! –

0

mXparser maneja operadores booleanos - por favor, encontrar algunos ejemplos

Ejemplo 1:

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

Resultado 1:

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

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

Res ult 2:

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

Para obtener más información, siga mXparser tutorial.

Saludos cordiales

Cuestiones relacionadas