2012-08-30 20 views
15

Czy istnieją jakieś biblioteki lub techniki Java do częściowego analizowania wyrażeń logicznych?analizator wyrażeń boolowskich w języku Java

Chodzi mi podano wyrażenie tak:

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

To może być rozbite na drzewie wypowiedzi aby pokazać, które Reklamowe spowodowane wartość na „F”, tak jak (być może coś w tym stylu):

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

Próbuję przekazać boolowskie oceny ekspresji do nie-programistów. Zająłem się Anlr, ale nie mogłem tego zrobić zbyt wiele (wydaje się, że ma trochę krzywej uczenia się).

Nie jestem przeciwny pisaniu tego samemu, ale wolałbym nie wymyślać koła.

Odpowiedz

11

Kodowałem to za pomocą Javaluator.
To nie jest dokładnie ten wynik, którego szukasz, ale myślę, że może to być punkt wyjścia.

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

Oto ouput:

kolejność ocen: T & & (|| F (F & & T))
(F & & T) = False
(F || (F & & T) = fałsz) = fałsz
(T & & (F || (F & & T) = False) = False) = False

kolejność ocen: (T & & T) || (F & & T)
(T & & T) = prawda
(F & & T) = False
((T & & T) = prawdą (|| F & & T) = False) = prawda

+0

Fajnie, wypróbuję to wkrótce i zaakceptuję, jeśli to jest to, co próbuję zrobić. +1 – javamonkey79

+0

Naprawiłem kilka błędów, ale ogólnie pomysł jest. Dzięki! – javamonkey79

10

Można to zrobić z MVEL lub JUEL. Obie są bibliotekami języków ekspresji, przykłady poniżej wykorzystują MVEL.

Przykład:

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

Wydruki: fałszywe

Jeżeli chcieliby używać 'T' i 'F' można to zrobić:

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

Drukuje: fałszywy

1

Zapoznaj się z BeanShell. Ma parsowanie wyrażeń, które akceptuje składnię podobną do języka Java.

EDIT: Chyba że starasz się faktycznie analizowania T && F dosłownie, choć można to zrobić w BeanShell za pomocą literałów true i false.

3

Niedawno stworzyłem bibliotekę w języku Java specjalnie do manipulowania wyrażeń logicznych: jbool_expressions.

Obejmuje ona narzędziem zbyt analizować wyrażeń z wejściem strun:

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

Można również zrobić dość prosty Uproszczenie:

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

daje

(A & B) 

Jeśli chciał aby przejść przez to zadanie, możesz przypisać wartości jeden po drugim. Na przykład tutaj,

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

pokazuje

B 

i można go rozwiązać poprzez przypisanie B.

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

pokazuje

true 

nie w 100% tego, czego prosić o, ale mam nadzieję, że to pomaga.

+0

Uwielbiam swoją bibliotekę - dzięki! –

0

mXparser obsługuje operatorów logicznych - proszę znaleźć kilka przykładów

Przykład 1:

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

Wynik 1:

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

Przykład 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 

Aby uzyskać więcej informacji, należy postępować zgodnie z mXparser tutorial.

Pozdrawiam

Powiązane problemy