Number() приватный статический Метод

private static Number ( string expression, int &index ) : double
expression string
index int
Результат double
    private Expression F()
    {
        if (lexer.Current == LexicalToken.Id)
        {
            var result = Expression.Identifier(lexer.Value);
            AddVariable(lexer.Value);
            lexer.Next();

            return(result);
        }
        else if (lexer.Current == LexicalToken.Num)
        {
            var result = Expression.Number(lexer.Value);
            lexer.Next();

            return(result);
        }
        else if (lexer.Current == LexicalToken.OpenPar)
        {
            lexer.Next();
            var e = E();
            lexer.Expect(LexicalToken.ClosePar);
            return(Expression.Parenthesis(e));
        }
        else
        {
            throw new ApplicationException(String.Format("Parse error: Incorrent token '{0}' encountered. Expected ')'.", lexer.Value));
        }
    }
    public BinaryExpression(string left, char op, string right)
    {
        int temp1;

        if (Int32.TryParse(left, out temp1))
        {
            int temp2;

            if (Int32.TryParse(right, out temp2))
            {
                Init(Expression.Number(temp1), Expression.Operator(op), Expression.Number(temp2));
            }
            else
            {
                Init(Expression.Number(temp1), Expression.Operator(op), Expression.Identifier(right));
            }
        }
        else
        {
            int temp2;

            if (Int32.TryParse(right, out temp2))
            {
                Init(Expression.Identifier(left), Expression.Operator(op), Expression.Number(temp2));
            }
            else
            {
                Init(Expression.Identifier(left), Expression.Operator(op), Expression.Identifier(right));
            }
        }
    }
Пример #3
0
 public IList <ITypeTranslationContext> BuildDefault()
 {
     return(new List <ITypeTranslationContext>
     {
         TypeTranslationContextFactory.Direct(typeof(object), Expression.Any()),
         TypeTranslationContextFactory.Direct(typeof(short), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(int), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(long), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(ushort), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(uint), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(ulong), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(byte), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(sbyte), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(float), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(double), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(decimal), Expression.Number()),
         TypeTranslationContextFactory.Direct(typeof(bool), Expression.Bool()),
         TypeTranslationContextFactory.Direct(typeof(string), Expression.String()),
         TypeTranslationContextFactory.Direct(typeof(char), Expression.String()),   // TODO consider better options if possible
         TypeTranslationContextFactory.Direct(typeof(DateTime), Expression.Date()), // TODO consider better options if possible
         // TODO TimeSpan -> ???
         TypeTranslationContextFactory.Enum(),
         TypeTranslationContextFactory.Nullable(),
         TypeTranslationContextFactory.GenericDictionary(),
         TypeTranslationContextFactory.Special(typeof(IDictionary), Expression.UntypedDictionary()),
         TypeTranslationContextFactory.Array(),
         TypeTranslationContextFactory.GenericEnumerable(),
         TypeTranslationContextFactory.Special(typeof(IEnumerable), Expression.UntypedArray())
     });
 }
Пример #4
0
        public void PrettyPrinter_Object()
        {
            var d = new Dictionary <string, Expression>
            {
                { "bar", Expression.Number("1") },
                { "foo", Expression.Number("2") },
            };

            AssertPretty(Expression.Object(d), "{" + Environment.NewLine + "  \"bar\": 1," + Environment.NewLine + "  \"foo\": 2" + Environment.NewLine + "}");
        }
Пример #5
0
        private Expression numbers(IList <Token> tokens, ref int index)
        {
            if (index < tokens.Count && tokens[index].Type == Symbol.Number)
            {
                double number = double.Parse(tokens[index].Value);
                index++;

                return(Expression.Number(number));
            }

            throw new Exception("Unknown token");
        }
    public BinaryExpression(Expression left, OperatorExpression op, string right)
    {
        int temp;

        if (Int32.TryParse(right, out temp))
        {
            Init(left, op, Expression.Number(temp));
        }
        else
        {
            Init(left, op, Expression.Identifier(right));
        }
    }
    public BinaryExpression(string left, char op, Expression right)
    {
        int temp;

        if (Int32.TryParse(left, out temp))
        {
            Init(Expression.Number(temp), Expression.Operator(op), right);
        }
        else
        {
            Init(Expression.Identifier(left), Expression.Operator(op), right);
        }
    }
