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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 4
0
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);
  }
}