tags:

views:

375

answers:

3

Assume I allow the user to input a arbitrary numerical expression that allows usage of the explicit set of functions and predefined variables.

Interpreting this is pretty straight forward but what if performance is a critical factor?

I need a way to compile (in runtime) a string with a expression into something that can be executed 20K times with different values on the variables.

+1  A: 

In C# 4.0, it'll become very easy and straightforward. However, before C# 4.0, I suggest you use Microsoft.JScript libraries to accomplish it.

This is all you want: http://www.odetocode.com/Articles/80.aspx

Mehrdad Afshari
+2  A: 

So really you want to parse the string into (eventually) a typed delegate.

One option, then it to parse the string into an Expression, which you can then compile to a lambda. This is quite complex, but I have some code that will do much of this - but there may be existing parsers that already do the job in full.

As a trivial Expression example:

    var x = Expression.Parameter(typeof(double), "x");
    var y = Expression.Parameter(typeof(double), "y");
    var body = Expression.Multiply(x, y);
    var func = Expression.Lambda<Func<double, double,double>>(body, x, y).Compile();

    double z = func(123.45, 678.90);

The problem is the rest of the parsing code ;-p

I wrote a string to Expression parser last week, but it is more code than I'd normally post here... over 300 lines (not including recognition of bespoke external functions, or named arguments (it currently uses anonymous "?" place-holders)).

but if (as you say) interpreting is easy, then perhaps use similar code to write an Expression that you can compile?

Marc Gravell
The hard part is parsing, of course :)
Mehrdad Afshari
@Mehrdad - I have most of the code "to hand", I'm just not sure this is the best dumping ground... existing parsers probably exist too. And the OP states "Interpreting this is pretty straight forward" so this might not be unfamiliar territory anyway.
Marc Gravell
Yeah, surely this is the better way. The JScript way is vulnerable to dangerous things such as JS injection.
Mehrdad Afshari
This looks as the solution I'm after, but what about performance? (Parsing isn't easy, but it's a common problem that is't easy to find example source code for, didn't mean to trivialize it :)
Niels Bosma
Once you have it compiled to a delegate, the performance will be very, very fast. Essentially, as though had had written a single C# method to do "x + y * z/sin(x)" etc
Marc Gravell
Get back to me if you need help with the parser... I'm fairly easy to track down
Marc Gravell
+2  A: 

Linq Samples by Microsoft already contain implementation of extensible Linq parser.

sealed class Order
{
  public double SubTotal { get; set; }
  public double Shipping { get; set; }
}
static void Main()
{
  var calculateTotal = DynamicExpression
    .ParseLambda<Order, double>("SubTotal*@0+Shipping", 0.12)
    .Compile();

  var order = new Order
  {
    SubTotal = 124.99,
    Shipping = 7.99
  };
  Console.WriteLine(calculateTotal(order));
  Console.ReadLine();
}

You can check out the DbLinq project for sources or this post for more details: Dynamic Linq and Expression Parsing in .NET as a hint of C# compiler extensibility

Rinat Abdullin