Пример #8
0
            public override Expression VisitConstant(ConstantExpression node)
            {
                if (node.NodeType == ExpressionType.Number)
                {
                    var value = int.Parse((string)node.Value);

                    if (value % 2 == 0)
                    {
                        return(Expression.Number((value / 2).ToString()));
                    }
                }

                return(base.VisitConstant(node));
            }
        public void UnaryOperationExpressionHelpersRequireExpression()
        {
            Expression expression = null;

            Expect.Throw <ArgumentNullException>(() => expression.BitwiseNot());
            Expect.Throw <ArgumentNullException>(() => expression.Delete());
            Expect.Throw <ArgumentNullException>(() => expression.Group());
            Expect.Throw <ArgumentNullException>(() => expression.LogicalNot());
            Expect.Throw <ArgumentNullException>(() => expression.Negative());
            Expect.Throw <ArgumentNullException>(() => expression.New());
            Expect.Throw <ArgumentNullException>(() => expression.Number());
            Expect.Throw <ArgumentNullException>(() => expression.PostDecrement());
            Expect.Throw <ArgumentNullException>(() => expression.PostIncrement());
            Expect.Throw <ArgumentNullException>(() => expression.PreDecrement());
            Expect.Throw <ArgumentNullException>(() => expression.PreIncrement());
            Expect.Throw <ArgumentNullException>(() => expression.TypeOf());
        }
Пример #10
0
        public override Expression Differentiate(IList <Expression> arguments, int position, int count)
        {
            if (count != 2)
            {
                throw new Exception("Logarithm function can't take more than 2 arguments");
            }

            Expression b = arguments[0];
            Expression x = arguments[1];

            if (position == 1)
            {
                return(Expression.Divide(Expression.Number(1), Expression.Multiply(x, Expression.Function(Alias, b))));
            }

            return(Expression.Divide(Expression.Multiply(Expression.Number(-1), Expression.Function(Alias, b)), Expression.Multiply(x, Expression.Power(Expression.Function(Alias, x), Expression.Number(2)))));
        }
Пример #11
0
        public Expression Eliminate(Expression expr)
        {
            if (expr is FunctionExpression)
            {
                FunctionExpression fexpr = (FunctionExpression)expr;

                IList <Expression> arguments = new List <Expression>();

                foreach (Expression arg in fexpr.Arguments)
                {
                    arguments.Add(Eliminate(arg));
                }

                return(Expression.Function(fexpr.Name, arguments));
            }
            else if (expr is BinaryExpression)
            {
                BinaryExpression bexpr = (BinaryExpression)expr;

                Expression left  = Eliminate(bexpr.Left);
                Expression right = Eliminate(bexpr.Right);

                if (bexpr.Operator == Binary.Subtract)
                {
                    if (right is NumberExpression)
                    {
                        double num = ((NumberExpression)right).Value;
                        num *= -1;

                        right = Expression.Number(num);
                    }
                    else
                    {
                        right = Expression.Multiply(Expression.Number(-1), right);
                    }

                    return(Expression.FromBinary(Binary.Add, left, right));
                }

                return(Expression.FromBinary(bexpr.Operator, left, right));
            }

            return(expr);
        }
