I have a custom expression program with a lexer, parser and evaluator. How do I LINQ-ify it?

c#, iqueryable, linq

Solution

Walk your expression tree, and convert each element to an object from the `System.Linq.Expressions` namespace, using the factory methods of the `Expression` class.

If you cannot modify your `IExpression` class to add methods that let you implement the visitor pattern, you can rely on type checking the old style:

private static Expression ConvertExpression(IExpression expr) {
    if (expr is ILiteralExpression) {
        return Expression.Constant(((ILiteralExpression)expr).Value);
    }
    if (expr is IOperatorExpression) {
        var ops = ((IOperatorExpression)expr)
            .Operands
            .Select(ConvertExpression)
            .ToList();
        var res = ops[0];
        for (int i = 1 ; i != ops.Length ; i++) {
            if (((IOperatorExpression)expr).OperatorUniqueName == "+") {
                res = Expressions.Add(res, ops[i]);
            } else if (((IOperatorExpression)expr).OperatorUniqueName == "-") {
                res = Expressions.Subtract(res, ops[i]);
            } else if (...) {
            }
        }
        return res;
    }
}

Of course you'll need a lot more logic in this method. The crucial part is passing parameters: you need to figure out where your variables are and what is their type, use `Expression.ParameterExpression` to create it, and then compile your converted expression into a `Func<...>` of some sort using the `LambdaExpression.Compile` method. With a compiled lambda in hand, you can plug in your expressions into LINQ's in-memory framework.

If you can make your `IExpressions` visitable, add a visitor that walks the expression and converts it to a LINQ expression using a stack.

Problem

Here are my interfaces and enum, dumbed down slightly. : ``` public interface IExpression { ExpressionType ExpressionType { get; } } public interface ILiteralExpression : IExpression { object Value { get; set; } } public interface IOperatorExpression : IExpression { IExpression[] Operands { get; set; } string OperatorUniqueName { get; set; } IOperatorExpression SetOperand(int index, IExpression expression); } public enum ExpressionType { Operator, Literal } ``` To create an expression, I can do something like this: ``` var expression = ExpressionManager.Engines["Default"].Parser.Parse("1 + 3 * 4 + \"myVariable\""); ``` Which is equivalent to something like this: ``` var expression1 = ExpressionManager.CreateOperator("Add", 2). SetOperand(0, ExpressionManager.CreateOperator("Add", 2). SetOperand(0, ExpressionManager.CreateLiteral(1)). SetOperand(1, ExpressionManager.CreateOperator("Multiply", 2). SetOperand(0, ExpressionManager.CreateLiteral(3)). SetOperand(1, ExpressionManager.CreateLiteral(4)))). SetOperand(1, ExpressionManager.CreateLiteral("myVariable")); ``` I'd like to be able to do something like this (efficiently): ``` (from e in expression where e is ILiteralExpression && "myVariable".Equals(((ILiteralExpression)e).Value) select (ILiteralExpression)e).ToList(). ForEach(e => e.Value = 2); ``` I think I need to do some implementing of `IQueryable` or something, but I'm not sure where to start. Any suggestions?

Original source