private NextOperator getNextOperator(string expression, int start, Operator match)
    {
        int numChars           = expression.Length;
        int numQuoteCharacters = 0;

        for (int charCtr = start; charCtr < numChars; charCtr++)
        {
            // Keep track of open strings.
            if (expression[charCtr] == quoteCharacter)
            {
                numQuoteCharacters++;
            }

            // Do not look into open strings.
            if ((numQuoteCharacters % 2) == 1)
            {
                continue;
            }

            int numOperators = operators.Count;
            for (int operatorCtr = 0; operatorCtr < numOperators; operatorCtr++)
            {
                Operator @operator = (Operator)operators[operatorCtr];

                if (match != null)
                {
                    // Look through the operators until we find the
                    // one we are searching for.
                    if (!match.Equals(@operator))
                    {
                        continue;
                    }
                }

                // The operator can 1 or 2 characters in length.
                if (@operator.Length == 2)
                {
                    int endCtr = -1;
                    if (charCtr + 2 <= expression.Length)
                    {
                        endCtr = charCtr + 2;
                    }
                    else
                    {
                        endCtr = expression.Length;
                    }

                    // Look for a match.
                    if (expression.Substring(charCtr, endCtr - charCtr).Equals(@operator.Symbol))
                    {
                        NextOperator nextOperator = new NextOperator(@operator, charCtr);

                        return(nextOperator);
                    }
                }
                else
                {
                    // Look for a match.
                    if (expression[charCtr] == @operator.Symbol[0])
                    {
                        NextOperator nextOperator = new NextOperator(@operator, charCtr);

                        return(nextOperator);
                    }
                }
            }
        }

        return(null);
    }
    private int processOperator(string expression, int originalOperatorIndex, Operator originalOperator, Stack operatorStack, Stack operandStack, bool haveOperand, Operator unaryOperator)
    {
        int      operatorIndex = originalOperatorIndex;
        Operator @operator     = originalOperator;


        if (haveOperand && @operator is OpenParenthesesOperator)
        {
            NextOperator nextOperator = processFunction(expression, operatorIndex, operandStack);

            @operator     = nextOperator.Operator;
            operatorIndex = nextOperator.Index + @operator.Length;

            nextOperator = getNextOperator(expression, operatorIndex, null);

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


        if (@operator is OpenParenthesesOperator)
        {
            ExpressionOperator expressionOperator = new ExpressionOperator(@operator, unaryOperator);
            operatorStack.Push(expressionOperator);
        }
        else if (@operator is ClosedParenthesesOperator)
        {
            ExpressionOperator stackOperator = null;

            if (operatorStack.Count > 0)
            {
                stackOperator = (ExpressionOperator)operatorStack.Peek();
            }

            // Process until we reach an open parentheses.
            while (stackOperator != null && !(stackOperator.Operator is OpenParenthesesOperator))
            {
                processTree(operandStack, operatorStack);

                if (operatorStack.Count > 0)
                {
                    stackOperator = (ExpressionOperator)operatorStack.Peek();
                }
                else
                {
                    stackOperator = null;
                }
            }

            if (operatorStack.Count == 0)
            {
                throw new EvaluationException("Expression is invalid.");
            }

            ExpressionOperator expressionOperator = (ExpressionOperator)operatorStack.Pop();

            if (!(expressionOperator.Operator is OpenParenthesesOperator))
            {
                throw new EvaluationException("Expression is invalid.");
            }

            // Process the unary operator if we have one.
            if (expressionOperator.UnaryOperator != null)
            {
                object operand = operandStack.Pop();

                ExpressionTree tree = new ExpressionTree(this, operand, null, null, expressionOperator.UnaryOperator);

                operandStack.Push(tree);
            }
        }
        else
        {
            // Process non-param operator.
            if (operatorStack.Count > 0)
            {
                ExpressionOperator stackOperator = (ExpressionOperator)operatorStack.Peek();

                while (stackOperator != null && stackOperator.Operator.Precedence >= @operator.Precedence)
                {
                    processTree(operandStack, operatorStack);

                    if (operatorStack.Count > 0)
                    {
                        stackOperator = (ExpressionOperator)operatorStack.Peek();
                    }
                    else
                    {
                        stackOperator = null;
                    }
                }
            }

            ExpressionOperator expressionOperator = new ExpressionOperator(@operator, unaryOperator);

            operatorStack.Push(expressionOperator);
        }


        int rtnCtr = operatorIndex + @operator.Length;

        return(rtnCtr);
    }
    private NextOperator processFunction(string expression, int operatorIndex, Stack operandStack)
    {
        int          parenthesisCount  = 1;
        NextOperator nextOperator      = null;
        int          nextOperatorIndex = operatorIndex;

        // Loop until we find the function's closing parentheses.
        while (parenthesisCount > 0)
        {
            nextOperator = getNextOperator(expression, nextOperatorIndex + 1, null);

            if (nextOperator == null)
            {
                throw new EvaluationException("Function is not closed.");
            }
            else if (nextOperator.Operator is OpenParenthesesOperator)
            {
                parenthesisCount++;
            }
            else if (nextOperator.Operator is ClosedParenthesesOperator)
            {
                parenthesisCount--;
            }

            // Get the next operator index.
            nextOperatorIndex = nextOperator.Index;
        }


        string arguments = expression.Substring(operatorIndex + 1, nextOperatorIndex - (operatorIndex + 1));

        // Pop the function name from the stack.
        ExpressionOperand operand       = (ExpressionOperand)operandStack.Pop();
        Operator          unaryOperator = operand.UnaryOperator;
        string            functionName  = operand.Value;

        // Validate that the function name is valid.
        try
        {
            isValidName(functionName);
        }
        catch (System.ArgumentException iae)
        {
            throw new EvaluationException("Invalid function name of \"" + functionName + "\".", iae);
        }

        // Get the function object.
        //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
        //ORIGINAL LINE: final net.sourceforge.jeval.function.Function function = (net.sourceforge.jeval.function.Function) functions.get(functionName);
        Function function = (Function)functions[functionName];

        if (function == null)
        {
            throw new EvaluationException("A function is not defined (index=" + operatorIndex + ").");
        }


        ParsedFunction parsedFunction = new ParsedFunction(function, arguments, unaryOperator);

        operandStack.Push(parsedFunction);

        return(nextOperator);
    }
    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);
        }
    }