5

文字列からブールへの複雑な式を解析する必要があります。


* ブール値 (true/false)、
* 括弧、
* AND/OR オペランド (&&、||) のみを含めることができます。

例えば:

bool.Parse("((true || false) && (false || false)) || (true || false)"

これを達成する方法はありますか?

4

3 に答える 3

6

C# コード内で JScript.NET Eval 関数を提供する巧妙なエバリュエーター クラスを次に示します。

static public class Evaluator
{
    private const string _jscriptSource =
        @"package Evaluator
        {
           class Evaluator
           {
              public function Eval(expr : String) : String 
              { 
                 return eval(expr); 
              }
           }
        }";

    static private object _evaluator;
    static private Type _evaluatorType;

    [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline",
        Justification = "Can't be done inline - too complex")]
    static Evaluator()
    {
        InstantiateInternalEvaluator();
    }

    static private void InstantiateInternalEvaluator()
    {
        JScriptCodeProvider compiler = new JScriptCodeProvider();

        CompilerParameters parameters;
        parameters = new CompilerParameters();
        parameters.GenerateInMemory = true;

        CompilerResults results;
        results = compiler.CompileAssemblyFromSource(parameters, _jscriptSource);

        Assembly assembly = results.CompiledAssembly;
        _evaluatorType = assembly.GetType("Evaluator.Evaluator");

        _evaluator = Activator.CreateInstance(_evaluatorType);
    }

    static public int EvaluateToInteger(string statement)
    {
        string s = EvaluateToString(statement);
        return int.Parse(s);
    }

    static public double EvaluateToDouble(string statement)
    {
        string s = EvaluateToString(statement);
        return double.Parse(s);
    }

    static public decimal ForceEvaluateToDecimal(string statement)
    {
        decimal result;
        bool s = Decimal.TryParse(statement, out result);
        return result;
    }

    static public decimal EvaluateToDecimal(string statement)
    {
        string s = EvaluateToString(statement);
        return decimal.Parse(s);
    }

    static public string EvaluateToString(string statement)
    {
        object o = EvaluateToObject(statement);
        return o.ToString();
    }

    static public bool EvaluateToBool(string statement)
    {
        object o = EvaluateToObject(statement);
        return (bool)o;
    }

    static public object EvaluateToObject(string statement)
    {
        try
        {
            return _evaluatorType.InvokeMember(
                "Eval",
                BindingFlags.InvokeMethod,
                null,
                _evaluator,
                new object[] {statement}
                );
        }
        catch (Exception)
        {
            InstantiateInternalEvaluator();
            return null;
        }
    }
}

次に、Evaluator.EvaluateToBool(string) を呼び出します。既存のプロジェクトから持ち上げられたので、微調整する必要があるかもしれません!

于 2009-03-27T14:42:03.467 に答える
2

説明した文字列は有効な C# コードであるため、実行時に解釈できれば完了です。多くの言語では、これは組み込み関数です。C# ではそうではありませんが、このランタイム C# インタープリターなどのサードパーティ ライブラリを使用できます。

于 2009-03-27T14:42:34.357 に答える
0

標準的な方法は次のとおりです。

  • 文字列をトークン化する
  • すべてのノードに演算子を配置し、すべての葉にオペランドを配置してツリーを構築する
  • 式を評価するツリーを訪問する
于 2009-03-27T14:40:28.697 に答える