/** * @return <code>false</code> if sub-expression represented the specified ParseNode definitely * cannot appear on either side of the range (':') operator */ private static boolean isValidRangeOperand(ParseNode a) { Ptg tkn = a.getToken(); // Note - order is important for these instance-of checks if (tkn instanceof OperandPtg) { // notably cell refs and area refs return true; } // next 2 are special cases of OperationPtg if (tkn instanceof AbstractFunctionPtg) { AbstractFunctionPtg afp = (AbstractFunctionPtg) tkn; byte returnClass = afp.getDefaultOperandClass(); return Ptg.CLASS_REF == returnClass; } if (tkn instanceof ValueOperatorPtg) { return false; } if (tkn instanceof OperationPtg) { return true; } // one special case of ControlPtg if (tkn instanceof ParenthesisPtg) { // parenthesis Ptg should have only one child return isValidRangeOperand(a.getChildren()[0]); } // one special case of ScalarConstantPtg if (tkn == ErrPtg.REF_INVALID) { return true; } // All other ControlPtgs and ScalarConstantPtgs cannot be used with ':' return false; }
/** * From OOO doc: "Whenever one operand of the reference subexpression is a function, a defined * name, a 3D reference, or an external reference (and no error occurs), a tMemFunc token is used" */ private static boolean needsMemFunc(ParseNode root) { Ptg token = root.getToken(); if (token instanceof AbstractFunctionPtg) { return true; } if (token instanceof ExternSheetReferenceToken) { // 3D refs return true; } if (token instanceof NamePtg || token instanceof NameXPtg) { // 3D refs return true; } if (token instanceof OperationPtg || token instanceof ParenthesisPtg) { // expect RangePtg, but perhaps also UnionPtg, IntersectionPtg etc for (ParseNode child : root.getChildren()) { if (needsMemFunc(child)) { return true; } } return false; } if (token instanceof OperandPtg) { return false; } if (token instanceof OperationPtg) { return true; } return false; }
private ParseNode parseUnary(boolean isPlus) { boolean numberFollows = IsDigit(look) || look == '.'; ParseNode factor = powerFactor(); if (numberFollows) { // + or - directly next to a number is parsed with the number Ptg token = factor.getToken(); if (token instanceof NumberPtg) { if (isPlus) { return factor; } token = new NumberPtg(-((NumberPtg) token).getValue()); return new ParseNode(token); } if (token instanceof IntPtg) { if (isPlus) { return factor; } int intVal = ((IntPtg) token).getValue(); // note - cannot use IntPtg for negatives token = new NumberPtg(-intVal); return new ParseNode(token); } } return new ParseNode(isPlus ? UnaryPlusPtg.instance : UnaryMinusPtg.instance, factor); }
private static ParseNode augmentWithMemPtg(ParseNode root) { Ptg memPtg; if (needsMemFunc(root)) { memPtg = new MemFuncPtg(root.getEncodedSize()); } else { memPtg = new MemAreaPtg(root.getEncodedSize()); } return new ParseNode(memPtg, root); }
private Ptg[] getRPNPtg(int formulaType) { OperandClassTransformer oct = new OperandClassTransformer(formulaType); // RVA is for 'operand class': 'reference', 'value', 'array' oct.transformFormula(_rootNode); return ParseNode.toTokenArray(_rootNode); }