/** * 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, 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 function. For this node only the * traversal is preorder. */ void L3FormulaFormatter_visitFunction ( const ASTNode_t *parent, const ASTNode_t *node, StringBuffer_t *sb, const L3ParserSettings_t *settings ) { unsigned int numChildren = ASTNode_getNumChildren(node); unsigned int n; L3FormulaFormatter_format(sb, node, settings); StringBuffer_appendChar(sb, '('); if (numChildren > 0) { L3FormulaFormatter_visit( node, ASTNode_getChild(node, 0), sb, settings); } for (n = 1; n < numChildren; n++) { StringBuffer_appendChar(sb, ','); StringBuffer_appendChar(sb, ' '); L3FormulaFormatter_visit( node, ASTNode_getChild(node, n), sb, settings); } StringBuffer_appendChar(sb, ')'); }
/** * Visits the given ASTNode node. This function is really just a * dispatcher to either SBML_formulaToL3String_visitFunction() or * SBML_formulaToL3String_visitOther(). */ void L3FormulaFormatter_visit ( const ASTNode_t *parent, const ASTNode_t *node, StringBuffer_t *sb, const L3ParserSettings_t *settings ) { if (ASTNode_isLog10(node)) { L3FormulaFormatter_visitLog10(parent, node, sb, settings); } else if (ASTNode_isSqrt(node)) { L3FormulaFormatter_visitSqrt(parent, node, sb, settings); } else if (isTranslatedModulo(node)) { L3FormulaFormatter_visitModulo(parent, node, sb, settings); } else if (L3FormulaFormatter_isFunction(node, settings)) { L3FormulaFormatter_visitFunction(parent, node, sb, settings); } else if (ASTNode_isUMinus(node)) { L3FormulaFormatter_visitUMinus(parent, node, sb, settings); } else if (ASTNode_hasTypeAndNumChildren(node, AST_LOGICAL_NOT, 1)) { L3FormulaFormatter_visitUNot(parent, node, sb, settings); } else if (ASTNode_hasTypeAndNumChildren(node, AST_QUALIFIER_LOGBASE, 1)) { L3FormulaFormatter_visit(node, ASTNode_getChild(node, 0), sb, settings); } else if (ASTNode_hasTypeAndNumChildren(node, AST_QUALIFIER_DEGREE, 1)) { L3FormulaFormatter_visit(node, ASTNode_getChild(node, 0), sb, settings); } else if (ASTNode_hasTypeAndNumChildren(node, AST_SEMANTICS, 1)) { L3FormulaFormatter_visit(node, ASTNode_getChild(node, 0), sb, settings); } else { L3FormulaFormatter_visitOther(parent, node, sb, settings); } }
/** * 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 the function "root(2, x)" and in doing so, * formats it as "sqrt(x)" (where x is any subexpression). */ void L3FormulaFormatter_visitSqrt ( const ASTNode_t *parent, const ASTNode_t *node, StringBuffer_t *sb, const L3ParserSettings_t *settings ) { StringBuffer_append(sb, "sqrt("); L3FormulaFormatter_visit(node, ASTNode_getChild(node, 1), sb, settings); StringBuffer_appendChar(sb, ')'); }
LIBSBML_EXTERN char * SBML_formulaToL3StringWithSettings (const ASTNode_t *tree, const L3ParserSettings_t *settings) { char *s; StringBuffer_t *sb = StringBuffer_create(128); if (tree == NULL) { return NULL; } L3FormulaFormatter_visit(NULL, tree, sb, settings); s = StringBuffer_getBuffer(sb); safe_free(sb); return s; }
/** * 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, ')'); } }
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 ); }