/** * Visits the given ASTNode as a function. For this node only the * traversal is preorder. */ void FormulaFormatter_visitFunction ( const ASTNode_t *parent, const ASTNode_t *node, StringBuffer_t *sb ) { unsigned int numChildren = ASTNode_getNumChildren(node); unsigned int n; FormulaFormatter_format(sb, node); StringBuffer_appendChar(sb, '('); if (numChildren > 0) { FormulaFormatter_visit( node, ASTNode_getChild(node, 0), sb ); } for (n = 1; n < numChildren; n++) { StringBuffer_appendChar(sb, ','); StringBuffer_appendChar(sb, ' '); FormulaFormatter_visit( node, ASTNode_getChild(node, n), sb ); } 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 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, ')'); } }
/** * Formats the given ASTNode as a rational number and appends the result to * the given StringBuffer. For SBML L1 this amounts to: * * "(numerator/denominator)" */ void FormulaFormatter_formatRational (StringBuffer_t *sb, const ASTNode_t *node) { StringBuffer_appendChar( sb, '('); StringBuffer_appendInt ( sb, ASTNode_getNumerator(node) ); StringBuffer_appendChar( sb, '/'); StringBuffer_appendInt ( sb, ASTNode_getDenominator(node) ); StringBuffer_appendChar( sb, ')'); }
/** * Formats the given ASTNode as a real number and appends the result to * the given StringBuffer. */ void L3FormulaFormatter_formatReal (StringBuffer_t *sb, const ASTNode_t *node, const L3ParserSettings_t *settings) { double value = ASTNode_getReal(node); int sign; char * units; if (ASTNode_isInteger(node)) { value = ASTNode_getInteger(node); } if (util_isNaN(value)) { StringBuffer_append(sb, "NaN"); } else if ((sign = util_isInf(value)) != 0) { if (sign == -1) { StringBuffer_appendChar(sb, '-'); } StringBuffer_append(sb, "INF"); } else if (util_isNegZero(value)) { StringBuffer_append(sb, "-0"); } else { if (ASTNode_getType(node) == AST_REAL_E) { StringBuffer_appendExp(sb, value); } else { StringBuffer_appendReal(sb, value); } } if (L3ParserSettings_getParseUnits(settings)) { if (ASTNode_hasUnits(node)) { StringBuffer_appendChar( sb, ' '); units = ASTNode_getUnits(node); StringBuffer_append( sb, units); safe_free(units); } } }
END_TEST START_TEST (test_StringBuffer_appendReal_locale) { char *s, *t; setlocale(LC_NUMERIC, "de_DE"); StringBuffer_appendReal(SB, 1.2); fail_unless( StringBuffer_length(SB) == 3 ); fail_unless( StringBuffer_capacity(SB) == 80 ); s = StringBuffer_toString(SB); fail_unless( !strcmp(s, "1.2") ); StringBuffer_appendChar(SB, ' '); StringBuffer_appendReal(SB, 3); fail_unless( StringBuffer_length(SB) == 5 ); fail_unless( StringBuffer_capacity(SB) == 80 ); t = StringBuffer_toString(SB); fail_unless( !strcmp(t, "1.2 3") ); setlocale(LC_NUMERIC, "C"); safe_free(s); safe_free(t); }
END_TEST START_TEST (test_StringBuffer_appendInt) { char *s, *t; StringBuffer_appendInt(SB, 1); fail_unless( StringBuffer_length(SB) == 1 ); fail_unless( StringBuffer_capacity(SB) == 80 ); s = StringBuffer_toString(SB); fail_unless( !strcmp(s, "1") ); StringBuffer_appendChar(SB, ' '); StringBuffer_appendInt(SB, 23); fail_unless( StringBuffer_length(SB) == 4 ); fail_unless( StringBuffer_capacity(SB) == 80 ); t = StringBuffer_toString(SB); fail_unless( !strcmp(t, "1 23") ); safe_free(s); safe_free(t); }
/** * Formats the given ASTNode as a rational number and appends the result to * the given StringBuffer. For SBML L1 this amounts to: * * "(numerator/denominator)" */ void L3FormulaFormatter_formatRational (StringBuffer_t *sb, const ASTNode_t *node, const L3ParserSettings_t *settings) { StringBuffer_appendChar( sb, '('); StringBuffer_appendInt ( sb, ASTNode_getNumerator(node) ); StringBuffer_appendChar( sb, '/'); StringBuffer_appendInt ( sb, ASTNode_getDenominator(node) ); StringBuffer_appendChar( sb, ')'); if (L3ParserSettings_getParseUnits(settings)) { if (ASTNode_hasUnits(node)) { StringBuffer_appendChar( sb, ' '); StringBuffer_append( sb, ASTNode_getUnits(node)); } } }
/** * Formats the given ASTNode as an SBML L1 operator and appends the result * to the given StringBuffer. */ void L3FormulaFormatter_formatOperator (StringBuffer_t *sb, const ASTNode_t *node) { ASTNodeType_t type = ASTNode_getType(node); if (type == AST_FUNCTION_POWER || type == AST_POWER) { StringBuffer_appendChar(sb, '^'); } else { StringBuffer_appendChar(sb, ' '); StringBuffer_appendChar(sb, ASTNode_getCharacter(node)); StringBuffer_appendChar(sb, ' '); } }
END_TEST START_TEST (test_StringBuffer_accessWithNULL) { StringBuffer_append(NULL, NULL); StringBuffer_appendChar(NULL, ' '); StringBuffer_appendExp(NULL, 0.0); StringBuffer_appendInt(NULL, 0); StringBuffer_appendNumber(NULL, NULL); StringBuffer_appendReal(NULL, 0.0); fail_unless (StringBuffer_capacity(NULL) == 0); StringBuffer_ensureCapacity(NULL, 0); StringBuffer_free(NULL); fail_unless (StringBuffer_getBuffer(NULL) == NULL); StringBuffer_grow(NULL, 0); fail_unless (StringBuffer_length(NULL) == 0); StringBuffer_reset(NULL); fail_unless (StringBuffer_toString(NULL) == NULL); }
END_TEST START_TEST (test_StringBuffer_appendChar_grow) { char *s, *t; StringBuffer_append(SB, "fooooooooo"); fail_unless( StringBuffer_length(SB) == 10 ); fail_unless( StringBuffer_capacity(SB) == 10 ); s = StringBuffer_toString(SB); fail_unless( !strcmp(s, "fooooooooo") ); StringBuffer_appendChar(SB, '!'); fail_unless( StringBuffer_length(SB) == 11 ); fail_unless( StringBuffer_capacity(SB) == 20 ); t = StringBuffer_toString(SB); fail_unless( !strcmp(t, "fooooooooo!") ); safe_free(s); safe_free(t); }
/** * 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 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 ); }
/** * Formats the given ASTNode as a rational number and returns the result as * a string. This amounts to: * * "(numerator/denominator)" */ char * FormulaGraphvizFormatter_formatRational (const ASTNode_t *node) { char *s; StringBuffer_t *p = StringBuffer_create(128); StringBuffer_appendChar( p, '('); StringBuffer_appendInt ( p, ASTNode_getNumerator(node) ); StringBuffer_appendChar( p, '/'); StringBuffer_appendInt ( p, ASTNode_getDenominator(node) ); StringBuffer_appendChar( p, ')'); s = StringBuffer_toString(p); free(p); return s; }
/** * 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 FormulaFormatter_visitSqrt ( const ASTNode_t *parent, const ASTNode_t *node, StringBuffer_t *sb ) { StringBuffer_append(sb, "sqrt("); FormulaFormatter_visit(node, ASTNode_getChild(node, 1), sb); StringBuffer_appendChar(sb, ')'); }
/** * Formats the given ASTNode as an SBML L1 operator and appends the result * to the given StringBuffer. */ void FormulaFormatter_formatOperator (StringBuffer_t *sb, const ASTNode_t *node) { ASTNodeType_t type = ASTNode_getType(node); if (type != AST_POWER) { StringBuffer_appendChar(sb, ' '); } StringBuffer_appendChar(sb, ASTNode_getCharacter(node)); if (type != AST_POWER) { StringBuffer_appendChar(sb, ' '); } }
/** * Formats the given ASTNode as an SBML L1 operator and appends the result * to the given StringBuffer. */ void L3FormulaFormatter_formatLogicalRelational (StringBuffer_t *sb, const ASTNode_t *node) { ASTNodeType_t type = ASTNode_getType(node); StringBuffer_appendChar(sb, ' '); switch(type) { case AST_LOGICAL_AND: StringBuffer_append(sb, "&&"); break; case AST_LOGICAL_OR: StringBuffer_append(sb, "||"); break; case AST_RELATIONAL_EQ: StringBuffer_append(sb, "=="); break; case AST_RELATIONAL_GEQ: StringBuffer_append(sb, ">="); break; case AST_RELATIONAL_GT: StringBuffer_append(sb, ">"); break; case AST_RELATIONAL_LEQ: StringBuffer_append(sb, "<="); break; case AST_RELATIONAL_LT: StringBuffer_append(sb, "<"); break; case AST_RELATIONAL_NEQ: StringBuffer_append(sb, "!="); break; case AST_LOGICAL_NOT: case AST_LOGICAL_XOR: default: //Should never be called for these cases; unary not is // handled by checking unary not earlier; xor always // claims that it's a function, and is caught with 'isFunction' assert(0); StringBuffer_append(sb, "!!"); break; } 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, ')'); }
/** * 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, ')'); } }
LIBSBML_EXTERN void StringBuffer_appendFullExp(StringBuffer_t *sb, double mantissa, long exponent, double value) { if (mantissa >= 1e14 || mantissa <= -1e14 || (mantissa < 1e-4 && mantissa > -1e-4)) { StringBuffer_appendReal(sb, value); return; } StringBuffer_appendNumber(sb, LIBSBML_FLOAT_FORMAT, mantissa); StringBuffer_appendChar(sb, 'e'); StringBuffer_appendInt(sb, exponent); }
END_TEST START_TEST (test_StringBuffer_appendChar) { char *s, *t, *u; StringBuffer_appendChar(SB, '*'); fail_unless( StringBuffer_length(SB) == 1 ); fail_unless( StringBuffer_capacity(SB) == 10 ); s = StringBuffer_toString(SB); fail_unless( !strcmp(s, "*") ); StringBuffer_append(SB, "foo"); fail_unless( StringBuffer_length(SB) == 4 ); fail_unless( StringBuffer_capacity(SB) == 10 ); t = StringBuffer_toString(SB); fail_unless( !strcmp(t, "*foo") ); StringBuffer_appendChar(SB, '*'); fail_unless( StringBuffer_length(SB) == 5 ); fail_unless( StringBuffer_capacity(SB) == 10 ); u = StringBuffer_toString(SB); fail_unless( !strcmp(u, "*foo*") ); safe_free(s); safe_free(t); safe_free(u); }
/** * Formats the given ASTNode as a directed graph operator and returns the result * as a string. */ char * FormulaGraphvizFormatter_formatOperator (const ASTNode_t *node) { char *s; ASTNodeType_t type = ASTNode_getType(node); StringBuffer_t *p = StringBuffer_create(128); switch (type) { case AST_TIMES: s = "times"; break; case AST_DIVIDE: s = "divide"; break; case AST_PLUS: s = "plus"; break; case AST_MINUS: s = "minus"; break; case AST_POWER: s = "power"; break; default: StringBuffer_appendChar(p, ASTNode_getCharacter(node)); s = StringBuffer_toString(p); break; } free(p); return s; }
/** * Formats the given ASTNode as a real number and appends the result to * the given StringBuffer. */ void FormulaFormatter_formatReal (StringBuffer_t *sb, const ASTNode_t *node) { double value = ASTNode_getReal(node); int sign; if (util_isNaN(value)) { StringBuffer_append(sb, "NaN"); } else if ((sign = util_isInf(value)) != 0) { if (sign == -1) { StringBuffer_appendChar(sb, '-'); } StringBuffer_append(sb, "INF"); } else if (util_isNegZero(value)) { StringBuffer_append(sb, "-0"); } else { if (ASTNode_getType(node) == AST_REAL_E) { StringBuffer_appendExp(sb, value); } else { StringBuffer_appendReal(sb, value); } } }
/** * Since graphviz will interpret identical names as referring to * the same node presentation-wise it is better if each function node * has a unique name. * * Returns the name of the operator with the name of the first child * prepended * * THIS COULD BE DONE BETTER */ char * FormulaGraphvizFormatter_OperatorGetUniqueName (const ASTNode_t *node) { char *s; char number[10]; StringBuffer_t *p = StringBuffer_create(128); ASTNodeType_t type = ASTNode_getType(node); if (FormulaGraphvizFormatter_isFunction(ASTNode_getChild(node,0)) || ASTNode_isOperator(ASTNode_getChild(node,0))) { StringBuffer_append(p, "func"); } else { if (ASTNode_isInteger(ASTNode_getChild(node, 0))) { sprintf(number, "%d", (int)ASTNode_getInteger(ASTNode_getChild(node, 0))); StringBuffer_append(p, number); } else if (ASTNode_isReal(ASTNode_getChild(node, 0))) { sprintf(number, "%ld", ASTNode_getNumerator(ASTNode_getChild(node, 0))); StringBuffer_append(p, number); } else { StringBuffer_append(p, ASTNode_getName(ASTNode_getChild(node,0))); } } switch (type) { case AST_TIMES: StringBuffer_append(p, "times"); break; case AST_DIVIDE: StringBuffer_append(p, "divide"); break; case AST_PLUS: StringBuffer_append(p, "plus"); break; case AST_MINUS: StringBuffer_append(p, "minus"); break; case AST_POWER: StringBuffer_append(p, "power"); break; default: StringBuffer_appendChar(p, ASTNode_getCharacter(node)); break; } s = StringBuffer_toString(p); free(p); return s; }