/** * 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); }
public virtual void setSubExpression(ParseItem[] pi) { subExpression = pi; }