char * @link SBML_formulaToString(const ASTNode_t* tree)
SBML_formulaToString(const ASTNode* tree) @endlink
reads an
AST, converts it to a text string in SBML Level 1 formula syntax, and
returns it. The caller owns the character string returned and should free
it after it is no longer needed.
@li ASTNode * SBML_parseFormula(const char* formula)
reads a
text-string containing a mathematical expression in SBML Level 1 syntax and
returns an AST corresponding to the expression.
@section math-diffs The string formula syntax and differences with MathML
The text-string formula syntax is an infix notation essentially derived
from the syntax of the C programming language and was originally used in
SBML Level 1. The formula strings may contain operators, function
calls, symbols, and white space characters. The allowable white space
characters are tab and space. The following are illustrative examples of
formulas expressed in the syntax:
@verbatim
0.10 * k4^2
@endverbatim
@verbatim
(vm * s1)/(km + s1)
@endverbatim
The following table shows the precedence rules in this syntax. In the
Class column, @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 Precedence column show how the order of
different types of operation are determined. For example, the expression
a * b + c is evaluated as (a * b) + c because the @c *
operator has higher precedence. The Associates column shows how the order
of similar precedence operations is determined; for example, a - b +
c is evaluated as (a - b) + c because the @c + and @c -
operators are left-associative. The precedence and associativity rules are
taken from the C programming language, except for the symbol @c ^, which is
used in C for a different purpose. (Exponentiation can be invoked using
either @c ^ or the function @c power.)
@htmlinclude libsbml-math-precedence-table.html
A program parsing a formula in an SBML model should assume that names
appearing in the formula are the identifiers of Species, Parameter,
Compartment, FunctionDefinition, or Reaction objects defined in a model.
When a function call is involved, the syntax consists of a function
identifier, followed by optional white space, followed by an opening
parenthesis, 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. There is an
almost one-to-one mapping between the list of predefined functions
available, and those defined in MathML. All of the MathML functions are
recognized; this set is larger than the functions defined in SBML Level 1.
In the subset of functions that overlap between MathML and SBML Level 1,
there exist a few differences. The following table summarizes the
differences between the predefined functions in SBML Level 1 and the MathML
equivalents in SBML Level 2:
@htmlinclude libsbml-math-functions.html
@section math-ast Methods for working with libSBML's Abstract Syntax Trees
Every ASTNode in a libSBML abstract syntax tree has an associated type,
which is a value taken from the enumeration ASTNodeType_t. The list of
possible types is quite long, because it covers all the mathematical
functions that are permitted in SBML. The values are shown in the
following table; their names hopefully evoke the construct that they
represent:
@htmlinclude libsbml-astnode-types.html
There are a number of methods for interrogating the type of an ASTNode and
for testing whether a node belongs to a general category of constructs.
The methods on ASTNode for this purpose are the following:
@li ASTNodeType_t @link ASTNode::getType() getType() @endlink
returns the type of this AST node.
@li bool @link ASTNode::isConstant() isConstant() @endlink
returns @c true if this AST node is a MathML constant (@c true, @c false,
@c pi, @c exponentiale), @c false otherwise.
@li bool @link ASTNode::isBoolean() isBoolean() @endlink
returns @c true if this AST node returns a boolean value (by being either a
logical operator, a relational operator, or the constant @c true or @c
false).
@li bool @link ASTNode::isFunction() isFunction() @endlink
returns @c true if this AST node is a function (i.e., a MathML defined
function such as @c exp or else a function defined by a FunctionDefinition
in the Model).
@li bool @link ASTNode::isInfinity() isInfinity() @endlink
returns @c true if this AST node is the special IEEE 754 value infinity.
@li bool @link ASTNode::isInteger() isInteger() @endlink
returns @c true if this AST node is holding an integer value.
@li bool @link ASTNode::isNumber() isNumber() @endlink
returns
@c true if this AST node is holding any number.
@li bool @link ASTNode::isLambda() isLambda() @endlink
returns
@c true if this AST node is a MathML @c lambda construct.
@li bool @link ASTNode::isLog10() isLog10() @endlink
returns
@c true if this AST node represents the @c log10 function, specifically,
that its type is AST_FUNCTION_LOG and it has two children, the first of
which is an integer equal to 10.
@li bool @link ASTNode::isLogical() isLogical() @endlink
returns @c true if this AST node is a logical operator (@c and, @c or, @c
not, @c xor).
@li bool @link ASTNode::isName() isName() @endlink
returns @c
true if this AST node is a user-defined name or (in SBML Level 2) one of
the two special @c csymbol constructs "delay" or "time".
@li bool @link ASTNode::isNaN() isNaN() @endlink
returns @c
true if this AST node has the special IEEE 754 value "not a number" (NaN).
@li bool @link ASTNode::isNegInfinity() isNegInfinity()
@endlink
returns @c true if this AST node has the special IEEE 754
value of negative infinity.
@li bool @link ASTNode::isOperator() isOperator() @endlink
returns @c true if this AST node is an operator (e.g., @c +, @c -, etc.)
@li bool @link ASTNode::isPiecewise() isPiecewise() @endlink
returns @c true if this AST node is the MathML @c piecewise function.
@li bool @link ASTNode::isRational() isRational() @endlink
returns @c true if this AST node is a rational number having a numerator
and a denominator.
@li bool @link ASTNode::isReal() isReal() @endlink
returns @c
true if this AST node is a real number (specifically, AST_REAL_E or
AST_RATIONAL).
@li bool @link ASTNode::isRelational() isRelational() @endlink
returns @c true if this AST node is a relational operator.
@li bool @link ASTNode::isSqrt() isSqrt() @endlink
returns @c
true if this AST node is the square-root operator
@li bool @link ASTNode::isUMinus() isUMinus() @endlink
returns
@c true if this AST node is a unary minus.
@li bool @link ASTNode::isUnknown() isUnknown() @endlink
returns @c true if this AST node's type is unknown.
Programs manipulating AST node structures should check the type of a given
node before calling methods that return a value from the node. The
following are the ASTNode object methods available for returning values
from nodes:
@li long @link ASTNode::getInteger() getInteger() @endlink
@li char @link ASTNode::getCharacter() getCharacter() @endlink
@li const char* @link ASTNode::getName() getName() @endlink
@li long @link ASTNode::getNumerator() getNumerator() @endlink
@li long @link ASTNode::getDenominator() getDenominator()
@endlink
@li double @link ASTNode::getReal() getReal() @endlink
@li double @link ASTNode::getMantissa() getMantissa() @endlink
@li long @link ASTNode::getExponent() getExponent() @endlink
Of course, all of this would be of little use if libSBML didn't also
provide methods for @em setting the values of AST node objects! And it
does. The methods are the following:
@li void @link ASTNode::setCharacter(char value) setCharacter(char
value) @endlink
sets the value of this ASTNode to the given
character value
. If character is one of @c +, @c -, @c *, @c
/ or @c ^, the node type will be to the appropriate operator type. For all
other characters, the node type will be set to AST_UNKNOWN.
@li void @link ASTNode::setName(const char *name) setName(const char
*name) @endlink
sets the value of this AST node to the given
name
. The node type will be set (to AST_NAME) only
if the AST node was previously an operator (isOperator(node) !=
0
) or number (isNumber(node) != 0
). This allows names
to be set for AST_FUNCTIONs and the like.
@li void @link ASTNode::setValue(int value) setValue(int value)
@endlink
sets the value of the node to the given integer
value
. Equivalent to the next method.
@li void @link ASTNode::setValue(long value) setValue(long value)
@endlink
sets the value of the node to the given integer
value
. Equivalent to the previous method. No, this is not a
Gödelian self-referential loop.
@li void @link ASTNode::setValue(long numerator, long denominator)
setValue(long numerator, long denominator) @endlink
sets the value
of this ASTNode to the given rational value
in two parts: the
numerator and denominator. The node type is set to AST_RATIONAL.
@li void @link ASTNode::setValue(double value) setValue(double value)
@endlink
sets the value of this ASTNode to the given real (double)
value
and sets the node type to AST_REAL.
@li void @link ASTNode::setValue(double mantissa, long exponent)
setValue(double mantissa, long exponent) @endlink
sets the value of
this ASTNode to a real (double) using the two parts given: the mantissa and
the exponent. The node type is set to AST_REAL_E.
Finally, ASTNode also defines some miscellaneous methods for manipulating
ASTs:
@li ASTNode* @link ASTNode::ASTNode(ASTNodeType_t type)
ASTNode(ASTNodeType_t type) @endlink
creates a new ASTNode object
and returns a pointer to it. The returned node will have the given
type
, or a type of AST_UNKNOWN if no argument
type
is explicitly given.
@li unsigned int @link ASTNode::getNumChildren() getNumChildren()
@endlink
returns the number of children of this AST node or
0
is this node has no children.
@li void @link ASTNode::addChild(ASTNode* child) addChild(ASTNode*
child) @endlink
adds the given node as a child of this AST node.
Child nodes are added in left-to-right order.
@li void @link ASTNode::prependChild(ASTNode* child)
prependChild(ASTNode* child) @endlink
adds the given node as a child
of this AST node. This method adds child nodes in right-to-left order.
@li ASTNode* @link ASTNode::getChild (unsigned int n) getChild
(unsigned int n) @endlink
returns the n
th child of this
AST node or NULL if this node has no n
th child [i.e., if
n > (node->getNumChildren() - 1)
, where node
is a pointer to a node].
@li ASTNode* @link ASTNode::getLeftChild() getLeftChild()
@endlink
returns the left child of this AST node. This is
equivalent to getChild(0)
;
@li ASTNode* @link ASTNode::getRightChild() getRightChild()
@endlink
returns the right child of this AST node or NULL if this
node has no right child.
@li void @link ASTNode::swapChildren(ASTNode *that)
swapChildren(ASTNode *that) @endlink
swaps the children of this
ASTNode with the children of @c that ASTNode.
@li void @link ASTNode::setType(ASTNodeType_t type)
setType(ASTNodeType_t type) @endlink
sets the type of this ASTNode
to the given ASTNodeType_t enumeration value.
@section math-reading Reading and Writing Mathematical Expressions into ASTs
As mentioned above, applications often can avoid working with raw MathML by
using either libSBML's text-string interface or the AST API. However, when
needed, reading MathML content directly and creating ASTs is easily done in
libSBML using a method designed for this purpose:
@li ASTNode* readMathMLFromString(const char* xml)
reads raw
MathML from a text string, constructs an AST from it, then returns the root
ASTNode of the resulting expression tree.
Similarly, writing out Abstract Syntax Tree structures is easily done using
the following method:
@li char* writeMathMLToString(const ASTNode* node)
writes an
AST to a string. The caller owns the character string returned and should free
it after it is no longer needed.
The example program given above demonstrate the use of these methods. */