web-dev-qa-db-ja.com

javaのブール式パーサー

Javaブール式を部分的に解析するためのライブラリまたはテクニックはありますか?

つまり、次のような表現が与えられます。

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

次のように、式ツリーに分解して、「F」値の原因となったトークンを示すことができます(maybethis like):

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

ブール式の評価をプログラマー以外の人に伝えようとしています。私はAnlrをいじくり回しましたが、あまり機能させることができませんでした(学習曲線が少しあるようです)。

私はそれを自分で書くことに反対しているわけではありませんが、ホイールを再発明したくありません。

18
javamonkey79

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)= false
(F ||(F && T)= false)= false
(T &&(F ||(F && T)= false)= false)= false

:(T && T)の評価シーケンス|| (F && T)
(T && T)= true
(F && T)= false
((T && T)= true ||(F && T)= false)= true

11

[〜#〜] mvel [〜#〜] または [〜#〜] juel [〜#〜] でこれを行うことができます。どちらも式言語ライブラリであり、以下の例ではMVELを使用しています。

例:

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

プリント:false

あなたが文字通り「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));

プリント:false

10
Dev

私は最近、Javaブール式を操作するために特にライブラリをまとめました: jbool_expressions

文字列入力から式を解析するツールも含まれています。

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

また、かなり単純な単純化を行うこともできます。

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

与える

(A & B)

割り当てを段階的に実行したい場合は、値を1つずつ割り当てることができます。ここの例では、

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%ではありませんが、それが役に立てば幸いです。

6
bpodgursky

チェックアウト BeanShell 。 Javaのような構文を受け入れる式の解析があります。

EDIT:実際に解析しようとしない限りT && F文字通りですが、リテラルtrueおよびfalseを使用してBeanShellでこれを行うことができます。

1
Brian

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チュートリアル に従ってください。

宜しくお願いします

0
Leroy Kegan