What's the easiest way to parse an expression and get a parse tree?

I just want to parse simple expressions like -

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

      

After parsing this, I need to know which functions contain which parameters.

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

      

I was stuck with .Net Framework 2.0, so there was no advantage of Linq or lambda expression for me. Also I want to include the code in my own library, not just link to it. Can anyone point me to some good library or code.

I just need to parse and not evaluate the expression and find which tokens are being used. After detecting tokens, I need to change the expression string before parsing, for example if a function is used ORGVAL

then the passed parameter must be prefixed with an underscore. For example, it ORGVAL(BAS)

converts to ORGVAL(_BAS)

. Some functions may have tow options such as ORGVAL(BAS, "2012/12/31")

, and this is converted toORGVAL(_BAS, "2012/12/31")

NOTE: IF OTHER WAYS TO DO IT PLEASE LET ME KNOW. I LOVE TO AVOID PARSER AND LEXER.

+1


source to share


3 answers


If you don't mind using one of the .NET languages ​​for your code, you can use CodeDom to compile, and the code on the fly and then execute it as an in-memory assembly. For example, this would be the closest approximation to the example expression you showed:

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);
}

      



EDIT: I know you said that you need to actually get expression three, by itself, and not just evaluate it, but I processed the code, so I figured I would just go ahead and post this for future passers-by.

+1


source


It looks like an unpolished but complete expression parser (didn't check it, but might be a starting point).

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



It did, but you mentioned C # 2.0, so it's ok anyway. I'm not sure which version of C # is the whole thing.

+1


source


What you want to do is similar to parsing, so I don't think you can manage to find a solution that doesn't require parsing. If you're trying to say that you don't want to program the parser yourself, there are several math parsing libraries available.

I am one of the authors of Jep.Net (http://www.singularsys.com/jep.net), which is the expression parsing component most likely to suit your needs. It's well documented, customizable, and will definitely let you skip the tedious and error prone process of implementing your own custom parser. And if that doesn't work for you, Googling ".net parsing library library" will provide you with other libraries.

Good luck!

+1


source







All Articles