views:

2356

answers:

14

I would like to allow the user to enter any equation, like the following, into a text box:

x = x / 2 * 0.07914
x = x^2 / 5

And have that equation applied to telemetry data that is coming from a device connected via a serial port. The incoming data points are represented by x and each data point is processed by the user-specified equation. I did this years ago, but I didn't like the solution because it required parsing the text of the equation for every calculation:

float ApplyEquation (string equation, float dataPoint)
{
    // parse the equation string and figure out how to do the math
    // lots of messy code here...
}

When you're processing boatloads of data points, this introduces quite a bit of overhead. I would like to be able to translate the equation into a function, on the fly, so that it only has to be parsed once. It would look something like this:

FunctionPointer foo = ConvertEquationToCode(equation);
....
x = foo(x);  // I could then apply the equation to my incoming data like this

Function ConvertEquationToCode would parse the equation and return a pointer to a function that applies the appropriate math.

The app would basically be writing new code at runtime. Is this possible with .NET?

+2  A: 

You can try looking at either CodeDom or Lambda Expression Trees. I think either one of those should allow you to accomplish this. Expression trees are probably the better way to go but also have a higher learning curve.

Scott Dorman
A: 

I would do a recursive function that doesn't write code but instead applies basic operators to portions of a string based on special characters found in that string. If more than one special character is found, it breaks up the string and calls itself on those two portions.

Totty
What you want is an expression parser. I did this once by converting the expression from infix to postfix then using a stack based posfix parser. Algorithms for both of these are well defined and exist on the web and in books.
Nick
+2  A: 

You could start here and if you really want to get into it, Boo can be modified to meet your needs. You could also integrate LUA with .NET. Any three of these could be utilized within the body of a delegate for your ConvertEquationToCode.

cfeduke
+6  A: 

Yes, definitely possible to have the user type C# into a text box, then compile that code and run it from within your app. We do that at my work to allow for custom business logic.

Here is an article (I haven't more than skimmed it) which should get you started:

http://www.c-sharpcorner.com/UploadFile/ChrisBlake/RunTimeCompiler12052005045037AM/RunTimeCompiler.aspx

rice
+8  A: 

You might try this: Calculator.Net

It will evaluate a math expression.

From the posting it will support the following:

MathEvaluator eval = new MathEvaluator();
//basic math
double result = eval.Evaluate("(2 + 1) * (1 + 2)");
//calling a function
result = eval.Evaluate("sqrt(4)");
//evaluate trigonometric 
result = eval.Evaluate("cos(pi * 45 / 180.0)");
//convert inches to feet
result = eval.Evaluate("12 [in->ft]");
//use variable
result = eval.Evaluate("answer * 10");
//add variable
eval.Variables.Add("x", 10);            
result = eval.Evaluate("x * 10");

Download Page And is distributed under the BSD license.

Brian Schmitt
This doesn't turn the equation into C# code, it just parses it. While it's not what I'm looking for, I'm glad I was made aware of it. May be useful in other circumstances.
raven
You'll want to look at the CodeDom namespace then, it is possible to compile code at runtime.
cfeduke
+3  A: 

I've done this using CSharpCodeProvider by creating the boiler plate class and function stuff as a const string inside my generator class. Then I insert the user code into the boiler plate and compile.

It was fairly straightforward to do, but the danger to this approach is that the user entering the equation could enter just about anything which could be a security issue depending on your application.

If security is at all a concern, I would recommend using Lambda Expression Trees, but if not, using CSharpCodeProvider is a fairly robust option.

Jon Norton
+3  A: 

You can also create a System.Xml.XPath.XPathNavigator from an empty, "dummy" XML stream, and evaluate expressions using the XPath evaluator:

static object Evaluate ( string xp )
{
  return _nav.Evaluate ( xp );
}
static readonly System.Xml.XPath.XPathNavigator _nav
  = new System.Xml.XPath.XPathDocument (
      new StringReader ( "<r/>" ) ).CreateNavigator ( );

If you want to register variables to use within this expression, you can dynamically build XML that you can pass in the Evaluate overload that takes a XPathNodeIterator.

<context>
  <x>2.151</x>
  <y>231.2</y>
</context>

You can then write expressions like "x / 2 * 0.07914" and then x is the value of the node in your XML context. Another good thing is, you will have access to all XPath core functions, which includes mathematics and string manipulation methods, and more stuff.

If you want to take it further, you can even build your own XsltCustomContext(or ill post here on demand) where you can resolve references to extension functions and variables:

object result = Evaluate ( "my:func(234) * $myvar" );

my:func is mapped to a C#/.NET method which takes a double or int as parameter. myvar is registered as a variable within the XSLT context.

baretta
+1  A: 

If all else fails, there are classes under the System.Reflection.Emit namespace which you can use to produce new assemblies, classes, and methods.

Tim
A word of caution though. We used this on .Less (dotlesscss.com), and emitting code usually means horrible performance.
Erik van Brakel
A: 

I don't know if it's possible to implement your ConvertEquationToCode function, however, you can generate a data structure that represents the calculation you need to perform.

For example, you could build a tree whose leaf nodes represent the input for your calculation, whose non-leaf nodes represent intermediate results, and whose root node represents the whole calculation.

It has some advantages. For example, if you're doing what-if analysis and want to change the value of one input at a time, you can recalculate the results that depend on the value that you have changed, while retaining the results that don't.

Eduardo León
A: 

You can use Irony as your expression evaluator.

plinth
He's not forming a compiler per se
0A0D
+2  A: 

Try Vici.Parser: download it here (free) , it's the most flexible expression parser/evaluator I've found so far.

Roel
A: 

http://dotscript.com/Products/ExpressionEvaluator/

This runtime expression evaluator could be exactly what you are looking for.

Blagovest Buyukliev
A: 

you can use system.CodeDom to generate code and compile it on the fly have a look here

Yassir
A: 

You could implement a postfix stack calculator. Basically what you have to do is convert the expression to postfix notation, and then simply iterate over the tokens in your postfix to calculate.

Erik van Brakel