2012-08-30 14 views
15

Esistono librerie o tecniche java per analizzare le espressioni booleane in modo frammentario?parser di espressioni booleane in java

Quello che voglio dire è dato un'espressione come questo:

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

potrebbe essere suddiviso in un albero di espressione per mostrare quali Token causato il valore 'F', in questo modo (forse qualcosa del genere):

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

Sto provando a comunicare le valutazioni di espressioni booleane ai non programmatori. Ho cercato con Anlr, ma non ho potuto farlo fare molto (sembra avere un po 'di una curva di apprendimento).

Non sono contrario a scrivere da solo, ma preferirei non reinventare la ruota.

risposta

11

L'ho codificato utilizzando Javaluator.
Non è esattamente l'output che stai cercando, ma penso che potrebbe essere un punto di partenza.

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

Ecco l'output:

sequenza di valutazione per: T & & (F || (F & & T))
(F & & T) = FALSE
(F || (F & & T) = falso) = falso
(T & & (F || (F & & T) = false) = false) = falso

sequenza di valutazione per: (T & & T) || (F & & T)
(T & & T) = true
(F & & T) = FALSE
((T & & T) = true || (F & & T) = false) = TRUE

+0

fredda, ci proverò fuori presto e lo accetto se è quello che sto cercando di fare. +1 – javamonkey79

+0

Ho risolto un paio di bug, ma nel complesso l'idea è lì. Grazie! – javamonkey79

10

È possibile farlo con MVEL o JUEL. Entrambe sono librerie di espressioni linguistiche, gli esempi seguenti utilizzano MVEL.

Esempio:

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

Stampe: falsa

Se volete letteralmente utilizzare 'T' e 'F' si può fare questo:

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

Stampe: falso

1

Check out BeanShell. Ha un parsing di espressioni che accetta la sintassi simile a Java.

EDIT: A meno che non si sta cercando di analizzare in realtà T && F letteralmente, anche se si potrebbe fare questo in BeanShell utilizzando i letterali true e false.

3

Recentemente ho creato una libreria in Java appositamente per manipolare le espressioni booleane: jbool_expressions.

Include uno strumento troppo analizzare le espressioni di stringa di input:

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

Si può anche fare un po 'abbastanza semplice semplificazione:

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

(A & B) 

Se si voleva per passare attraverso il compito, quindi, è possibile assegnare i valori uno per uno. Per l'esempio qui,

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

mostra

B 

e si potrebbe risolverlo assegnando B.

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

mostra

true 
Non

100% quello che eri chiedere, ma spero che aiuti.

+0

ama la tua libreria - grazie! –

0

mXparser maniglie operatori booleani - si prega di trovare alcuni esempi

Esempio 1:

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

Risultato 1:

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

Esempio 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 

Per ulteriori dettagli, seguire mXparser tutorial.

migliori saluti