bool ASTPiecewiseFunctionNode::usingChildConstructors() const { bool usingChildConstructors = false; if (getNumChildren() != ASTFunctionBase::getNumChildren()) { // generally this will be true usingChildConstructors = true; } else { ASTBase * base = ASTFunctionBase::getChild(getNumChildren() - 1); if (base != NULL && (base->getType() == AST_CONSTRUCTOR_PIECE || base->getType() == AST_CONSTRUCTOR_OTHERWISE)) { usingChildConstructors = true; } } return usingChildConstructors; }
bool ArraysASTPlugin::hasUnambiguousPackageInfixGrammar(const ASTNode *child) const { ASTBase* function = const_cast<ASTBase*>(getParentASTObject()); if (function == NULL) return false; if (function->getType() != AST_ORIGINATES_IN_PACKAGE) return false; if (function->getPackageName() != "arrays") return false; // cast the function to an ASTNode ASTNode* newAST = dynamic_cast<ASTNode*>(function); if (newAST == NULL) { return false; } const ArraysASTPlugin* aap = static_cast<const ArraysASTPlugin*>(function->getPlugin("arrays")); switch(aap->getASTType()) { case AST_LINEAR_ALGEBRA_SELECTOR: if (newAST->getNumChildren() == 0) return true; if (newAST->getChild(0) == child) return false; //The *first* child of the selector needs parentheses in some situations! return true; //All other children are separated by commas, and thus don't need parentheses. case AST_LINEAR_ALGEBRA_VECTOR_CONSTRUCTOR: #if (0) case AST_LINEAR_ALGEBRA_MATRIX_CONSTRUCTOR: case AST_LINEAR_ALGEBRA_DETERMINANT: case AST_LINEAR_ALGEBRA_TRANSPOSE: case AST_LINEAR_ALGEBRA_VECTOR_PRODUCT: case AST_LINEAR_ALGEBRA_SCALAR_PRODUCT: case AST_LINEAR_ALGEBRA_OUTER_PRODUCT: case AST_LINEAR_ALGEBRA_MATRIXROW_CONSTRUCTOR: #endif case AST_QUALIFIER_CONDITION: case AST_LOGICAL_EXISTS: case AST_LOGICAL_FORALL: case AST_QUALIFIER_LOWLIMIT: case AST_STATISTICS_MEAN: case AST_STATISTICS_MEDIAN: case AST_STATISTICS_MODE: case AST_STATISTICS_MOMENT: case AST_QUALIFIER_MOMENTABOUT: case AST_SERIES_PRODUCT: case AST_STATISTICS_SDEV: case AST_SERIES_SUM: case AST_QUALIFIER_UPLIMIT: case AST_STATISTICS_VARIANCE: return true; //Everything is either a function or has unambiguous syntax. case AST_ARRAYS_UNKNOWN: return false; } return false; }
int ASTNaryFunctionNode::removeChild (unsigned int n) { int removed = LIBSBML_OPERATION_FAILED; if (this->getType() != AST_FUNCTION_ROOT) { removed = ASTFunctionBase::removeChild(n); } else { /* HACK TO REPLICATE OLD AST */ /* Hack to remove memory since the overall * remove does not remove memory * but the old api does not give access to the new * intermediate parents so these can never * be explicilty deleted by the user * * in this case the first remove is accessible */ if (ASTFunctionBase::getChild(n)->getType() == AST_QUALIFIER_DEGREE) { ASTBase * base = ASTFunctionBase::getChild(n); ASTNode * degree = dynamic_cast<ASTNode*>(base); if (degree != NULL && degree->getNumChildren() == 1) { removed = degree->removeChild(0); if (removed == LIBSBML_OPERATION_SUCCESS) { ASTBase * removedAST = NULL; removedAST = this->ASTFunctionBase::getChild(n); removed = ASTFunctionBase::removeChild(n); if (removedAST != NULL) delete removedAST; } } } else { removed = ASTFunctionBase::removeChild(n); } } /* HACK TO REPLICATE OLD AST */ // if we now have an odd number of children the last one // should be subject NOT the degree if (removed == LIBSBML_OPERATION_SUCCESS) { unsigned int size = getNumChildren(); unsigned int numChildren = ASTFunctionBase::getNumChildren(); if ((unsigned int)(size%2) == 1) { ASTBase * child = ASTFunctionBase::getChild(numChildren-1); if (child->getType() == AST_QUALIFIER_DEGREE) { ASTNode * degree = dynamic_cast<ASTNode *>(child); if (degree != NULL && degree->getNumChildren() == 1) { ASTNode *pChild = degree->getChild(0); degree->removeChild(0); ASTBase * temp = this->ASTFunctionBase::getChild(numChildren-1); this->ASTFunctionBase::removeChild(numChildren-1); delete temp; this->addChild(pChild); } } } } return removed; }
bool ArraysASTPlugin::isPackageInfixFunction() const { ASTBase* function = const_cast<ASTBase*>(getParentASTObject()); if (function == NULL) return false; if (function->getType() != AST_ORIGINATES_IN_PACKAGE) return false; if (function->getPackageName() != "arrays") return false; // cast the function to an ASTNode ASTNode* newAST = dynamic_cast<ASTNode*>(function); if (newAST == NULL) { return false; } unsigned int numChildren = newAST->getNumChildren(); unsigned int child = 0; const ArraysASTPlugin* aap = static_cast<const ArraysASTPlugin*>(newAST->getPlugin("arrays")); switch(aap->getASTType()) { case AST_LINEAR_ALGEBRA_SELECTOR: case AST_LINEAR_ALGEBRA_VECTOR_CONSTRUCTOR: return false; #if (0) case AST_LINEAR_ALGEBRA_MATRIX_CONSTRUCTOR: //An empty matrix or a matrix with only one row looks like a vector, so we have to use the functional form if (numChildren<=1) return true; //Also, none of the rows may be empty for the { ... ; ... } to be parseable: for (child=0; child<numChildren; child++) { if(newAST->getChild(child)->getNumChildren() == 0) { return true; } } return false; case AST_LINEAR_ALGEBRA_DETERMINANT: case AST_LINEAR_ALGEBRA_TRANSPOSE: case AST_LINEAR_ALGEBRA_VECTOR_PRODUCT: case AST_LINEAR_ALGEBRA_SCALAR_PRODUCT: case AST_LINEAR_ALGEBRA_OUTER_PRODUCT: case AST_LINEAR_ALGEBRA_MATRIXROW_CONSTRUCTOR: return true; #endif case AST_LOGICAL_EXISTS: case AST_LOGICAL_FORALL: case AST_STATISTICS_MEAN: case AST_STATISTICS_MEDIAN: case AST_STATISTICS_MODE: case AST_STATISTICS_MOMENT: case AST_SERIES_PRODUCT: case AST_STATISTICS_SDEV: case AST_SERIES_SUM: case AST_STATISTICS_VARIANCE: case AST_ARRAYS_UNKNOWN: return true; case AST_QUALIFIER_CONDITION: case AST_QUALIFIER_LOWLIMIT: case AST_QUALIFIER_MOMENTABOUT: case AST_QUALIFIER_UPLIMIT: return false; } return false; }
int ASTPiecewiseFunctionNode::insertChildForReplace(unsigned int n, ASTBase* newChild) { int inserted = LIBSBML_INDEX_EXCEEDS_SIZE; unsigned int numChildren = ASTFunctionBase::getNumChildren(); unsigned int numChildrenForUser = getNumChildren(); // determine index that we actually want unsigned int childNo = (unsigned int)(n/2); unsigned int pieceIndex = (unsigned int)(n%2); if (numChildren == numChildrenForUser) { // we have an old style piecewise function childNo = n; pieceIndex = n; } ASTBase * base = NULL; if (childNo < numChildren) { base = ASTFunctionBase::getChild(childNo); } if (getHasOtherwise() == true && childNo == numChildren - 1) { if (base == NULL) { return inserted; } if (base->getType() == AST_CONSTRUCTOR_OTHERWISE) { ASTNode * otherwise = dynamic_cast<ASTNode*>(base); if (otherwise != NULL) { inserted = otherwise->replaceChild(0, static_cast<ASTNode*>(newChild)); } else { return inserted; } } else { inserted = ASTFunctionBase::replaceChild(childNo, newChild); } } else if (base != NULL && base->getType() == AST_CONSTRUCTOR_PIECE) { ASTNode * piece = dynamic_cast<ASTNode*>(base); if (piece != NULL) { if (piece->getNumChildren() > pieceIndex) { inserted = piece->replaceChild(pieceIndex, static_cast<ASTNode*>(newChild)); } else { return inserted; } } else { return inserted; } } else if (n < numChildren) { return ASTFunctionBase::replaceChild(n, newChild); } else { return inserted; } return inserted; //unsigned int numChildren = ASTFunctionBase::getNumChildren(); //vector < ASTBase *> copyChildren; //unsigned int i; //for (i = n; i < numChildren; i++) //{ // ASTBase * child = getChild(i); // // this might be NULL if we have deleted part of the piece function // if (child != NULL) // { // copyChildren.push_back(getChild(i)); // } //} //for (i = numChildren; i > n; i--) //{ // ASTFunctionBase::removeChild(i-1); //} //unsigned int success = addChild(newChild); //i = 0; //while (success == LIBSBML_OPERATION_SUCCESS && i < copyChildren.size()) //{ // success = addChild(copyChildren.at(i)); // i++; //} //inserted = success; //return inserted; }
ASTBase* ASTPiecewiseFunctionNode::getChild (unsigned int n) const { /* HACK TO REPLICATE OLD AST */ /* do not return a node with teh piece or otherwise type * return the correct child of the piece type * or the child of the otherwise */ unsigned int numChildren = ASTFunctionBase::getNumChildren(); if (numChildren == 0) { return NULL; } // determine index that we actually want unsigned int childNo = (unsigned int)(n/2); unsigned int pieceIndex = (unsigned int)(n%2); ASTBase * base = NULL; if (childNo < numChildren) { base = ASTFunctionBase::getChild(childNo); } if (getHasOtherwise() == true && childNo == numChildren - 1) { if (base == NULL) { return NULL; } if (base->getType() == AST_CONSTRUCTOR_OTHERWISE) { ASTNode * otherwise = dynamic_cast<ASTNode*>(base); if (otherwise != NULL) { if (otherwise->getNumChildren() > 0) { return otherwise->getChild(0); } else { return NULL; } } else { return NULL; } } else { return base; } } else if (base != NULL && base->getType() == AST_CONSTRUCTOR_PIECE) { ASTNode * piece = dynamic_cast<ASTNode*>(base); if (piece != NULL) { if (piece->getNumChildren() > pieceIndex) { return piece->getChild(pieceIndex); } else { return NULL; } } else { return NULL; } } else if (n < numChildren) { return ASTFunctionBase::getChild(n); } else { return NULL; } }
int ASTPiecewiseFunctionNode::addChild(ASTBase* child, bool inRead) { // now here what I want to do is just keep track of the number // of children being added so the mNumPiece and mHasOtherwise // variables can be given appropriate values // but not if we are reading a stream because then we already know if (inRead == false) { if (child->getType() != AST_CONSTRUCTOR_PIECE && child->getType() != AST_CONSTRUCTOR_OTHERWISE) { // this child does not have a piece/otherwise but if // the rest of the function does then it needs to fit in with that unsigned int currentNum = getNumChildren(); if (usingChildConstructors() == false) { if ((currentNum+1)%2 == 0) { setNumPiece(getNumPiece()+1); setHasOtherwise(false); } else { setHasOtherwise(true); } return ASTFunctionBase::addChild(child); } else { ASTBase * lastChild = ASTFunctionBase::getChild(ASTFunctionBase::getNumChildren()-1); if (lastChild == NULL) { // we have a serious issue going on but may as well just // add the child return ASTFunctionBase::addChild(child); } else if (lastChild->getType() == AST_CONSTRUCTOR_PIECE) { ASTNode * piece = dynamic_cast<ASTNode*>(lastChild); if (piece == NULL) { return LIBSBML_OPERATION_FAILED; } if (piece->getNumChildren() == 1) { return piece->addChild((ASTNode*)(child)); } else { ASTNode * otherwise = new ASTNode(AST_CONSTRUCTOR_OTHERWISE); if (otherwise->addChild((ASTNode*)(child)) == LIBSBML_OPERATION_SUCCESS) { setHasOtherwise(true); return ASTFunctionBase::addChild(otherwise); } else { return LIBSBML_OPERATION_FAILED; } } } else { ASTNode * otherwise = dynamic_cast<ASTNode*>(lastChild); if (otherwise == NULL || otherwise->getNumChildren() != 1) { return LIBSBML_OPERATION_FAILED; } ASTNode * piece = new ASTNode(AST_CONSTRUCTOR_PIECE); // add teh child from teh otherwise if (piece->addChild(otherwise->getChild(0)) != LIBSBML_OPERATION_SUCCESS) { return LIBSBML_OPERATION_FAILED; } else { if (piece->addChild((ASTNode*)(child)) == LIBSBML_OPERATION_SUCCESS) { this->removeChild(currentNum-1); setHasOtherwise(false); setNumPiece(getNumPiece() + 1); return ASTFunctionBase::addChild(piece); } else { return LIBSBML_OPERATION_FAILED; } } } } } else { if (child->getType() == AST_CONSTRUCTOR_PIECE) { setNumPiece(getNumPiece()+1); } else { setHasOtherwise(true); } return ASTFunctionBase::addChild(child); } } else { return ASTFunctionBase::addChild(child); } }