/** * 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; }
/** * @return true (non-zero) if the given ASTNode is to formatted as a * function. */ int FormulaGraphvizFormatter_isFunction (const ASTNode_t *node) { return ASTNode_isFunction (node) || ASTNode_isLambda (node) || ASTNode_isLogical (node) || ASTNode_isRelational(node); }