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 或 lambda 表达式好东西。此外,我想将代码包含在我的自定义库中,而不仅仅是引用它。谁能指出我一些好的库或代码。

我只需要解析而不是评估表达式并找到正在使用的标记。找到标记后,我需要在解析之前更改表达式字符串,例如如果使用函数ORGVAL,则传递的参数必须以下划线作为前缀。喜欢ORGVAL(BAS)将转变为ORGVAL(_BAS)。有些函数可以有两个参数,例如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);
}

编辑:我知道你说你需要真正得到表达式三,它本身,不仅仅是评估它,而是我处理了代码,所以我想我会继续并将它发布给未来的路人。

于 2012-06-08T11:31:27.480 回答
1

你想做的事情听起来很像解析,所以我认为你不会很幸运地找到不涉及解析的解决方案。如果您想说的是您不想自己编写解析器,那么有几个可用的数学表达式解析库。

我是 Jep.Net (http://www.singularsys.com/jep.net) 的作者之一,它是一个可能适合您需求的表达式解析组件。它有据可查,高度可定制,肯定会让您跳过实现自己的自定义解析器的繁琐且容易出错的过程。如果它不适合您,谷歌搜索“.net 表达式解析库”将为您提供其他库。

祝你好运!

于 2012-06-13T05:44:17.860 回答