/** * 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; }
/** * 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; }
/** * 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); }