public virtual void parse(string expression)
    {
        // Save the expression.
        bool parse = true;

        if (!expression.Equals(previousExpression))
        {
            previousExpression = expression;
        }
        else
        {
            parse         = false;
            operatorStack = (Stack)previousOperatorStack.Clone();
            operandStack  = (Stack)previousOperandStack.Clone();
        }

        try
        {
            if (parse)
            {
                operandStack  = new Stack();
                operatorStack = new Stack();


                bool     haveOperand   = false;
                bool     haveOperator  = false;
                Operator unaryOperator = null;


                int numChars = expression.Length;
                int charCtr  = 0;

                while (charCtr < numChars)
                {
                    Operator @operator     = null;
                    int      operatorIndex = -1;


                    if (EvaluationHelper.isSpace(expression[charCtr]))
                    {
                        charCtr++;
                        continue;
                    }


                    NextOperator nextOperator = getNextOperator(expression, charCtr, null);

                    if (nextOperator != null)
                    {
                        @operator     = nextOperator.Operator;
                        operatorIndex = nextOperator.Index;
                    }

                    if (operatorIndex > charCtr || operatorIndex == -1)
                    {
                        charCtr = processOperand(expression, charCtr, operatorIndex, operandStack, unaryOperator);

                        haveOperand   = true;
                        haveOperator  = false;
                        unaryOperator = null;
                    }

                    // Check if it is time to process an operator.
                    if (operatorIndex == charCtr)
                    {
                        if (nextOperator.Operator.Unary && (haveOperator || charCtr == 0))
                        {
                            charCtr = processUnaryOperator(operatorIndex, nextOperator.Operator);

                            if (unaryOperator == null)
                            {
                                // We have an unary operator.
                                unaryOperator = nextOperator.Operator;
                            }
                            else
                            {
                                throw new EvaluationException("Consecutive unary " + "operators are not allowed (index=" + charCtr + ").");
                            }
                        }
                        else
                        {
                            charCtr = processOperator(expression, operatorIndex, @operator, operatorStack, operandStack, haveOperand, unaryOperator);

                            unaryOperator = null;
                        }

                        if (!(nextOperator.Operator is ClosedParenthesesOperator))
                        {
                            haveOperand  = false;
                            haveOperator = true;
                        }
                    }
                }

                // Save the parsed operators and operands.
                previousOperatorStack = (Stack)operatorStack.Clone();
                previousOperandStack  = (Stack)operandStack.Clone();
            }
        }
        catch (Exception e)
        {
            // Clear the previous expression, because it is invalid.
            previousExpression = "";

            throw new EvaluationException(e.Message, e);
        }
    }