Пример #12
0
        /// <summary>
        /// Parses the given JSON token stream and returns an expression tree representing the JSON expression.
        /// </summary>
        /// <param name="tokens">JSON token stream to be parsed.</param>
        /// <returns>Expression tree representing the JSON expression.</returns>
        private static Expression Parse(IEnumerator <Token> tokens)
        {
            //
            // JSON is LL(1); we can simply look-ahead one symbol to decide how to proceed
            // with parsing, i.e. { indicates an object, [ indicates an array, etc.
            //
            var token = tokens.Current;

            return(token.Type switch
            {
                TokenType.LeftCurly => ParseObject(tokens),
                TokenType.LeftBracket => ParseArray(tokens),
                TokenType.False => Expression.Boolean(false),
                TokenType.True => Expression.Boolean(true),
                TokenType.Null => Expression.Null(),
                TokenType.String => Expression.String(token.Data),
                TokenType.Number => Expression.Number(token.Data),
                _ => throw new ParseException("Unexpected token: " + token.Type, token.Position, ParseError.UnexpectedToken),
            });
Пример #13
0
    static void Main()
    {
        // create abstract syntax tree for
        // the expression: a + b * 4 - 1

        var exp1 = Expression.Binary(Expression.Identifier("b"), Expression.Operator('*'), Expression.Number(4));
        var exp2 = Expression.Binary(Expression.Identifier("a"), Expression.Operator('+'), exp1);
        var exp3 = Expression.Binary(exp2, Expression.Operator('-'), Expression.Number(1));

        var context = new Context();

        context.Variables.Add("a", 2);
        context.Variables.Add("b", 3);

        exp3.Interpret(context);

        Console.WriteLine(context.Value);               // writes 13

        Console.ReadKey();
    }
Пример #14
0
        /// <summary>
        /// Parses the given JSON token stream and returns an expression tree representing the JSON expression.
        /// </summary>
        /// <param name="tokens">JSON token stream to be parsed.</param>
        /// <returns>Expression tree representing the JSON expression.</returns>
        private static Expression Parse(IEnumerator <Token> tokens)
        {
            //
            // JSON is LL(1); we can simply look-ahead one symbol to decide how to proceed
            // with parsing, i.e. { indicates an object, [ indicates an array, etc.
            //
            var token = tokens.Current;

            switch (token.Type)
            {
            case TokenType.LeftCurly:
                return(ParseObject(tokens));

            case TokenType.LeftBracket:
                return(ParseArray(tokens));

            case TokenType.False:
                return(Expression.Boolean(false));

            case TokenType.True:
                return(Expression.Boolean(true));

            case TokenType.Null:
                return(Expression.Null());

            case TokenType.String:
                return(Expression.String(JsonStringToBclString(token.Data)));

            case TokenType.Number:
                return(Expression.Number(token.Data));

            case TokenType.Eof:
            case TokenType.White:     // indicates improper filtering earlier on
            case TokenType.RightCurly:
            case TokenType.RightBracket:
            case TokenType.Comma:
            case TokenType.Colon:
            default:
                throw new ParseException("Unexpected token: " + token.Type, token.Position, ParseError.UnexpectedToken);
            }
        }
Пример #15
0
        public void ExpressionVisitor_Unchanged()
        {
            var e1 = Expression.Null();
            var e2 = Expression.Number("42");
            var e3 = Expression.String("foo");
            var e4 = Expression.Array(e2, e3);
            var e5 = Expression.Object(new Dictionary <string, Expression> {
                { "bar", e2 }, { "foo", e3 }
            });

            var v = new ExpressionVisitor();

            var es = new Expression[]
            {
                e1, e2, e3, e4, e5,
            };

            foreach (var e in es)
            {
                Assert.AreSame(e, v.Visit(e));
            }
        }
Пример #16
0
        public void TokenStack_Push1()
        {
            var tokens = new TokenStack();

            Assert.IsFalse(tokens.TryPop(out _));
            Assert.AreEqual(0, tokens.Count);

            for (var i = 0; i < 99; i++)
            {
                tokens.Push(new Token {
                    Expression = Expression.Number(i.ToString())
                });
                Assert.AreEqual(i + 1, tokens.Count);
            }

            for (var i = 98; i >= 0; i--)
            {
                Assert.IsTrue(tokens.TryPop(out var token));
                Assert.AreEqual(i, tokens.Count);
                Assert.AreEqual(i.ToString(), ((ConstantExpression)token.Expression).Value);
            }
        }
Пример #17
0
        /// <summary>
        /// Recursive serialization method.
        /// </summary>
        /// <param name="o">Object to serialize.</param>
        /// <param name="refs">Stack to keep track of objects being serialized, to spot cycles.</param>
        /// <returns>JSON expression tree for the serialized object.</returns>
        private Expression Serialize(object o, Stack <object> refs)
        {
            if (o == null)
            {
                return(Expression.Null());
            }

            var type = o.GetType();

            // Nullables are weird. If they're not assigned null, we'll see their underlying value type here.
            // The null check above takes care of our untyped null case.

            if (type.IsEnum)
            {
                type = Enum.GetUnderlyingType(type);
            }

            if (type == typeof(string))
            {
                return(Expression.String((string)o));
            }
            else if (type == typeof(bool))
            {
                return(Expression.Boolean((bool)o));
            }
            else if (type == typeof(int))
            {
                return(Expression.Number(((int)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(uint))
            {
                return(Expression.Number(((uint)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(byte))
            {
                return(Expression.Number(((byte)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(sbyte))
            {
                return(Expression.Number(((sbyte)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(long))
            {
                return(Expression.Number(((long)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(ulong))
            {
                return(Expression.Number(((ulong)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(short))
            {
                return(Expression.Number(((short)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(ushort))
            {
                return(Expression.Number(((ushort)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(float))
            {
                return(Expression.Number(((float)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(double))
            {
                return(Expression.Number(((double)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type == typeof(decimal))
            {
                return(Expression.Number(((decimal)o).ToString(CultureInfo.InvariantCulture)));
            }
            else if (type.IsArray || type.GetInterface("System.Collections.Generic.IList`1", false) != null || typeof(IList).IsAssignableFrom(type))
            {
                return(SerializeArray(o, refs));
            }
            else
            {
                return(SerializeObject(o, refs));
            }
        }
Пример #18
0
 public override Expression Differentiate(Expression argument)
 {
     return(Expression.Divide(Expression.Number(1), argument));
 }
Пример #19
0
 public void JsonExpressionReader_Primitives_Decimal_InvalidInput()
 {
     Deserialize(FloatParseHandling.Decimal, Expression.Number("12.34???"));
 }
Пример #20
0
        public Expression Simplify(Expression expr)
        {
            if (expr is VariableExpression)
            {
                VariableExpression vexpr = (VariableExpression)expr;
                string             name  = vexpr.Name;

                if (existsVariable(name))
                {
                    return(getVariable(name));
                }
            }
            else if (expr is FunctionExpression)
            {
                FunctionExpression fexpr = (FunctionExpression)expr;
                string             name  = fexpr.Name;

                bool exists = existsFunction(name);

                if (exists && !acceptsFunction(name, fexpr.Arguments.Count))
                {
                    throw new Exception("Function doesn't accept as many arguments");
                }

                IList <double>     varguments = new List <double>();
                IList <Expression> arguments  = new List <Expression>();

                foreach (Expression arg in fexpr.Arguments)
                {
                    Expression sarg = Simplify(arg);
                    arguments.Add(sarg);

                    if (sarg is NumberExpression)
                    {
                        varguments.Add(((NumberExpression)sarg).Value);
                    }
                }

                if (exists)
                {
                    if (varguments.Count == arguments.Count)
                    {
                        return(Expression.Number(calculateFunction(name, varguments)));
                    }

                    return(evaluateFunction(name, arguments));
                }
                else
                {
                    return(Expression.Function(name, arguments));
                }
            }
            else if (expr is BinaryExpression)
            {
                BinaryExpression bexpr = (BinaryExpression)expr;

                Binary op = bexpr.Operator;

                Expression left  = Simplify(bexpr.Left);
                Expression right = Simplify(bexpr.Right);

                if (left is NumberExpression && right is NumberExpression)
                {
                    return(calculate(op, (NumberExpression)left, (NumberExpression)right));
                }
                else if (left is NumberExpression || right is NumberExpression)
                {
                    double     num;
                    Expression other;

                    bool isLeft = true;

                    if (left is NumberExpression)
                    {
                        num   = ((NumberExpression)left).Value;
                        other = right;
                    }
                    else
                    {
                        isLeft = false;

                        num   = ((NumberExpression)right).Value;
                        other = left;
                    }

                    if (num == 0 && op == Binary.Add ||
                        num == 0 && op == Binary.Subtract && !isLeft ||
                        num == 1 && op == Binary.Multiply ||
                        num == 1 && op == Binary.Divide && !isLeft ||
                        num == 1 && op == Binary.Power && !isLeft)
                    {
                        return(other);
                    }

                    if (num == 0 && op == Binary.Multiply ||
                        num == 0 && op == Binary.Divide && isLeft ||
                        num == 0 && op == Binary.Power && isLeft)
                    {
                        return(Expression.Number(0));
                    }

                    if (num == 0 && op == Binary.Power && !isLeft ||
                        num == 1 && op == Binary.Power && isLeft)
                    {
                        return(Expression.Number(1));
                    }

                    if (isLeft && op == Binary.Add)
                    {
                        return(Expression.Add(right, left));
                    }

                    if (!isLeft && op == Binary.Multiply)
                    {
                        return(Expression.Multiply(right, left));
                    }
                }
                else
                {
                    if (op == Binary.Divide && left.Equals(right))
                    {
                        return(Expression.Number(1));
                    }

                    if (op == Binary.Subtract && left.Equals(right))
                    {
                        return(Expression.Number(0));
                    }

                    if (op == Binary.Add && right is BinaryExpression && ((BinaryExpression)right).Operator == Binary.Multiply && ((BinaryExpression)right).Left is NumberExpression && ((NumberExpression)((BinaryExpression)right).Left).Value == -1)
                    {
                        BinaryExpression bright = (BinaryExpression)right;

                        if (left.Equals(bright.Right))
                        {
                            return(Expression.Number(0));
                        }
                    }
                }

                return(Expression.FromBinary(bexpr.Operator, left, right));
            }
            else if (expr is LinearExpression)
            {
                LinearExpression lexpr = (LinearExpression)expr;

                IList <Expression> list = new List <Expression>();

                foreach (Expression item in lexpr.List)
                {
                    list.Add(Simplify(item));
                }

                return(new LinearExpression(lexpr.Operator, list));
            }

            return(expr);
        }
Пример #21
0
 public void PrettyPrinter_Array()
 {
     AssertPretty(Expression.Array(Expression.Number("1"), Expression.Number("2")), "[" + Environment.NewLine + "  1," + Environment.NewLine + "  2" + Environment.NewLine + "]");
 }
Пример #22
0
 public void PrettyPrinter_Constant_Int()
 {
     AssertPretty(Expression.Number("42"), "42");
 }
Пример #23
0
        public Expression Differentiate(Expression expr)
        {
            if (expr is NumberExpression)
            {
                return(Expression.Number(0));
            }
            else if (expr is VariableExpression)
            {
                VariableExpression vexpr = (VariableExpression)expr;

                if (vexpr.Name != var)
                {
                    return(Expression.Number(0));
                }

                return(Expression.Number(1));
            }
            else if (expr is FunctionExpression)
            {
                FunctionExpression fexpr = (FunctionExpression)expr;

                if (fexpr.Arguments.Count == 0)
                {
                    return(Expression.Number(0));
                }

                int pos = 0;

                Expression result = null;

                foreach (Expression arg in fexpr.Arguments)
                {
                    Expression darg = Differentiate(arg);

                    if (darg.Equals(Expression.Number(0)))
                    {
                        pos++;
                        continue;
                    }
                    else
                    {
                        Expression argResult  = null;
                        Expression derivative = null;

                        if (fexpr.Arguments.Count > 1)
                        {
                            derivative = functions.Differentiate(fexpr.Name, fexpr.Arguments, pos, fexpr.Arguments.Count);
                        }
                        else
                        {
                            derivative = functions.Differentiate(fexpr.Name, fexpr.Arguments[0]);
                        }

                        if (darg.Equals(Expression.Number(1)))
                        {
                            argResult = derivative;
                        }
                        else
                        {
                            argResult = Expression.Multiply(derivative, darg);
                        }

                        if (result == null)
                        {
                            result = argResult;
                        }
                        else
                        {
                            result = Expression.Add(result, argResult);
                        }
                    }

                    pos++;
                }

                if (result == null)
                {
                    result = Expression.Number(0);
                }

                return(result);
            }
            else if (expr is BinaryExpression)
            {
                BinaryExpression bexpr = (BinaryExpression)expr;

                Expression left  = bexpr.Left;
                Expression right = bexpr.Right;

                Expression dleft  = Differentiate(left);
                Expression dright = Differentiate(right);

                if (bexpr.Operator == Binary.Add)
                {
                    return(Expression.Add(dleft, dright));
                }
                else if (bexpr.Operator == Binary.Subtract)
                {
                    return(Expression.Subtract(dleft, dright));
                }
                else if (bexpr.Operator == Binary.Multiply)
                {
                    if (dleft.Equals(Expression.Number(0)))
                    {
                        return(Expression.Multiply(left, dright));
                    }
                    else if (dright.Equals(Expression.Number(0)))
                    {
                        return(Expression.Multiply(dleft, right));
                    }

                    return(Expression.Add(Expression.Multiply(dleft, right), Expression.Multiply(left, dright)));
                }
                else if (bexpr.Operator == Binary.Divide)
                {
                    if (dright.Equals(Expression.Number(0)))
                    {
                        return(Expression.Divide(dleft, right));
                    }
                    else if (dleft.Equals(Expression.Number(0)))
                    {
                        return(Expression.Divide(Expression.Multiply(Expression.Multiply(Expression.Number(-1), left), dright), Expression.Power(right, Expression.Number(2))));
                    }

                    return(Expression.Divide(Expression.Subtract(Expression.Multiply(dleft, right), Expression.Multiply(left, dright)), Expression.Power(right, Expression.Number(2))));
                }
                else if (bexpr.Operator == Binary.Power)
                {
                    if (dright.Equals(Expression.Number(0)))
                    {
                        return(Expression.Multiply(Expression.Multiply(right, Expression.Power(left, Expression.Subtract(right, Expression.Number(1)))), dleft));
                    }
                    else if (dleft.Equals(Expression.Number(0)))
                    {
                        return(Expression.Multiply(Expression.Multiply(Expression.Power(left, right), dright), log(left)));
                    }

                    return(Expression.Multiply(expr, Expression.Add(Expression.Multiply(dright, log(left)), Expression.Multiply(right, Expression.Divide(dleft, left)))));
                }
            }

            return(expr);
        }
Пример #24
0
        public override Expression Evaluate(IList <Expression> arguments)
        {
            Expression arg = arguments[0];

            return(Expression.Power(arg, Expression.Number(0.5)));
        }
Пример #25
0
 public void Add(string name, double value)
 {
     vars.Add(name, Expression.Number(value));
 }
 public BinaryExpression(double left, OperatorExpression op, double right)
 {
     Init(Expression.Number(left), op, Expression.Number(right));
 }
 public BinaryExpression(double left, char op, double right)
 {
     Init(Expression.Number(left), Expression.Operator(op), Expression.Number(right));
 }
Пример #28
0
 public override Expression Differentiate(Expression argument)
 {
     return(Expression.Multiply(Expression.Number(-1), Expression.Function(Sine.Alias, argument)));
 }
Пример #29
0
        public Expression ReturnSubtraction(Expression expr)
        {
            if (expr is FunctionExpression)
            {
                FunctionExpression fexpr = (FunctionExpression)expr;

                IList <Expression> args = new List <Expression>();

                foreach (Expression arg in fexpr.Arguments)
                {
                    args.Add(Return(arg));
                }

                return(Expression.Function(fexpr.Name, args));
            }
            else if (expr is BinaryExpression)
            {
                BinaryExpression bexpr = (BinaryExpression)expr;

                Expression left  = ReturnSubtraction(bexpr.Left);
                Expression right = ReturnSubtraction(bexpr.Right);

                Expression oleft  = left;
                Expression oright = right;

                if (bexpr.Operator == Binary.Multiply || bexpr.Operator == Binary.Divide)
                {
                    /*
                     * bool negative = false;
                     *
                     * NumberExpression number = null;
                     * bool isLeft = false;
                     *
                     * if (left is NumberExpression && ((NumberExpression)left).Value < 0)
                     * {
                     *  negative = true;
                     *  nleft = Expression.Number(((NumberExpression)left).Value * -1);
                     *
                     *  isLeft = true;
                     *  number = (NumberExpression)nleft;
                     * }
                     * else if (right is NumberExpression && ((NumberExpression)right).Value < 0)
                     * {
                     *  negative = true;
                     *  nright = Expression.Number(((NumberExpression)right).Value * -1);
                     *
                     *  number = (NumberExpression)nright;
                     * }
                     *
                     * if (left is NegativeExpression || right is NegativeExpression)
                     *  negative = !negative;
                     *
                     * if (left is NegativeExpression)
                     * {
                     *  nleft = ((NegativeExpression)nleft).Value;
                     *  left = ((NegativeExpression)left).Original;
                     * }
                     * else if (right is NegativeExpression)
                     * {
                     *  nright = ((NegativeExpression)nright).Value;
                     *  right = ((NegativeExpression)right).Original;
                     * }
                     *
                     * Expression toReturn = null;
                     *
                     * if (number != null && number.Value == 1 && (bexpr.Operator == Binary.Multiply || bexpr.Operator == Binary.Divide && !isLeft))
                     * {
                     *  if (isLeft)
                     *      toReturn = nright;
                     *  else
                     *      toReturn = nleft;
                     * }
                     * else
                     *  toReturn = Expression.FromBinary(bexpr.Operator, nleft, nright);
                     *
                     * if (!negative)
                     *  return toReturn;
                     *
                     * return new NegativeExpression(toReturn, Expression.FromBinary(bexpr.Operator, left, right));
                     */

                    bool negative = false;

                    if (left is NegativeExpression)
                    {
                        negative = !negative;

                        oleft = ((NegativeExpression)left).Original;
                        left  = ((NegativeExpression)left).Value;
                    }

                    if (right is NegativeExpression)
                    {
                        negative = !negative;

                        oright = ((NegativeExpression)right).Original;
                        right  = ((NegativeExpression)right).Value;
                    }

                    Expression full = null;

                    if (left is NumberExpression && ((NumberExpression)left).Value == 1 && bexpr.Operator == Binary.Multiply)
                    {
                        full = right;
                    }
                    else if (right is NumberExpression && ((NumberExpression)right).Value == 1 && (bexpr.Operator == Binary.Multiply || bexpr.Operator == Binary.Divide))
                    {
                        full = left;
                    }
                    else
                    {
                        full = Expression.FromBinary(bexpr.Operator, left, right);
                    }

                    if (negative)
                    {
                        full = new NegativeExpression(full, Expression.FromBinary(bexpr.Operator, oleft, oright));
                    }

                    return(full);
                }
                else if (bexpr.Operator == Binary.Add && (left is NegativeExpression || right is NegativeExpression))
                {
                    if (!(left is NegativeExpression) && right is NegativeExpression)
                    {
                        return(Expression.Subtract(left, ((NegativeExpression)right).Value));
                    }
                    else if (left is NegativeExpression && !(right is NegativeExpression))
                    {
                        return(Expression.Subtract(right, ((NegativeExpression)left).Value));
                    }
                    else
                    {
                        return(Expression.Subtract(((NegativeExpression)left).Original, ((NegativeExpression)right).Value));
                    }
                }

                return(Expression.FromBinary(bexpr.Operator, left, right));
            }
            else if (expr is NumberExpression)
            {
                NumberExpression nexpr = (NumberExpression)expr;

                if (nexpr.Value < 0)
                {
                    return(new NegativeExpression(Expression.Number(-1 * nexpr.Value), nexpr));
                }

                return(nexpr);
            }

            return(expr);
        }