metodo - analizador de expresiones booleanas en java
operadores logicos (5)
Echa un vistazo a BeanShell . Tiene un análisis de expresiones que acepta la sintaxis de Java.
EDITAR: a menos que esté intentando analizar realmente T && F
literalmente, aunque podría hacer esto en BeanShell usando los literales true
y false
.
¿Existen bibliotecas o técnicas de java para analizar expresiones booleanas de forma poco sistemática?
A lo que me refiero se le da una expresión como esta:
T && ( F || ( F && T ) )
Se podría dividir en un árbol de expresiones para mostrar qué token causó el valor ''F'', como tal ( quizás algo como esto):
T && <- rhs false
( F || <- rhs false
( F && T ) <- eval, false
)
Estoy tratando de comunicar evaluaciones de expresiones booleanas a no programadores. He tocado con Anlr, pero no pude hacer mucho (parece tener una pequeña curva de aprendizaje).
No me opongo a escribirlo yo mismo, pero preferiría no reinventar la rueda.
He codificado esto utilizando 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í está la salida:
Secuencia de evaluación para: T && (F || (F && T))
(F && T) = falso
(F || (F && T) = falso) = falso
(T && (F || (F && T) = falso) = falso) = falsoSecuencia de evaluación para: (T && T) || (F && T)
(T && T) = verdadero
(F && T) = falso
((T && T) = verdadero || (F && T) = falso) = verdadero
Podrías hacer esto con MVEL o JUEL . Ambas son bibliotecas de lenguaje de expresión, los siguientes ejemplos utilizan MVEL.
Ejemplo:
System.out.println(MVEL.eval("true && ( false || ( false && true ) )"));
Estampados: falso
Si literalmente quieres usar ''T'' y ''F'' puedes 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));
Estampados: falso
Recientemente jbool_expressions una biblioteca en Java específicamente para manipular expresiones booleanas: jbool_expressions .
Incluye una herramienta también para analizar expresiones de entrada de cadena:
Expression<String> expr = ExprParser.parse("( ( (! C) | C) & A & B)")
También puedes hacer una simplificación bastante simple:
Expression<String> simplified = RuleSet.simplify(expr);
System.out.println(expr);
da
(A & B)
Si desea avanzar en la asignación, 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 podrías resolverlo asignando B.
Expression<String> resolved = RuleSet.assign(halfAssigned, Collections.singletonMap("B", true));
System.out.println(resolved);
muestra
true
No es el 100% de lo que pedías, pero espero que te sirva de ayuda.
mXparser maneja operadores booleanos - por favor encuentre 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());
Resultado 2:
T && (F || (F && T)) = 0.0
Para más detalles, siga el tutorial de mXparser .
Atentamente