Esempio n. 1
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);
        }
Esempio n. 2
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);
            }
        }