/** * @return the given formula AST as a directed graph. The caller * owns the returned string and is responsible for freeing it. */ char * SBML_formulaToDot (const ASTNode_t *tree) { StringBuffer_t *sb = StringBuffer_create(128); char *name; char *s; if (FormulaGraphvizFormatter_isFunction(tree) || ASTNode_isOperator(tree)) { FormulaGraphvizFormatter_visit(NULL, tree, sb); } else { name = FormulaGraphvizFormatter_format(tree); StringBuffer_append(sb, name); } StringBuffer_append(sb, "}\n"); s = StringBuffer_getBuffer(sb); free(sb); return s; }
END_TEST START_TEST (test_FormulaFormatter_multiDivide) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); ASTNode_t *c = ASTNode_create(); ASTNode_setType(n, AST_DIVIDE); s = SBML_formulaToString(n); fail_unless( !strcmp(s, " / "), NULL ); ASTNode_setName(c, "x"); ASTNode_addChild(n, c); s = SBML_formulaToString(n); fail_unless( !strcmp(s, " / (x)"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "y"); ASTNode_addChild(n, c); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "x / y"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "z"); ASTNode_addChild(n, c); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "x / y / z"), NULL ); safe_free(s); ASTNode_free(n); }
END_TEST START_TEST (test_FormulaFormatter_multiOr) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); ASTNode_t *c = ASTNode_create(); ASTNode_setType(n, AST_LOGICAL_OR); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "or()"), NULL ); ASTNode_setName(c, "x"); ASTNode_addChild(n, c); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "or(x)"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "y"); ASTNode_addChild(n, c); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "or(x, y)"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "z"); ASTNode_addChild(n, c); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "or(x, y, z)"), NULL ); safe_free(s); ASTNode_free(n); }
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_FormulaFormatter_multiPlusTimes) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); ASTNode_t *c = ASTNode_create(); ASTNode_setType(n, AST_PLUS); ASTNode_setName(c, "x"); ASTNode_addChild(n, c); c = ASTNode_create(); ASTNode_setName(c, "y"); ASTNode_addChild(n, c); c = ASTNode_create(); ASTNode_setName(c, "z"); ASTNode_addChild(n, c); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "x + y + z"), NULL ); ASTNode_setType(n, AST_TIMES); s = SBML_formulaToString(n); fail_unless( !strcmp(s, "x * y * z"), NULL ); safe_free(s); ASTNode_free(n); }
END_TEST START_TEST (test_L3FormulaFormatter_multiAnd) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); ASTNode_t *c = ASTNode_create(); ASTNode_setType(n, AST_LOGICAL_AND); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "and()"), NULL ); ASTNode_setName(c, "x"); ASTNode_addChild(n, c); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "and(x)"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "y"); ASTNode_addChild(n, c); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "x && y"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "z"); ASTNode_addChild(n, c); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "x && y && z"), NULL ); safe_free(s); ASTNode_free(n); }
END_TEST START_TEST (test_L3FormulaFormatter_multiGT) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); ASTNode_t *c = ASTNode_create(); ASTNode_setType(n, AST_RELATIONAL_GT); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "gt()"), NULL ); ASTNode_setName(c, "x"); ASTNode_addChild(n, c); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "gt(x)"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "y"); ASTNode_addChild(n, c); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "x > y"), NULL ); safe_free(s); c = ASTNode_create(); ASTNode_setName(c, "z"); ASTNode_addChild(n, c); s = SBML_formulaToL3String(n); fail_unless( !strcmp(s, "gt(x, y, z)"), NULL ); safe_free(s); ASTNode_free(n); }
END_TEST START_TEST (test_L3FormulaFormatter_parseUnits) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); L3ParserSettings_t* l3ps = L3ParserSettings_create(); ASTNode_setReal(n, 1.1); ASTNode_setUnits(n, "mL"); //default (true) s = SBML_formulaToL3StringWithSettings(n, l3ps); fail_unless( !strcmp(s, "1.1 mL"), NULL ); safe_free(s); //explicit false L3ParserSettings_setParseUnits(l3ps, 0); s = SBML_formulaToL3StringWithSettings(n, l3ps); fail_unless( !strcmp(s, "1.1"), NULL ); safe_free(s); //explicit true L3ParserSettings_setParseUnits(l3ps, 1); s = SBML_formulaToL3StringWithSettings(n, l3ps); fail_unless( !strcmp(s, "1.1 mL"), NULL ); safe_free(s); ASTNode_free(n); L3ParserSettings_free(l3ps); }
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; }
END_TEST START_TEST (test_L3FormulaFormatter_collapseMinus) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); ASTNode_t *c = ASTNode_create(); ASTNode_t *c2 = ASTNode_create(); ASTNode_t *c3 = ASTNode_create(); ASTNode_t *c4 = ASTNode_create(); L3ParserSettings_t* l3ps = L3ParserSettings_create(); ASTNode_setType(n, AST_MINUS); ASTNode_setType(c, AST_MINUS); ASTNode_addChild(n, c); ASTNode_setType(c2, AST_MINUS); ASTNode_addChild(c, c2); ASTNode_setType(c3, AST_MINUS); ASTNode_addChild(c2, c3); ASTNode_setName(c4, "x"); ASTNode_addChild(c3, c4); //default (false) s = SBML_formulaToL3StringWithSettings(n, l3ps); fail_unless( !strcmp(s, "----x"), NULL ); safe_free(s); //explicit false L3ParserSettings_setParseCollapseMinus(l3ps, 0); s = SBML_formulaToL3StringWithSettings(n, l3ps); fail_unless( !strcmp(s, "----x"), NULL ); safe_free(s); //explicit true L3ParserSettings_setParseCollapseMinus(l3ps, 1); s = SBML_formulaToL3StringWithSettings(n, l3ps); fail_unless( !strcmp(s, "x"), NULL ); safe_free(s); ASTNode_free(n); L3ParserSettings_free(l3ps); }
/** * Converts an AST to a string representation of a formula using a syntax * basically derived from SBML Level 1. * * @if clike The text-string form of mathematical formulas produced by * SBML_formulaToString() and read by SBML_parseFormula() and SBML_parseL3Formula() * are in a C-inspired infix notation. A formula in * this text-string form therefore can be handed to a program that * understands SBML mathematical expressions, or used as part * of a formula translation system. The syntax is described in detail in * the documentation for ASTNode. @endif@if java The text-string form of * mathematical formulas produced by <code><a * href="libsbml.html#formulaToString(org.sbml.libsbml.ASTNode)"> * libsbml.formulaToString()</a></code> and read by * <code><a href="libsbml.html#parseFormula(java.lang.String)"> * libsbml.parseFormula()</a></code> and * <code><a href="libsbml.html#parseL3Formula(java.lang.String)"> * libsbml.parseL3Formula()</a></code> are in a * simple C-inspired infix notation. A * formula in this text-string form therefore can be handed to a program * that understands SBML mathematical expressions, or used as * part of a formula translation system. The syntax is described in detail * in the documentation for ASTNode. @endif * * Note that this facility is provided as a convenience by libSBML—the * MathML standard does not actually define a "string-form" equivalent to * MathML expression trees, so the choice of formula syntax is somewhat * arbitrary. The approach taken by libSBML is to use the syntax defined by * SBML Level 1 (which in fact used a text-string representation of * formulas and not MathML). This formula syntax is based mostly on C * programming syntax, and may contain operators, function calls, symbols, * and white space characters. The following table provides the precedence * rules for the different entities that may appear in formula strings. * * @htmlinclude math-precedence-table.html * * In the table above, @em operand implies the construct is an operand, @em * prefix implies the operation is applied to the following arguments, @em * unary implies there is one argument, and @em binary implies there are * two arguments. The values in the <b>Precedence</b> column show how the * order of different types of operation are determined. For example, the * expression <code>a * b + c</code> is evaluated as <code>(a * b) + * c</code> because the @c * operator has higher precedence. The * <b>Associates</b> column shows how the order of similar precedence * operations is determined; for example, <code>a - b + c</code> is * evaluated as <code>(a - b) + c</code> because the @c + and @c - * operators are left-associative. * * The function call syntax consists of a function name, followed by optional * white space, followed by an opening parenthesis token, followed by a * sequence of zero or more arguments separated by commas (with each comma * optionally preceded and/or followed by zero or more white space * characters, followed by a closing parenthesis token. The function name * must be chosen from one of the pre-defined functions in SBML or a * user-defined function in the model. The following table lists the names * of certain common mathematical functions; this table corresponds to * Table 6 in the <a target="_blank" href="http://sbml.org/Documents/Specifications#SBML_Level_1_Version_2">SBML Level 1 Version 2 specification</a>: * * @htmlinclude string-functions-table.html * * @warning There are differences between the symbols used to represent the * common mathematical functions and the corresponding MathML token names. * This is a potential source of incompatibilities. Note in particular that * in this text-string syntax, <code>log(x)</code> represents the natural * logarithm, whereas in MathML, the natural logarithm is * <code><ln/></code>. Application writers are urged to be careful * when translating between text forms and MathML forms, especially if they * provide a direct text-string input facility to users of their software * systems.<br><br> * @htmlinclude L1-math-syntax-warning.html * * @param tree the AST to be converted. * * @return the formula from the given AST as an SBML Level 1 text-string * mathematical formula. The caller owns the returned string and is * responsible for freeing it when it is no longer needed. * * @see SBML_parseFormula() * @see SBML_parseL3Formula() */ LIBSBML_EXTERN char * SBML_formulaToString (const ASTNode_t *tree) { char *s; if (tree == NULL) { s = NULL; } else { StringBuffer_t *sb = StringBuffer_create(128); FormulaFormatter_visit(NULL, tree, sb); s = StringBuffer_getBuffer(sb); safe_free(sb); } return s; }
END_TEST START_TEST (test_FormulaFormatter_formatReal) { StringBuffer_t *sb = StringBuffer_create(42); char *s = StringBuffer_getBuffer(sb); ASTNode_t *n = ASTNode_create(); /** 1.2 **/ ASTNode_setReal(n, 1.2); FormulaFormatter_formatReal(sb, n); fail_unless( !strcmp(s, "1.2"), NULL ); StringBuffer_reset(sb); /** 1e-100 **/ ASTNode_setRealWithExponent(n, 1, -100); FormulaFormatter_formatReal(sb, n); fail_unless( !strcmp(s, "1.000000e-100"), NULL ); StringBuffer_reset(sb); /** NaN **/ ASTNode_setReal(n, util_NaN()); FormulaFormatter_formatReal(sb, n); fail_unless( !strcmp(s, "NaN"), NULL ); StringBuffer_reset(sb); /** Inf **/ ASTNode_setReal(n, util_PosInf()); FormulaFormatter_formatReal(sb, n); fail_unless( !strcmp(s, "INF"), NULL ); StringBuffer_reset(sb); /** -Inf **/ ASTNode_setReal(n, util_NegInf()); FormulaFormatter_formatReal(sb, n); fail_unless( !strcmp(s, "-INF"), NULL ); StringBuffer_reset(sb); /** -0 **/ ASTNode_setReal(n, util_NegZero()); FormulaFormatter_formatReal(sb, n); fail_unless( !strcmp(s, "-0"), NULL ); StringBuffer_reset(sb); StringBuffer_free(sb); ASTNode_free(n); }