/// <summary>
        /// Executes an operator with a set of arguments.
        /// </summary>
        /// <param name="op">The operator to execute.</param>
        /// <param name="args">The arguments to use when executing the operator.</param>
        /// <returns>The result of the operation.</returns>
        public Token Operate(RaspyOperator op, Token[] args)
        {
            if (op == null)
            {
                throw new ArgumentNullException("op", "op cannot be null.");
            }

            if (args == null)
            {
                throw new ArgumentNullException("args", "args cannot be null.");
            }

            if (args.Length != op.ArgumentCount)
            {
                throw new ArgumentException("The argument length must match the number of arguments expected by the operator.", "args");
            }

            switch (op.Symbol)
            {
                case '!':
                    return Factorial(args);
                case '^':
                    return Power(args);
                case '*':
                    return Multiply(args);
                case '/':
                    return Divide(args);
                case '%':
                    return Modulo(args);
                case '+':
                    return Add(args);
                case '-':
                    return Subtract(args);
                default:
                    throw new ArgumentException("op", string.Format(CultureInfo.InvariantCulture, "The operator '{0}' is not implemented by this provider.", op.Symbol));
            }
        }
        /// <summary>
        /// Implements the subtract operation.
        /// </summary>
        /// <param name="args">The operand arguments.</param>
        /// <returns>The result of the operation.</returns>
        internal static Token Subtract(Token[] args)
        {
            Operand left = args[0] as Operand;
            Operand right = args[1] as Operand;

            if (left.IsFloat)
            {
                if (right.IsFloat)
                {
                    return new Operand(Convert.ToDouble(left.Value, CultureInfo.InvariantCulture) - Convert.ToDouble(right.Value, CultureInfo.InvariantCulture));
                }
                else
                {
                    return new Operand(Convert.ToDouble(left.Value, CultureInfo.InvariantCulture) - Convert.ToInt64(right.Value, CultureInfo.InvariantCulture));
                }
            }
            else
            {
                if (right.IsFloat)
                {
                    return new Operand(Convert.ToInt64(left.Value, CultureInfo.InvariantCulture) - Convert.ToDouble(right.Value, CultureInfo.InvariantCulture));
                }
                else
                {
                    return new Operand(Convert.ToInt64(left.Value, CultureInfo.InvariantCulture) - Convert.ToInt64(right.Value, CultureInfo.InvariantCulture));
                }
            }
        }
        /// <summary>
        /// Implements the factorial operation.
        /// </summary>
        /// <param name="args">The operand arguments.</param>
        /// <returns>The result of the operation.</returns>
        internal static Token Factorial(Token[] args)
        {
            long f = 1;
            long n = Convert.ToInt64(((Operand)args[0]).Value, CultureInfo.InvariantCulture);

            for (long i = 1; i <= n; i++)
            {
                f *= i;
            }

            return new Operand(f);
        }
        /// <summary>
        /// Implements the power operation.
        /// </summary>
        /// <param name="args">The operand arguments.</param>
        /// <returns>The result of the operation.</returns>
        internal static Token Power(Token[] args)
        {
            Operand left = args[0] as Operand;
            Operand right = args[1] as Operand;
            bool integer = !left.IsFloat && !right.IsFloat;

            double result = Math.Pow(
                Convert.ToDouble(left.Value, CultureInfo.InvariantCulture),
                Convert.ToDouble(right.Value, CultureInfo.InvariantCulture));

            return integer ? new Operand((long)result) : new Operand(result);
        }
        /// <summary>
        /// Implements the divide operation.
        /// </summary>
        /// <param name="args">The operand arguments.</param>
        /// <returns>The result of the operation.</returns>
        internal static Token Divide(Token[] args)
        {
            double left = Convert.ToDouble(((Operand)args[0]).Value, CultureInfo.InvariantCulture);
            double right = Convert.ToDouble(((Operand)args[1]).Value, CultureInfo.InvariantCulture);

            return new Operand(left / right);
        }