Reputation: 3
I'm creating tree-like structure allowing user to define math operations. User choses function (say Add), and in node's leafs (at least two, but can be more) user can specify arguments (values or other functions). I thought that using Expressions is a good idea, however it seems, that Expressions supports only binary operations. I wonder if there is some way to create Add function expression with more than two arguments. For instance if I write:
Expression<Func<double, double, double, double>> e = (x, y, z) => x + y + z;
I get tree: [(x + y) + z], so clearly there is some kind of parser.
If there is nothing I could use, I will probably write some logic to manually create subtrees. Or maybe there is a better way? Any help will be appreciated.
Here are my simply node classes:
abstract class Node
{
public abstract void PrepareExpression();
public Expression Expr { get; set; }
public string Name { get; set; }
public IList<Node> InnerNodes { get; set; }
protected Node()
{
InnerNodes = new List<Node>();
}
}
class AddFunction : Node
{
public AddFunction()
{
Name = String.Format("Sum_{0}", Guid.NewGuid());
}
public override void PrepareExpression()
{
var exprParams = new List<ParameterExpression>(InnerNodes.Count);
foreach (var node in InnerNodes)
{
node.PrepareExpression();
}
var binaryExpression = Expression.AddChecked(InnerNodes[0].Expr, InnerNodes[1].Expr);
Expr = binaryExpression;
}
}
class ValueArgument : Node
{
public double Value { get; set; }
public ValueArgument(double value)
{
Name = String.Format("Val_{0}", Guid.NewGuid());
Value = value;
}
public override void PrepareExpression()
{
var constantExpression = Expression.Constant(Value, typeof(double));
Expr = constantExpression;
}
}
And for evaluating whole tree:
rootNode.PrepareExpression();
var expr = Expression.Lambda<Func<double>>(rootNode.Expr);
var exprCom = expr.Compile();
var result = exprCom.Invoke();
Upvotes: 0
Views: 74
Reputation: 8380
The expressions in your example are binary and that's all you need. Just apply them multiple times. The example you provided yourself:
x + y + z = (x + y) + z
corresponds to two applications of a binary operator, i.e. two binary expressions:
Add( Add(x, y), z)
There are two key observations here:
Add
is itself an expression, so it can be the operand of yet another Add
operationUpvotes: 2
Reputation: 866
Are you looking to parse strings into expressions? If so, don't reinvent the wheel. Check out Dijkstra's Shunting Yard algorithm.
Upvotes: 0