0

I'm doing a simple task for investigation purposes. The problem is as follows:

  1. Create an arithmetic expression with variables.
  2. Build an AST for the expression.
  3. Send it to the server (using Sockets)
  4. Calculate an result of the server side and return the results.

Now I can to build a tree. This method doing it:

    private readonly Stack<Expression> expressionStack = new Stack<Expression>();
    private readonly Stack<Symbol> operatorStack = new Stack<Symbol>();
    private readonly List<string> parameters = new List<string>();
    public Expression<Func<decimal[], decimal>> Parse(string expression)
    {
        if (string.IsNullOrWhiteSpace(expression))
        {
            return s => 0;
        }

        var arrayParameter = Expression.Parameter(typeof(decimal[]), "args");

        parameters.Clear();
        operatorStack.Clear();
        expressionStack.Clear();

        using (var reader = new StringReader(expression))
        {
            int peek;
            while ((peek = reader.Peek()) > -1)
            {
                var next = (char)peek;

                if (char.IsDigit(next))
                {
                    expressionStack.Push(ReadOperand(reader));
                    continue;
                }

                if (char.IsLetter(next))
                {
                    expressionStack.Push(ReadParameter(reader, arrayParameter));
                    continue;
                }

                if (Operation.IsDefined(next))
                {
                    if (next == '-' && expressionStack.Count == 0)
                    {
                        reader.Read();
                        operatorStack.Push(Operation.UnaryMinus);
                        continue;
                    }

                    var currentOperation = ReadOperation(reader);

                    EvaluateWhile(() => operatorStack.Count > 0 && operatorStack.Peek() != Parentheses.Left &&
                        currentOperation.Precedence <= ((Operation)operatorStack.Peek()).Precedence);

                    operatorStack.Push(currentOperation);
                    continue;
                }

                if (next == '(')
                {
                    reader.Read();
                    operatorStack.Push(Parentheses.Left);

                    if (reader.Peek() == '-')
                    {
                        reader.Read();
                        operatorStack.Push(Operation.UnaryMinus);
                    }

                    continue;
                }

                if (next == ')')
                {
                    reader.Read();
                    EvaluateWhile(() => operatorStack.Count > 0 && operatorStack.Peek() != Parentheses.Left);
                    operatorStack.Pop();
                    continue;
                }

                if (next == ' ')
                {
                    reader.Read();
                }
                else
                {
                    throw new ArgumentException(string.Format("Encountered invalid character {0}", next),
                        "expression");
                }
            }
        }

        EvaluateWhile(() => operatorStack.Count > 0);

        return Expression.Lambda<Func<decimal[], decimal>>(expressionStack.Pop(), arrayParameter);
    }

This method works, and returns the expected result.
Before being sent to the server I want to serialize a tree to binary type. My question is as follows. Which is the simplest way I can apply for this?
I found a lot of solutions for LINQ serialization, but they are too big. I don't need the full functionality of these solutions. In addition, usually, they provide the JSON or XML-serialization, but I need a binary serialization. Can somebody suggest a simple and easy solution for this problem?

user6408649
  • 1,227
  • 3
  • 16
  • 40
  • 1
    The easiest thing I can think of is to send the original expression string to the server directly, and parse it there... – Pieter Witvoet Jan 26 '17 at 11:30
  • I know it. But it doesn't suit me for some reason. – user6408649 Jan 26 '17 at 11:36
  • 4
    For *what* reason? The server needs access to classes like `Operation` anyway if it is to deserialize faithfully, so you're already sharing code. The best you can hope for is to serialize to something that's easier to parse than your original expression (like an [S-expression](https://en.wikipedia.org/wiki/S-expression) or [RPN](https://en.wikipedia.org/wiki/Reverse_Polish_notation)), but even that barely simplifies things for a language that is already simple on its own. It's not like you'd be saving on parsing. – Jeroen Mostert Jan 26 '17 at 12:15
  • The reason is that it is requirement of the specification. Also, I want to know how to serialize such objects. I'm want serialize this object - `Expression.Lambda>` – user6408649 Jan 26 '17 at 16:59
  • You can do that with an `ExpressionVisitor`, but you'll have to put in some legwork, since you don't like the existing solutions. You can't expect a "simple and easy" solution. – Jeroen Mostert Jan 26 '17 at 19:24

0 Answers0