/// <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>
        /// 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));
            }
        }
예제 #3
0
        /// <summary>
        /// Parses an infix expression into a an RPN token queue.
        /// </summary>
        /// <param name="expression">The expression to parse.</param>
        /// <returns>An RPN token queue.</returns>
        public ExpressionQueue Parse(string expression)
        {
            ExpressionQueue output = new ExpressionQueue(expression);
            Stack <Token>   stack  = new Stack <Token>();

            if (!string.IsNullOrEmpty(expression))
            {
                int        i = 0;
                ReadResult result;

                while (i < expression.Length)
                {
                    result = this.ReadOperand(expression, i);

                    if (result.Success)
                    {
                        output.Enqueue(result.Token);
                        i = result.Position;
                    }
                    else
                    {
                        result = this.ReadOperator(expression, i);

                        if (result.Success)
                        {
                            RaspyOperator op1 = (RaspyOperator)result.Token;

                            while (stack.Count > 0 && stack.Peek().IsOperator)
                            {
                                RaspyOperator op2 = (RaspyOperator)stack.Peek();

                                if ((op1.Associativity == Associativity.Left && op1.Precedence <= op2.Precedence) ||
                                    (op1.Associativity == Associativity.Right && op1.Precedence < op2.Precedence))
                                {
                                    output.Enqueue(stack.Pop());
                                }
                                else
                                {
                                    break;
                                }
                            }

                            stack.Push(result.Token);
                            i = result.Position;
                        }
                        else if (expression[i] == '(')
                        {
                            stack.Push(new Parenthesis(ParenthesisType.Left));
                            i++;
                        }
                        else if (expression[i] == ')')
                        {
                            bool foundLeft = false;

                            while (stack.Count > 0)
                            {
                                Token token = stack.Peek();

                                if (token.IsOperator)
                                {
                                    output.Enqueue(stack.Pop());
                                }
                                else if (token.IsParenthesis)
                                {
                                    if (((Parenthesis)token).ParenthesisType == ParenthesisType.Left)
                                    {
                                        stack.Pop();
                                        foundLeft = true;
                                        break;
                                    }
                                }
                            }

                            i++;

                            if (!foundLeft)
                            {
                                throw new RaspyParseException("The expression contains mismatched parentheses.", expression);
                            }
                        }
                        else if (!char.IsWhiteSpace(expression[i]))
                        {
                            throw new RaspyParseException(string.Format(CultureInfo.InvariantCulture, "The expression contains an invalid character, '{0}'.", expression[i]), expression);
                        }
                        else
                        {
                            i++;
                        }
                    }
                }

                while (stack.Count > 0)
                {
                    Token token = stack.Peek();

                    if (!token.IsParenthesis)
                    {
                        output.Enqueue(stack.Pop());
                    }
                    else
                    {
                        throw new RaspyParseException("The expression contains mismatched parentheses.", expression);
                    }
                }
            }

            return(output);
        }
예제 #4
0
        /// <summary>
        /// Evaluates a parsed arithmetic expression.
        /// </summary>
        /// <param name="expression">The expression to evaluate.</param>
        /// <returns>The result of the evaluation.</returns>
        public object Evaluate(ExpressionQueue expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression", "expression cannot be null.");
            }

            string        infixExpression  = expression.InfixExpression;
            string        parsedExpression = expression.ToString();
            Stack <Token> stack            = new Stack <Token>();

            try
            {
                while (expression.Count > 0)
                {
                    Token token = expression.Dequeue();

                    if (token.IsOperator)
                    {
                        RaspyOperator      op       = (RaspyOperator)token;
                        IOperationProvider provider = this.providerFactory.GetProvider(op.Symbol);

                        if (provider != null)
                        {
                            List <Token> args = new List <Token>();
                            int          i    = op.ArgumentCount;

                            while (i-- > 0)
                            {
                                args.Add(stack.Pop());
                            }

                            args.Reverse();
                            stack.Push(provider.Operate(op, args.ToArray()));
                        }
                        else
                        {
                            throw new RaspyEvaluationException(
                                      string.Format(CultureInfo.InvariantCulture, "No provider could be found for operator '{0}'.", op.Symbol),
                                      infixExpression,
                                      parsedExpression);
                        }
                    }
                    else
                    {
                        stack.Push(token);
                    }
                }

                if (stack.Count != 1 || !stack.Peek().IsOperand)
                {
                    throw new RaspyEvaluationException(
                              string.Format(CultureInfo.InvariantCulture, "Invalid expression: '{0}'.", parsedExpression),
                              infixExpression,
                              parsedExpression);
                }

                return(((Operand)stack.Pop()).Value);
            }
            catch (RaspyException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new RaspyEvaluationException(
                          string.Format(CultureInfo.InvariantCulture, "An error occurred while evaluating the expression '{0}'.", parsedExpression),
                          ex,
                          infixExpression,
                          parsedExpression);
            }
        }