Exemplo n.º 1
0
/**
 * Visits the given ASTNode as a unary minus.  For this node only the
 * traversal is preorder.
 */
void
L3FormulaFormatter_visitUMinus ( const ASTNode_t *parent,
                                 const ASTNode_t *node,
                                 StringBuffer_t  *sb, 
                                 const L3ParserSettings_t *settings )
{
  //Unary minus is *not* the highest precedence, since it is superceded by 'power'
  unsigned int group;
  
  //If we are supposed to collapse minuses, do so.
  if (L3ParserSettings_getParseCollapseMinus(settings)) {
    if (ASTNode_getNumChildren(node) == 1 &&
        ASTNode_isUMinus(ASTNode_getLeftChild(node))) {
      L3FormulaFormatter_visit(parent, ASTNode_getLeftChild(ASTNode_getLeftChild(node)), sb, settings);
      return;
    }
  }
  
  group = L3FormulaFormatter_isGrouped(parent, node, settings);

  if (group)
  {
    StringBuffer_appendChar(sb, '(');
  }
  StringBuffer_appendChar(sb, '-');
  L3FormulaFormatter_visit ( node, ASTNode_getLeftChild(node), sb, settings);
  if (group)
  {
    StringBuffer_appendChar(sb, ')');
  }
}
Exemplo n.º 2
0
/**
 * Visits the given ASTNode, translating the piecewise function
 * to the much simpler 'x % y' format.
 */
void
L3FormulaFormatter_visitModulo ( const ASTNode_t *parent,
                                 const ASTNode_t *node,
                                 StringBuffer_t  *sb, 
                                 const L3ParserSettings_t *settings )
{
  unsigned int group       = L3FormulaFormatter_isGrouped(parent, node, settings);
  const ASTNode_t* subnode = ASTNode_getLeftChild(node);
  if (group)
  {
    StringBuffer_appendChar(sb, '(');
  }

  //Get x and y from the first child of the piecewise function, 
  // then the first child of that (times), and the first child
  // of that (minus).
  L3FormulaFormatter_visit ( subnode, ASTNode_getLeftChild(subnode), sb, settings);
  StringBuffer_appendChar(sb, ' ');
  StringBuffer_appendChar(sb, '%');
  StringBuffer_appendChar(sb, ' ');
  subnode = ASTNode_getRightChild(subnode);
  L3FormulaFormatter_visit ( node, ASTNode_getLeftChild(subnode), sb, settings);

  if (group)
  {
    StringBuffer_appendChar(sb, ')');
  }
}
Exemplo n.º 3
0
/**
 * @return true (non-zero) if the given child ASTNode should be grouped
 * (with parenthesis), false (0) otherwise.
 *
 * A node should be group if it is not an argument to a function and
 * either:
 *
 *   - The parent node has higher precedence than the child, or
 *
 *   - If parent node has equal precedence with the child and the child is
 *     to the right.  In this case, operator associativity and right-most
 *     AST derivation enforce the grouping.
 */
int
L3FormulaFormatter_isGrouped (const ASTNode_t *parent, const ASTNode_t *child, const L3ParserSettings_t *settings)
{
  int pp, cp;
  int pt, ct;
  int group = 0;
  int parentmodulo = 0;


  if (parent != NULL)
  {
    parentmodulo = isTranslatedModulo(parent);
    if (parentmodulo || !L3FormulaFormatter_isFunction(parent, settings))
    {
      group = 1;
      pp = getL3Precedence(parent);
      cp = getL3Precedence(child);

      if (pp < cp)
      {
        group = 0;
      }
      else if (pp == cp)
      {
        if (parentmodulo) {
          //Always group:  x * y % z -> (x * y) % z
          group = 1;
        }
        /**
         * Don't group only if i) child is the first on the list and ii) both parent and
         * child are the same type, or if they
         * should be associative operators (i.e. not AST_MINUS or
         * AST_DIVIDE).  That is, do not group a parent and left child
         * that are either both AST_PLUS or both AST_TIMES operators, nor the logical operators
         * that have the same precedence.
         */
        if (ASTNode_getLeftChild(parent) == child)
        {
          pt = ASTNode_getType(parent);
          ct = ASTNode_getType(child);
          if (ASTNode_isLogical(parent) || ASTNode_isRelational(parent)) {
            group = !(pt == ct);
          }
          else {
            group = !((pt == ct) || (pt == AST_PLUS || pt == AST_TIMES));
          }
        }
      }
      else if (pp==7 && cp==6) {
        //If the parent is 'power' and the child is 'unary not' or 'unary minus', we only need
        // to group if the child is the *left* child:  '(-x)^y', but 'x^-y'.
        if (!(ASTNode_getLeftChild(parent) == child)) { 
          group = 0;
        }
      }
    }
  }

  return group;
}
Exemplo n.º 4
0
/**
 * Visits the given ASTNode as a unary minus.  For this node only the
 * traversal is preorder.
 * Writes the function as a directed graph and appends the result
 * to the StringBuffer.
 */
