/**
 * 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, ')');
  }
}
/**
 * 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, ')');
  }
}
/**
 * Visits the given ASTNode and continues the inorder traversal.
 */
void
L3FormulaFormatter_visitOther ( const ASTNode_t *parent,
                                const ASTNode_t *node,
                                StringBuffer_t  *sb, 
                                const L3ParserSettings_t *settings )
{
  unsigned int numChildren = ASTNode_getNumChildren(node);
  unsigned int group       = L3FormulaFormatter_isGrouped(parent, node, settings);
  unsigned int n;


  if (group)
  {
    StringBuffer_appendChar(sb, '(');
  }

  if (numChildren == 0) {
    L3FormulaFormatter_format(sb, node, settings);
  }

  else if (numChildren == 1)
  {
    //I believe this would only be called for invalid ASTNode setups,
    // but this could in theory occur.  This is the safest 
    // behavior I can think of.
    L3FormulaFormatter_format(sb, node, settings);
    StringBuffer_appendChar(sb, '(');
    L3FormulaFormatter_visit( node, ASTNode_getChild(node, 0), sb, settings);
    StringBuffer_appendChar(sb, ')');
  }

  else {
    L3FormulaFormatter_visit( node, ASTNode_getChild(node, 0), sb, settings);

    for (n = 1; n < numChildren; n++)
    {
      L3FormulaFormatter_format(sb, node, settings);
      L3FormulaFormatter_visit( node, ASTNode_getChild(node, n), sb, settings);
    }
  }

  if (group)
  {
    StringBuffer_appendChar(sb, ')');
  }
}
/**
 * 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, ')');
  }
}
示例#5
0
END_TEST

START_TEST (test_L3FormulaFormatter_accessWithNULL)
{

  // ensure we survive NULL arguments
  L3FormulaFormatter_format(NULL, NULL, NULL);
  L3FormulaFormatter_formatFunction(NULL, NULL, NULL);
  L3FormulaFormatter_formatOperator(NULL, NULL);
  L3FormulaFormatter_visit(NULL, NULL, NULL, NULL);
  L3FormulaFormatter_visitFunction(NULL, NULL, NULL, NULL);
  L3FormulaFormatter_visitLog10(NULL, NULL, NULL, NULL);
  L3FormulaFormatter_visitOther(NULL, NULL, NULL, NULL);
  L3FormulaFormatter_visitSqrt(NULL, NULL, NULL, NULL);
  L3FormulaFormatter_visitUMinus(NULL, NULL, NULL, NULL);

  fail_unless( L3FormulaFormatter_isFunction(NULL, NULL) == 0 );
  fail_unless( L3FormulaFormatter_isGrouped(NULL, NULL, NULL) == 0 );
  fail_unless( SBML_formulaToL3String(NULL) == NULL );
  
}
示例#6
0
END_TEST


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


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


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

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);


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

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

  c = ASTNode_getRightChild(p);
  fail_unless( L3FormulaFormatter_isGrouped(p, c, NULL) == 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_parseL3Formula("foo(1 + 2, 2 * 3)");

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

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

  ASTNode_free(p);


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

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

  c = ASTNode_getRightChild(p);
  fail_unless( L3FormulaFormatter_isGrouped(p, c, NULL) == 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_parseL3Formula("a / (b * c)");

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

  c = ASTNode_getRightChild(p);
  fail_unless( L3FormulaFormatter_isGrouped(p, c, NULL) == 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 L3FormulaFormatter_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_parseL3Formula("a - (b - c)");

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);


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

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

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

  ASTNode_free(p);
}