/** * Formats the given ASTNode as an SBML L3 token and appends the result to * the given StringBuffer. */ void L3FormulaFormatter_format (StringBuffer_t *sb, const ASTNode_t *node, const L3ParserSettings_t *settings) { if (sb == NULL) return; if (L3FormulaFormatter_isFunction(node, settings)) { L3FormulaFormatter_formatFunction(sb, node, settings); } else if (ASTNode_isOperator(node) || ASTNode_getType(node) == AST_FUNCTION_POWER) { L3FormulaFormatter_formatOperator(sb, node); } else if (ASTNode_isLogical(node) || ASTNode_isRelational(node)) { L3FormulaFormatter_formatLogicalRelational(sb, node); } else if (ASTNode_isRational(node)) { L3FormulaFormatter_formatRational(sb, node, settings); } else if (ASTNode_isInteger(node)) { L3FormulaFormatter_formatReal(sb, node, settings); } else if (ASTNode_isReal(node)) { L3FormulaFormatter_formatReal(sb, node, settings); } else if ( !ASTNode_isUnknown(node) ) { StringBuffer_append(sb, ASTNode_getName(node)); } }
/** * @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; }
/** * 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); } }
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 ); }
LIBSBML_CPP_NAMESPACE_USE CK_CPPSTART #endif START_TEST (test_L3FormulaFormatter_isFunction) { ASTNode_t *n = ASTNode_create(); ASTNode_t *c = ASTNode_create(); ASTNode_setType(n, AST_NAME); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 0, NULL ); ASTNode_setType(n, AST_CONSTANT_PI); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 0, NULL ); ASTNode_setType(n, AST_LAMBDA); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); ASTNode_setType(n, AST_FUNCTION); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); ASTNode_setType(n, AST_LOGICAL_AND); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); ASTNode_setType(n, AST_RELATIONAL_EQ); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); ASTNode_setType(n, AST_PLUS); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); ASTNode_addChild(n, c); ASTNode_setType(n, AST_LOGICAL_AND); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); ASTNode_setType(n, AST_RELATIONAL_EQ); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); ASTNode_setType(n, AST_PLUS); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 1, NULL ); c = ASTNode_create(); ASTNode_addChild(n, c); ASTNode_setType(n, AST_LOGICAL_AND); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 0, NULL ); ASTNode_setType(n, AST_RELATIONAL_EQ); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 0, NULL ); ASTNode_setType(n, AST_PLUS); fail_unless( L3FormulaFormatter_isFunction(n, NULL) == 0, NULL ); ASTNode_free(n); }