public ParseNode(Ptg token, ParseNode[] children) { _token = token; _children = children; _isIf = IsIf(token); int tokenCount = 1; for (int i = 0; i < children.Length; i++) { tokenCount += children[i].TokenCount; } if (_isIf) { // there will be 2 or 3 extra tAttr Tokens according To whether the false param is present tokenCount += children.Length; } _tokenCount = tokenCount; }
/** * Traverses the supplied formula parse tree, calling <c>Ptg.SetClass()</c> for each non-base * Token To Set its operand class. */ public void TransformFormula(ParseNode rootNode) { byte rootNodeOperandClass; switch (_formulaType) { case FormulaType.CELL: rootNodeOperandClass = Ptg.CLASS_VALUE; break; case FormulaType.ARRAY: rootNodeOperandClass = Ptg.CLASS_ARRAY; break; case FormulaType.NAMEDRANGE: case FormulaType.DATAVALIDATION_LIST: rootNodeOperandClass = Ptg.CLASS_REF; break; default: throw new Exception("Incomplete code - formula type (" + _formulaType + ") not supported yet"); } TransformNode(rootNode, rootNodeOperandClass, false); }
/** * @param callerForceArrayFlag <c>true</c> if one of the current node's parents is a * function Ptg which Has been Changed from default 'V' To 'A' type (due To requirements on * the function return value). */ private void TransformNode(ParseNode node, byte desiredOperandClass, bool callerForceArrayFlag) { Ptg token = node.GetToken(); ParseNode[] children = node.GetChildren(); bool IsSimpleValueFunc = IsSimpleValueFunction(token); if (IsSimpleValueFunc) { bool localForceArray = desiredOperandClass == Ptg.CLASS_ARRAY; for (int i = 0; i < children.Length; i++) { TransformNode(children[i], desiredOperandClass, localForceArray); } SetSimpleValueFuncClass((AbstractFunctionPtg)token, desiredOperandClass, callerForceArrayFlag); return; } if (IsSingleArgSum(token)) { // Need to process the argument of SUM with transformFunctionNode below // so make a dummy FuncVarPtg for that call. token = FuncVarPtg.SUM; // Note - the tAttrSum token (node.getToken()) is a base // token so does not need to have its operand class set } if (token is ValueOperatorPtg || token is ControlPtg || token is MemFuncPtg || token is MemAreaPtg || token is UnionPtg) { // Value Operator Ptgs and Control are base Tokens, so Token will be unchanged // but any child nodes are processed according To desiredOperandClass and callerForceArrayFlag // As per OOO documentation Sec 3.2.4 "Token Class Transformation", "Step 1" // All direct operands of value operators that are initially 'R' type will // be converted To 'V' type. byte localDesiredOperandClass = desiredOperandClass == Ptg.CLASS_REF ? Ptg.CLASS_VALUE : desiredOperandClass; for (int i = 0; i < children.Length; i++) { TransformNode(children[i], localDesiredOperandClass, callerForceArrayFlag); } return; } if (token is AbstractFunctionPtg) { TransformFunctionNode((AbstractFunctionPtg)token, children, desiredOperandClass, callerForceArrayFlag); return; } if (children.Length > 0) { //if (token == RangePtg.instance) if(token is OperationPtg) { // TODO is any Token transformation required under the various ref operators? return; } throw new InvalidOperationException("Node should not have any children"); } if (token.IsBaseToken) { // nothing To do return; } token.PtgClass = (TransformClass(token.PtgClass, desiredOperandClass, callerForceArrayFlag)); }
private void TransformFunctionNode(AbstractFunctionPtg afp, ParseNode[] children, byte desiredOperandClass, bool callerForceArrayFlag) { bool localForceArrayFlag; byte defaultReturnOperandClass = afp.DefaultOperandClass; if (callerForceArrayFlag) { switch (defaultReturnOperandClass) { case Ptg.CLASS_REF: if (desiredOperandClass == Ptg.CLASS_REF) { afp.PtgClass = (Ptg.CLASS_REF); } else { afp.PtgClass = (Ptg.CLASS_ARRAY); } localForceArrayFlag = false; break; case Ptg.CLASS_ARRAY: afp.PtgClass = (Ptg.CLASS_ARRAY); localForceArrayFlag = false; break; case Ptg.CLASS_VALUE: afp.PtgClass = (Ptg.CLASS_ARRAY); localForceArrayFlag = true; break; default: throw new InvalidOperationException("Unexpected operand class (" + defaultReturnOperandClass + ")"); } } else { if (defaultReturnOperandClass == desiredOperandClass) { localForceArrayFlag = false; // an alternative would have been To for non-base Ptgs To Set their operand class // from their default, but this would require the call in many subclasses because // the default OC is not known until the end of the constructor afp.PtgClass = (defaultReturnOperandClass); } else { switch (desiredOperandClass) { case Ptg.CLASS_VALUE: // always OK To Set functions To return 'value' afp.PtgClass = (Ptg.CLASS_VALUE); localForceArrayFlag = false; break; case Ptg.CLASS_ARRAY: switch (defaultReturnOperandClass) { case Ptg.CLASS_REF: afp.PtgClass = (Ptg.CLASS_REF); // afp.SetClass(Ptg.CLASS_ARRAY); break; case Ptg.CLASS_VALUE: afp.PtgClass = (Ptg.CLASS_ARRAY); break; default: throw new InvalidOperationException("Unexpected operand class (" + defaultReturnOperandClass + ")"); } localForceArrayFlag = (defaultReturnOperandClass == Ptg.CLASS_VALUE); break; case Ptg.CLASS_REF: switch (defaultReturnOperandClass) { case Ptg.CLASS_ARRAY: afp.PtgClass=(Ptg.CLASS_ARRAY); break; case Ptg.CLASS_VALUE: afp.PtgClass=(Ptg.CLASS_VALUE); break; default: throw new InvalidOperationException("Unexpected operand class (" + defaultReturnOperandClass + ")"); } localForceArrayFlag = false; break; default: throw new InvalidOperationException("Unexpected operand class (" + desiredOperandClass + ")"); } } } for (int i = 0; i < children.Length; i++) { ParseNode child = children[i]; byte paramOperandClass = afp.GetParameterClass(i); TransformNode(child, paramOperandClass, localForceArrayFlag); } }
/** * Collects the array of <c>Ptg</c> Tokens for the specified tree. */ public static Ptg[] ToTokenArray(ParseNode rootNode) { TokenCollector temp = new TokenCollector(rootNode.TokenCount); rootNode.CollectPtgs(temp); return temp.GetResult(); }
public ParseNode(Ptg token, ParseNode child0, ParseNode child1) : this(token, new ParseNode[] { child0, child1, }) { }