1

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 should be able to know what functions contains what parameters.

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

I'm stuck with .Net Framework 2.0, so no Linq or lambda expression goodies for me. Also I want to include the code in my custom library and not just reference it. Can anyone point me to some good library or code.

I just need to parse and not evaluate the expression and find what tokens are in use. After finding the tokens I need to change the expression string before parsing, like if the function ORGVAL is used then the parameter passed has has to be prefixed by an underscore. Like ORGVAL(BAS) will transform to ORGVAL(_BAS). Some functions can have tow parameters like ORGVAL(BAS, "2012/12/31") and this will transform to ORGVAL(_BAS, "2012/12/31")

NOTE: IF THERE ARE OTHER WAYS OF DOING IT PLEASE LET ME KNOW. I WOULD LOVE TO AVOID A PARSER AND LEXER.

3
  • ANTLR. Or another syntax parser.. Commented Jun 8, 2012 at 10:49
  • @Yossarian ANTLR is too tough for me. I couldn't understand anything about it. Something simpler maybe. Commented Jun 8, 2012 at 10:50
  • Dismissing a common solution makes this the hallmark of a shopping question. Off topic on all SE sites. Commented Jun 8, 2012 at 12:01

3 Answers 3

1

If you don't mind using one of the .NET languages for the code, you can use CodeDom to compile and the code on the fly and then execute it as an in-memory-only assembly. For instance, 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 you need to actually get the expression three, itself, not just evaluate it, but I worked up the code, so I figured I'd just go ahead and post it for future passers-by.

Sign up to request clarification or add additional context in comments.

1 Comment

We have tried this method and this is extremely slow. We have shifted to using Flee instead. This is much faster. But for some bad technical design which is still being carried on I need to change the expression based on some logic. Anyway all I want to do is replace BAS by _BAS.
1

This looks like an unpolished but complete expression parser (haven't tested it, but might be a starting point).

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

It's old but you mentioned C# 2.0 so it might be alright anyway. I'm not sure which version of C# it targets though.

Comments

1

What you want to do sounds a lot like parsing, so I don't think you'll have much luck finding a solution that doesn't involve parsing. If what you are trying to say is you don't want to program a parser yourself then there are several math expression parsing libraries available.

I am one of the authors of Jep.Net (http://www.singularsys.com/jep.net) which is an expression parsing component that would likely suit your needs. It is well documented, highly customizable and would definitely let you skip the tedious and error-prone process of implementing your own custom parser. And if it's not a fit for you, Googling ".net expression parsing library" will get you other libraries.

Good luck!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.