/**
         * Adds operands to this item
         */
        public void add(ParseItem n)
        {
            n.setParent(this);

            // Grow the array
            ParseItem[] newOperands = new ParseItem[operands.Length + 1];
            System.Array.Copy(operands,0,newOperands,0,operands.Length);
            newOperands[operands.Length] = n;
            operands = newOperands;
        }
        /**
         * Handles a memory function
         */
        private void handleMemoryFunction(SubExpression subxp)
        {
            pos += subxp.read(tokenData,pos);

            // Create new tokenStack for the sub expression
            Stack<ParseItem> oldStack = tokenStack;
            tokenStack = new Stack<ParseItem>();

            parseSubExpression(subxp.getLength());

            ParseItem[] subexpr = new ParseItem[tokenStack.Count];
            int i = 0;
            while (tokenStack.Count > 0)
                {
                subexpr[i] = (ParseItem)tokenStack.Pop();
                i++;
                }

            subxp.setSubExpression(subexpr);

            tokenStack = oldStack;
            tokenStack.Push(subxp);
        }
        /**
         * Parses the sublist of tokens.  In most cases this will equate to
         * the full list
         *
         * @exception FormulaException
         */
        public void parse()
        {
            parseSubExpression(tokenData.Length);

            // Finally, there should be one thing left on the stack.  Get that
            // and add it to the root node
            root = (ParseItem)tokenStack.Pop();

            Assert.verify(tokenStack.Count == 0);
        }
        /**
         * Gets the operands for this operator from the stack
         *
         * @param s the token stack
         */
        public override void getOperands(Stack<ParseItem> s)
        {
            // parameters are in the correct order, god damn them
            ParseItem[] items = new ParseItem[function.getNumArgs()];
            // modified in 2.4.3
            for (int i = function.getNumArgs() - 1; i >= 0; i--)
                {
                ParseItem pi = s.Pop();
                items[i] = pi;
                }

            for (int i = 0; i < function.getNumArgs(); i++)
                add(items[i]);
        }
        /**
         * Gets the operands for this operator from the stack
         */
        public override void getOperands(Stack<ParseItem> s)
        {
            // parameters are in the correct order, god damn them
            ParseItem[] items = new ParseItem[arguments];

            for (int i = arguments - 1; i >= 0; i--)
                {
                ParseItem pi = s.Pop();
                items[i] = pi;
                }

            for (int i = 0; i < arguments; i++)
                add(items[i]);
        }
 /**
  * Parses the list of tokens
  *
  * @exception FormulaException
  */
 public void parse()
 {
     root = parseCurrent(getTokens().GetEnumerator());
 }
        /**
         * Handles the case when parsing a string when a token is a function
         *
         * @param sf the string function
         * @param i  the token iterator
         * @param stack the parse tree stack
         * @exception FormulaException if an error occurs
         */
        private void handleFunction(StringFunction sf,IEnumerator<ParseItem> i,Stack<ParseItem> stack)
        {
            ParseItem pi2 = parseCurrent(i);

            // If the function is unknown, then throw an error
            if (sf.getFunction(settings) == Function.UNKNOWN)
                throw new FormulaException(FormulaException.UNRECOGNIZED_FUNCTION);

            // First check for possible optimized functions and possible
            // use of the Attribute token
            if (sf.getFunction(settings) == Function.SUM && arguments == null)
                {
                // this is handled by an attribute
                Attribute a = new Attribute(sf,settings);
                a.add(pi2);
                stack.Push(a);
                return;
                }

            if (sf.getFunction(settings) == Function.IF)
                {
                // this is handled by an attribute
                Attribute a = new Attribute(sf,settings);

                // Add in the if conditions as a var arg function in
                // the correct order
                VariableArgFunction vaf = new VariableArgFunction(settings);
                object [] items = arguments.ToArray();
                for (int j = 0; j < items.Length; j++)
                    {
                    ParseItem pi3 = (ParseItem)items[j];
                    vaf.add(pi3);
                    }

                a.setIfConditions(vaf);
                stack.Push(a);
                return;
                }

            int newNumArgs;

            // Function cannot be optimized.  See if it is a variable argument
            // function or not
            if (sf.getFunction(settings).getNumArgs() == 0xff)
                {

                // If the arg stack has not been initialized, it means
                // that there was only one argument, which is the
                // returned parse item
                if (arguments == null)
                    {
                    int numArgs = pi2 != null ? 1 : 0;
                    VariableArgFunction vaf = new VariableArgFunction(sf.getFunction(settings),numArgs,settings);

                    if (pi2 != null)
                        vaf.add(pi2);

                    stack.Push(vaf);
                    }
                else
                    {
                    // Add the args to the function in the correct order
                    newNumArgs = arguments.Count;
                    VariableArgFunction vaf = new VariableArgFunction(sf.getFunction(settings),newNumArgs,settings);

                    ParseItem[] args = new ParseItem[newNumArgs];
                    for (int j = 0; j < newNumArgs; j++)
                        {
                        ParseItem pi3 = (ParseItem)arguments.Pop();
                        args[newNumArgs - j - 1] = pi3;
                        }

                    for (int j = 0; j < args.Length; j++)
                        vaf.add(args[j]);
                    stack.Push(vaf);
                    arguments.Clear();
                    arguments = null;
                    }
                return;
                }

            // Function is a standard built in function
            BuiltInFunction bif = new BuiltInFunction(sf.getFunction(settings),settings);

            newNumArgs = sf.getFunction(settings).getNumArgs();
            if (newNumArgs == 1)
                {
                // only one item which is the returned ParseItem
                bif.add(pi2);
                }
            else
                {
                if ((arguments == null && newNumArgs != 0) ||
                    (arguments != null && newNumArgs != arguments.Count))
                    {
                    throw new FormulaException(FormulaException.INCORRECT_ARGUMENTS);
                    }
                // multiple arguments so go to the arguments stack.
                // Unlike the variable argument function, the args are
                // stored in reverse order
                object[] items = arguments.ToArray();
                for (int j = 0; j < newNumArgs; j++)
                    {
                    ParseItem pi3 = (ParseItem)items[j];
                    bif.add(pi3);
                    }
                }
            stack.Push(bif);
        }
 /**
  * Called by this class to initialize the parent
  */
 public void setParent(ParseItem p)
 {
     parent = p;
 }
        /**
         * Handles the case when parsing a string when a token is a function
         *
         * @param sf the string function
         * @param i  the token iterator
         * @param stack the parse tree stack
         * @exception FormulaException if an error occurs
         */
        private void handleFunction(StringFunction sf, IEnumerator <ParseItem> i, Stack <ParseItem> stack)
        {
            ParseItem pi2 = parseCurrent(i);

            // If the function is unknown, then throw an error
            if (sf.getFunction(settings) == Function.UNKNOWN)
            {
                throw new FormulaException(FormulaException.UNRECOGNIZED_FUNCTION);
            }

            // First check for possible optimized functions and possible
            // use of the Attribute token
            if (sf.getFunction(settings) == Function.SUM && arguments == null)
            {
                // this is handled by an attribute
                Attribute a = new Attribute(sf, settings);
                a.add(pi2);
                stack.Push(a);
                return;
            }

            if (sf.getFunction(settings) == Function.IF)
            {
                // this is handled by an attribute
                Attribute a = new Attribute(sf, settings);

                // Add in the if conditions as a var arg function in
                // the correct order
                VariableArgFunction vaf   = new VariableArgFunction(settings);
                object []           items = arguments.ToArray();
                for (int j = 0; j < items.Length; j++)
                {
                    ParseItem pi3 = (ParseItem)items[j];
                    vaf.add(pi3);
                }

                a.setIfConditions(vaf);
                stack.Push(a);
                return;
            }

            int newNumArgs;

            // Function cannot be optimized.  See if it is a variable argument
            // function or not
            if (sf.getFunction(settings).getNumArgs() == 0xff)
            {
                // If the arg stack has not been initialized, it means
                // that there was only one argument, which is the
                // returned parse item
                if (arguments == null)
                {
                    int numArgs             = pi2 != null ? 1 : 0;
                    VariableArgFunction vaf = new VariableArgFunction(sf.getFunction(settings), numArgs, settings);

                    if (pi2 != null)
                    {
                        vaf.add(pi2);
                    }

                    stack.Push(vaf);
                }
                else
                {
                    // Add the args to the function in the correct order
                    newNumArgs = arguments.Count;
                    VariableArgFunction vaf = new VariableArgFunction(sf.getFunction(settings), newNumArgs, settings);

                    ParseItem[] args = new ParseItem[newNumArgs];
                    for (int j = 0; j < newNumArgs; j++)
                    {
                        ParseItem pi3 = (ParseItem)arguments.Pop();
                        args[newNumArgs - j - 1] = pi3;
                    }

                    for (int j = 0; j < args.Length; j++)
                    {
                        vaf.add(args[j]);
                    }
                    stack.Push(vaf);
                    arguments.Clear();
                    arguments = null;
                }
                return;
            }

            // Function is a standard built in function
            BuiltInFunction bif = new BuiltInFunction(sf.getFunction(settings), settings);

            newNumArgs = sf.getFunction(settings).getNumArgs();
            if (newNumArgs == 1)
            {
                // only one item which is the returned ParseItem
                bif.add(pi2);
            }
            else
            {
                if ((arguments == null && newNumArgs != 0) ||
                    (arguments != null && newNumArgs != arguments.Count))
                {
                    throw new FormulaException(FormulaException.INCORRECT_ARGUMENTS);
                }
                // multiple arguments so go to the arguments stack.
                // Unlike the variable argument function, the args are
                // stored in reverse order
                object[] items = arguments.ToArray();
                for (int j = 0; j < newNumArgs; j++)
                {
                    ParseItem pi3 = (ParseItem)items[j];
                    bif.add(pi3);
                }
            }
            stack.Push(bif);
        }
        /**
         * Recursively parses the token array.  Recursion is used in order
         * to evaluate parentheses and function arguments
         *
         * @param iterator an iterator of tokens
         * @return the root node of the current parse stack
         * @exception FormulaException if an error occurs
         */
        private ParseItem parseCurrent(IEnumerator <ParseItem> iterator)
        {
            Stack <ParseItem> stack     = new Stack <ParseItem>();
            Stack <Operator>  operators = new Stack <Operator>();
            Stack <ParseItem> args      = null;       // we usually don't need this

            bool      parenthesesClosed = false;
            ParseItem lastParseItem     = null;

            while (!parenthesesClosed && iterator.MoveNext())
            {
                ParseItem pi = iterator.Current;
                if (pi == null)
                {
                    break;
                }

                pi.setParseContext(parseContext);

                if (pi is Operand)
                {
                    handleOperand((Operand)pi, stack);
                }
                else if (pi is StringFunction)
                {
                    handleFunction((StringFunction)pi, iterator, stack);
                }
                else if (pi is Operator)
                {
                    Operator op = (Operator)pi;

                    // See if the operator is a binary or unary operator
                    // It is a unary operator either if the stack is empty, or if
                    // the last thing off the stack was another operator
                    if (op is StringOperator)
                    {
                        StringOperator sop = (StringOperator)op;
                        if (stack.Count == 0 || lastParseItem is Operator)
                        {
                            op = sop.getUnaryOperator();
                        }
                        else
                        {
                            op = sop.getBinaryOperator();
                        }
                    }

                    if (operators.Count == 0)
                    {
                        // nothing much going on, so do nothing for the time being
                        operators.Push(op);
                    }
                    else
                    {
                        Operator op2 = operators.Peek();

                        // If the last  operator has a higher precedence then add this to
                        // the operator stack and wait
                        if (op2.getPrecedence() < op2.getPrecedence())
                        {
                            operators.Push(op2);
                        }
                        else if (op2.getPrecedence() == op2.getPrecedence() && op2 is UnaryOperator)
                        {
                            // The operators are of equal precedence, but because it is a
                            // unary operator the operand isn't available yet, so put it on
                            // the stack
                            operators.Push(op2);
                        }
                        else
                        {
                            // The operator is of a lower precedence so we can sort out
                            // some of the items on the stack
                            operators.Pop();                             // remove the operator from the stack
                            op2.getOperands(stack);
                            stack.Push(op2);
                            operators.Push(op2);
                        }
                    }
                }
                else if (pi is ArgumentSeparator)
                {
                    // Clean up any remaining items on this stack
                    while (operators.Count > 0)
                    {
                        Operator o = operators.Pop();
                        o.getOperands(stack);
                        stack.Push(o);
                    }

                    // Add it to the argument stack.  Create the argument stack
                    // if necessary.  Items will be stored on the argument stack in
                    // reverse order
                    if (args == null)
                    {
                        args = new Stack <ParseItem>();
                    }

                    args.Push(stack.Pop());
                    stack.Clear();
                }
                else if (pi is OpenParentheses)
                {
                    ParseItem   pi2 = parseCurrent(iterator);
                    Parenthesis p   = new Parenthesis();
                    pi2.setParent(p);
                    p.add(pi2);
                    stack.Push(p);
                }
                else if (pi is CloseParentheses)
                {
                    parenthesesClosed = true;
                }

                lastParseItem = pi;
            }

            while (operators.Count > 0)
            {
                Operator o = operators.Pop();
                o.getOperands(stack);
                stack.Push(o);
            }

            ParseItem rt = (stack.Count > 0) ? (ParseItem)stack.Pop() : null;

            // if the argument stack is not null, then add it to that stack
            // as well for good measure
            if (args != null && rt != null)
            {
                args.Push(rt);
            }

            arguments = args;

            if (stack.Count > 0 || operators.Count > 0)
            {
                //logger.warn("Formula " + formula + " has a non-empty parse stack");
            }

            return(rt);
        }
 /**
  * Parses the list of tokens
  *
  * @exception FormulaException
  */
 public void parse()
 {
     root = parseCurrent(getTokens().GetEnumerator());
 }
 public virtual void setSubExpression(ParseItem[] pi)
 {
     subExpression = pi;
 }