void
FormulaGraphvizFormatter_visitUMinus (const ASTNode_t *parent,
                                      const ASTNode_t *node,
                                      StringBuffer_t  *sb )
{
  char *uniqueName = FormulaGraphvizFormatter_getUniqueName(node);
  char *name       = FormulaGraphvizFormatter_format(node);

  StringBuffer_append(sb, uniqueName);
  StringBuffer_append(sb, " [shape=box, label=");
  StringBuffer_append(sb, name);
  StringBuffer_append(sb, "];\n");

  if (parent != NULL) 
  {
    uniqueName = FormulaGraphvizFormatter_getUniqueName(parent);
    name       = FormulaGraphvizFormatter_getUniqueName(node);

    if(strcmp(name, uniqueName)) 
    {
      StringBuffer_append(sb, uniqueName);
      StringBuffer_append(sb, " -> ");
      StringBuffer_append(sb, name);
      StringBuffer_append(sb, ";\n");
    }
  }
  
  FormulaGraphvizFormatter_visit ( node, ASTNode_getLeftChild(node), sb );
}
END_TEST


START_TEST (test_SBML_parseFormula_15)
{
  ASTNode_t *r = SBML_parseFormula("foo(1, bar)");
  ASTNode_t *c;


  fail_unless( ASTNode_getType(r) == AST_FUNCTION , NULL );
  fail_unless( !strcmp(ASTNode_getName(r), "foo") , NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2     , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "bar") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_6)
{
  ASTNode_t *r = SBML_parseFormula("1 + 2");
  ASTNode_t *c;



  fail_unless( ASTNode_getType       (r) == AST_PLUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '+', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 2, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
Exemplo n.º 7
0
/**
 * Visits the given ASTNode as a unary minus.  For this node only the
 * traversal is preorder.
 */
void
FormulaFormatter_visitUMinus ( const ASTNode_t *parent,
                               const ASTNode_t *node,
                               StringBuffer_t  *sb )
{
  StringBuffer_appendChar(sb, '-');
  FormulaFormatter_visit ( node, ASTNode_getLeftChild(node), sb );
}
END_TEST


START_TEST (test_SBML_parseFormula_11)
{
  ASTNode_t *r = SBML_parseFormula("1 - -foo / 3");
  ASTNode_t *c;



  fail_unless( ASTNode_getType       (r) == AST_MINUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '-', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_DIVIDE, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '/', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2, NULL );

  c = ASTNode_getLeftChild( ASTNode_getRightChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_MINUS, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '-', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 1  , NULL );

  c = ASTNode_getLeftChild( ASTNode_getLeftChild( ASTNode_getRightChild(r) ) );

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "foo") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  c = ASTNode_getRightChild( ASTNode_getRightChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 3, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
Exemplo n.º 9
0
END_TEST


START_TEST (test_SBML_parseFormula_10)
{
  ASTNode_t *r = SBML_parseFormula("1 + -2e100 / 3");
  ASTNode_t *c;


  fail_unless( ASTNode_getType       (r) == AST_PLUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '+', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_DIVIDE, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '/', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2  , NULL );

  c = ASTNode_getLeftChild(c);

  fail_unless( ASTNode_getType       (c) == AST_REAL_E, NULL );
  fail_unless( ASTNode_getMantissa   (c) ==  -2, NULL );
  fail_unless( ASTNode_getExponent   (c) == 100, NULL );
  fail_unless( ASTNode_getReal       (c) == -2e+100, NULL );
  fail_unless( ASTNode_getNumChildren(c) ==   0, NULL );

  c = ASTNode_getRightChild( ASTNode_getRightChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 3, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_8)
{
  ASTNode_t *r = SBML_parseFormula("(1 - 2) * 3");
  ASTNode_t *c;


  fail_unless( ASTNode_getType       (r) == AST_TIMES, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '*', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_MINUS, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '-', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2, NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 3, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getLeftChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 1, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger   (c)  == 2, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  ASTNode_free(r);
}
END_TEST


START_TEST (test_SBML_parseFormula_12)
{
  ASTNode_t *r = SBML_parseFormula("2 * foo^bar + 3.0");
  ASTNode_t *c;


  fail_unless( ASTNode_getType       (r) == AST_PLUS, NULL );
  fail_unless( ASTNode_getCharacter  (r) == '+', NULL );
  fail_unless( ASTNode_getNumChildren(r) == 2  , NULL );

  c = ASTNode_getLeftChild(r);

  fail_unless( ASTNode_getType       (c) == AST_TIMES, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '*', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2  , NULL );

  c = ASTNode_getRightChild(r);

  fail_unless( ASTNode_getType       (c) == AST_REAL, NULL );
  fail_unless( ASTNode_getReal       (c) == 3.0, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0  , NULL );

  c = ASTNode_getLeftChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_INTEGER, NULL );
  fail_unless( ASTNode_getInteger    (c) == 2, NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0, NULL );

  c = ASTNode_getRightChild( ASTNode_getLeftChild(r) );

  fail_unless( ASTNode_getType       (c) == AST_POWER, NULL );
  fail_unless( ASTNode_getCharacter  (c) == '^', NULL );
  fail_unless( ASTNode_getNumChildren(c) == 2  , NULL );

  c = ASTNode_getLeftChild( ASTNode_getRightChild( ASTNode_getLeftChild(r) ) );

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "foo") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  c = ASTNode_getRightChild( ASTNode_getRightChild( ASTNode_getLeftChild(r) ) );

  fail_unless( ASTNode_getType(c) == AST_NAME     , NULL );
  fail_unless( !strcmp(ASTNode_getName(c), "bar") , NULL );
  fail_unless( ASTNode_getNumChildren(c) == 0     , NULL );

  ASTNode_free(r);
}
Exemplo n.º 12
0
/**
 * Visits the given ASTNode as a unary not.
 */
void
L3FormulaFormatter_visitUNot ( const ASTNode_t *parent,
                               const ASTNode_t *node,
                               StringBuffer_t  *sb, 
                               const L3ParserSettings_t *settings )
{
  //Unary not is also not the highest precedence, since it is superceded by 'power'
  unsigned int group       = L3FormulaFormatter_isGrouped(parent, node, settings);

  if (group)
  {
    StringBuffer_appendChar(sb, '(');
  }
  StringBuffer_appendChar(sb, '!');
  L3FormulaFormatter_visit ( node, ASTNode_getLeftChild(node), sb, settings);
  if (group)
  {
    StringBuffer_appendChar(sb, ')');
  }
}
Exemplo n.º 13
0
/**
 * Visits the given ASTNode and continues the inorder traversal.
 * Writes the function as a directed graph and appends the result
 * to the StringBuffer.
 */
void
FormulaGraphvizFormatter_visitOther (const ASTNode_t *parent,
                                     const ASTNode_t *node,
                                     StringBuffer_t  *sb )
{
  unsigned int numChildren = ASTNode_getNumChildren(node);
  char         *name;
  char         *uniqueName;

  if (numChildren > 0)
  {
    uniqueName = FormulaGraphvizFormatter_getUniqueName(node);
    name       = FormulaGraphvizFormatter_format(node);
    
    StringBuffer_append(sb, uniqueName);
    StringBuffer_append(sb, " [shape=box, label=");
    StringBuffer_append(sb, name);
    StringBuffer_append(sb, "];\n");
    
    FormulaGraphvizFormatter_visit( node, ASTNode_getLeftChild(node), sb );
  }

  if (parent != NULL) 
  {
    name       = FormulaGraphvizFormatter_getUniqueName(node);
    uniqueName = FormulaGraphvizFormatter_getUniqueName(parent);
    
    if(strcmp(name, uniqueName)) 
    {
      StringBuffer_append(sb, uniqueName);
      StringBuffer_append(sb, " -> ");
      StringBuffer_append(sb, name);
      StringBuffer_append(sb, ";\n");
    }
  }

  if (numChildren > 1)
  {
    FormulaGraphvizFormatter_visit( node, ASTNode_getRightChild(node), sb );
  }
}
Exemplo n.º 14
0
void
printFunctionDefinition (unsigned int n, const FunctionDefinition_t *fd)
{
  const ASTNode_t *math;
  char *formula;


  if ( FunctionDefinition_isSetMath(fd) )
  {
    printf("FunctionDefinition %d, %s(", n, FunctionDefinition_getId(fd));

    math = FunctionDefinition_getMath(fd);

    /* Print function arguments. */
    if (ASTNode_getNumChildren(math) > 1)
    {
      printf("%s", ASTNode_getName( ASTNode_getLeftChild(math) ));

      for (n = 1; n < ASTNode_getNumChildren(math) - 1; ++n)
      {
        printf(", %s", ASTNode_getName( ASTNode_getChild(math, n) ));
      }
    }

    printf(") := ");

    /* Print function body. */
    if (ASTNode_getNumChildren(math) == 0)
    {
      printf("(no body defined)");
    }
    else
    {
      math    = ASTNode_getChild(math, ASTNode_getNumChildren(math) - 1);
      formula = SBML_formulaToString(math);
      printf("%s\n", formula);
      free(formula);
    }
  }
}
Exemplo n.º 15
0
void alg_alter_tree_structure(ASTNode_t **node_p, ASTNode_t *parent, int child_order) {
    ASTNode_t *node, *left, *right;
    ASTNode_t *times_node, *one_node;
    node = *node_p;
    if((left=ASTNode_getLeftChild(node)) != NULL) {
        alg_alter_tree_structure(&left, node, 0);
    }
    if((right=ASTNode_getRightChild(node)) != NULL) {
        alg_alter_tree_structure(&right, node, 1);
    }
    if(ASTNode_getType(node) == AST_NAME) {
        times_node = ASTNode_createWithType(AST_TIMES);
        one_node = ASTNode_createWithType(AST_INTEGER);
        ASTNode_setInteger(one_node, 1);
        ASTNode_addChild(times_node, one_node);
        ASTNode_addChild(times_node, node);
        if(parent != NULL) {
            ASTNode_replaceChild(parent, child_order, times_node);
        } else {
            *node_p = times_node;
        }
    }
    return;
}
Exemplo n.º 16
0
END_TEST


START_TEST (test_FormulaFormatter_isGrouped)
{
  ASTNode_t *p = ASTNode_create();
  ASTNode_t *c;


  /** Empty parent, p is the root of the tree. **/
  fail_unless( FormulaFormatter_isGrouped(NULL, p) == 0, NULL );
  ASTNode_free(p);


  /** "1 + 2 * 3" **/
  p = SBML_parseFormula("1 + 2 * 3");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  /** "(1 + 2) * 3" **/
  p = SBML_parseFormula("(1 + 2) * 3");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 1, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  /**
   * "1 + (2 * 3)":
   *
   * In this case, explicit grouping is not needed due to operator
   * precedence rules.
   */
  p = SBML_parseFormula("1 + (2 * 3)");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  /**
   * "foo(1 + 2, 2 * 3)":
   *
   * The parent node foo has higher precedence than its children, but
   * grouping is not nescessary since foo is a function.
   */
  p = SBML_parseFormula("foo(1 + 2, 2 * 3)");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  /**
   * "(a / b) * c":
   *
   * In this case, explicit grouping is not needed due to associativity
   * rules.
   */
  p = SBML_parseFormula("(a / b) * c");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  /**
   * "a / (b * c)":
   *
   * In this case, explicit grouping is needed.  The operators / and * have
   * the same precedence, but the parenthesis modifies the associativity.
   */
  p = SBML_parseFormula("a / (b * c)");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 1, NULL );

  ASTNode_free(p);


  /**
   * "a - (b - c)":
   *
   * Rainer Machne reported that the above parsed correctly, but was not
   * formatted correctly.
   *
   * The bug was in FormulaFormatter_isGrouped().  While it was correctly
   * handling parent and child ASTNodes of the same precedence, it was not
   * handling the special subcase where parent and child nodes were the
   * same operator.  For grouping, this only matters for the subtraction
   * and division operators, as they are not associative.
   * 
   * An exhaustive set of eight tests follow.
   */
  p = SBML_parseFormula("a - (b - c)");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 1, NULL );

  ASTNode_free(p);


  p = SBML_parseFormula("a - b - c");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  p = SBML_parseFormula("a + (b + c)");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  p = SBML_parseFormula("a + b + c");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  p = SBML_parseFormula("a * (b * c)");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  p = SBML_parseFormula("a * b * c");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);


  p = SBML_parseFormula("a / (b / c)");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 1, NULL );

  ASTNode_free(p);


  p = SBML_parseFormula("a / b / c");

  c = ASTNode_getLeftChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  c = ASTNode_getRightChild(p);
  fail_unless( FormulaFormatter_isGrouped(p, c) == 0, NULL );

  ASTNode_free(p);
}