1

次のような単純な式を解析したいだけです-

IIF(FVAL(PFC) = TRUE, (IIF((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500, (FVAL(BAS)  + FVAL(DA)) * 12%, 780)), 0)`

これを解析した後、どの関数にどのパラメーターが含まれているかを知ることができるはずです。

|-FVAL
       |-PFC
|-ORGVAL 
       |-BAS
       |-"2012/12/31"

私は .Net Framework 2.0 で立ち往生しているので、Linq やラムダ式の利点はありません。また、コードを参照するだけでなく、カスタム ライブラリにコードを含めたいと考えています。誰かが私に良いライブラリやコードを教えてくれますか?

式を評価せずに解析し、使用されているトークンを見つけるだけです。トークンを見つけたら、解析する前に式の文字列を変更する必要があります。たとえば、関数ORGVALが使用されている場合、渡されるパラメーターの前にアンダースコアを付ける必要があります。LikeORGVAL(BAS)は に変換されORGVAL(_BAS)ます。一部の関数は次のような 2 つのパラメーターを持つことができORGVAL(BAS, "2012/12/31")、これは次のように変換されます。ORGVAL(_BAS, "2012/12/31")

注: 他の方法がある場合は、お知らせください。パーサーとレクサーは避けたいです。

4

3 に答える 3

1

これは洗練されていないが完全な式パーサーのように見えます (テストしていませんが、出発点になる可能性があります)。

http://gbacon.blogspot.it/2005/09/simple-expression-parser-in-c.html

古いけどC#2.0って言ってたから大丈夫かも。ただし、対象となる C# のバージョンはわかりません。

于 2012-06-08T11:27:34.440 に答える
1

コードに .NET 言語のいずれかを使用してもかまわない場合は、CodeDom を使用してコードをオンザフライでコンパイルし、メモリ内のみのアセンブリとして実行できます。たとえば、これはあなたが示した式の例に最も近い近似になります。

private abstract class Logic
{
    protected double FVAL(object arg)
    {
        // put code here
        return 0;
    }

    protected double ORGVAL(object arg)
    {
        // put code here
        return 0;
    }

    protected double ORGVAL(object arg, string date)
    {
        // put code here
        return 0;
    }

    public abstract double GetValue(object PFC, object BAS, object DA);
}

private class DynamicLogic : Logic
{
    public override double GetValue(object PFC, object BAS, object DA)
    {
        return (FVAL(PFC) = true ? ((ORGVAL(BAS, "2012/12/31") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12 : 780) : 0);
    }
}


private Logic GenerateLogic(string code)
{
    using (CSharpCodeProvider provider = new CSharpCodeProvider())
    {
        StringBuilder classCode = new StringBuilder();
        classCode.AppendLine("private class DynamicLogic : Logic");
        classCode.AppendLine("    {");
        classCode.AppendLine("        public override int GetValue(object PFC, object BAS, object DA)");
        classCode.AppendLine("        {");
        classCode.AppendLine("            return (" + code + ");");
        classCode.AppendLine("        }");
        classCode.AppendLine("    }");
        CompilerParameters p = new CompilerParameters();
        p.GenerateInMemory = true;
        p.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
        CompilerResults results = provider.CompileAssemblyFromSource(p, code);
        return (Logic)Activator.CreateInstance(type);
        if (results.Errors.HasErrors)
        {
            throw new Exception("Failed to compile DynamicLogic class");
        }
        return (Logic)results.CompiledAssembly.CreateInstance("DynamicLogic");
    }
}

private double evaluate(object PFC, object BAS, object DA)
{
    Logic logic = GenerateLogic("FVAL(PFC) = true ? ((ORGVAL(BAS, \"2012/12/31\") + ORGVAL(DA)) < 6500 ? (FVAL(BAS) + FVAL(DA)) * .12  : 780) : 0");
    return logic.GetValue(PFC, BAS, DA);
}

編集:評価するだけでなく、式3自体を実際に取得する必要があるとあなたが言ったことは知っていますが、コードを修正したので、先に進んで将来の通行人のために投稿することにしました。

于 2012-06-08T11:31:27.480 に答える
1

あなたがやりたいことは構文解析によく似ているので、構文解析を伴わない解決策を見つけるのは難しいと思います。あなたが言おうとしていることが、自分でパーサーをプログラムしたくないということであれば、利用可能な数式解析ライブラリがいくつかあります。

私は Jep.Net (http://www.singularsys.com/jep.net) の作成者の 1 人です。これは、あなたのニーズに合った式解析コンポーネントです。十分に文書化されており、高度にカスタマイズ可能であり、独自のカスタム パーサーを実装するという面倒でエラーが発生しやすいプロセスを確実に省略できます。それがあなたに合わない場合は、「.net式解析ライブラリ」をグーグルで検索すると、他のライブラリが得られます。

幸運を!

于 2012-06-13T05:44:17.860 に答える