Анализатор логических выражений в Java
Существуют ли какие-либо java-библиотеки или методы для разбора булевых выражений по частям?
Что я имею в виду, так это выражение:
T && ( F || ( F && T ) )
Его можно разбить на дерево выражений, чтобы показать, какой токен вызвал значение 'F', например, (например,что- то вроде этого):
T && <- rhs false
( F || <- rhs false
( F && T ) <- eval, false
)
Я пытаюсь передать оценки булевых выражений непрограммистам. Я возился с Anlr, но я не мог заставить его делать много (кажется, что он немного обучается).
Я не против написать это сам, но я бы не стал изобретать велосипед.
6 ответов
Я закодировал это с помощью Javaluator.
Это не совсем вывод, который вы ищете, но я думаю, что это может быть отправной точкой.
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 ();
}
}
Вот результат:
Последовательность оценки для: T && (F || (F && T))
(F && T) = ложь
(F || (F && T) = false) = false
(T && (F || (F && T) = false) = false) = falseПоследовательность оценки для: (T && T) || (F && T)
(T && T) = правда
(F && T) = ложь
((T && T) = true || (F && T) = false) = true
Вы можете сделать это с MVEL или JUEL. Оба являются библиотеками языка выражений, примеры ниже используют MVEL.
Пример:
System.out.println(MVEL.eval("true && ( false || ( false && true ) )"));
Печать: ложь
Если вы буквально хотите использовать "T" и "F", вы можете сделать это:
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));
Печать: ложь
Недавно я собрал библиотеку на Java специально для управления логическими выражениями: jbool_expressions.
Он включает в себя инструмент для анализа выражений из строкового ввода:
Expression<String> expr = ExprParser.parse("( ( (! C) | C) & A & B)")
Вы также можете сделать довольно простое упрощение:
Expression<String> simplified = RuleSet.simplify(expr);
System.out.println(expr);
дает
(A & B)
Если вы хотите пошагово выполнить назначение, вы можете назначить значения одно за другим. Для примера здесь
Expression<String> halfAssigned = RuleSet.assign(simplified, Collections.singletonMap("A", true));
System.out.println(halfAssigned);
шоу
B
и вы можете решить это, назначив B.
Expression<String> resolved = RuleSet.assign(halfAssigned, Collections.singletonMap("B", true));
System.out.println(resolved);
шоу
true
Не на 100% то, что вы просили, но надеюсь, что это поможет.
Проверьте BeanShell. Он имеет разбор выражений, который принимает Java-подобный синтаксис.
РЕДАКТИРОВАТЬ: Если вы не пытаетесь разобрать T && F
буквально, хотя вы могли бы сделать это в BeanShell, используя литералы true
а также false
,
Попробуй это.
static boolean parseBooleanExpression(String s) {
return new Object() {
int length = s.length(), index = 0;
boolean match(String expect) {
while (index < length && Character.isWhitespace(s.charAt(index)))
++index;
if (index >= length)
return false;
if (s.startsWith(expect, index)) {
index += expect.length();
return true;
}
return false;
}
boolean element() {
if (match("T"))
return true;
else if (match("F"))
return false;
else if (match("(")) {
boolean result = expression();
if (!match(")"))
throw new RuntimeException("')' expected");
return result;
} else
throw new RuntimeException("unknown token");
}
boolean term() {
if (match("!"))
return !element();
else
return element();
}
boolean factor() {
boolean result = term();
while (match("&&"))
result &= term();
return result;
}
boolean expression() {
boolean result = factor();
while (match("||"))
result |= factor();
return result;
}
boolean parse() {
boolean result = expression();
if (index < length)
throw new RuntimeException(
"extra string '" + s.substring(index) + "'");
return result;
}
}.parse();
}
А также
public static void main(String[] args) {
String s = "T && ( F || ( F && T ) )";
boolean result = parseBooleanExpression(s);
System.out.println(result);
}
выход:
false
Синтаксис:
expression = factor { "||" factor }
factor = term { "&&" term }
term = [ "!" ] element
element = "T" | "F" | "(" expression ")"
mXparser обрабатывает логические операторы - пожалуйста, найдите несколько примеров
Пример 1:
import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("1 && (0 || (0 && 1))");
System.out.println(e.getExpressionString() + " = " + e.calculate());
Результат 1:
1 && (0 || (0 && 1)) = 0.0
Пример 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());
Результат 2:
T && (F || (F && T)) = 0.0
Для получения более подробной информации, пожалуйста, следуйте инструкциям mXparser.
С наилучшими пожеланиями