Abstract Syntax Tree (AST)
The node classes below are documented because they are what you see when you inspect or print a parsed expression; they are not meant to be constructed by hand.
The backend-neutral expression tree and the serializers that render it.
formulate.from_root() and formulate.from_numexpr() both return an
AST. Its node types (Literal, Symbol,
UnaryOperator, BinaryOperator, Matrix and
Call) are frozen dataclasses that hold canonical names rather than
any one language’s spelling: the ROOT &&, the NumExpr & and the Python
& all parse to BinaryOperator(operator="and", ...).
Rendering that tree back out is the job of AST.to_root(),
AST.to_numexpr() and AST.to_python(). Each looks its node up in the
tables in formulate.identifiers; a name that is missing from a table is
how “this construct has no faithful equivalent here” is expressed, and raises
ValueError rather than emitting something subtly different.
- class formulate.AST.AST
Bases:
objectBase class of every expression node.
Instances are produced by
formulate.from_root()andformulate.from_numexpr(), not constructed directly, and are immutable: converting an expression never modifies it, so one parsed expression can be rendered to as many backends as needed.str(node)gives a language-independent view of the tree in canonical names (add(x, pow(y, 2))), which is useful when debugging a conversion; use theto_*methods to get something an engine will accept.Nodes are deliberately neither comparable nor hashable.
==andhash()both raiseTypeError; see__eq__().- to_numexpr() str
Render the expression as NumExpr source.
Named constants have no NumExpr spelling and are substituted by their numeric value, so
picomes back as3.141592653589793.- Raises:
ValueError – if the expression uses a construct NumExpr has no equivalent for, such as array indexing,
inf, or the element-wiseTMath::Min/TMath::Max.
>>> import formulate >>> formulate.from_root("TMath::Sqrt(x**2 + y**2)").to_numexpr() 'sqrt(((x ** 2) + (y ** 2)))'
- to_root() str
Render the expression as a ROOT
TTreeFormulastring.- Raises:
ValueError – if the expression uses a construct ROOT has no equivalent for, such as
^used as XOR or NumExpr’swhere.
>>> import formulate >>> formulate.from_numexpr("sqrt(x**2 + y**2)").to_root() 'TMath::Sqrt(((x ** 2) + (y ** 2)))'
- to_python() str
Render the expression as plain Python, using NumPy for functions.
Function and constant names are emitted with an
np.prefix, so the result is meant to be evaluated somewhere NumPy is imported asnp. This backend is output-only: there is nofrom_python.- Raises:
ValueError – if the expression uses a construct with no NumPy equivalent that can be written as a single name, such as NumExpr’s
contains.
>>> import formulate >>> formulate.from_root("TMath::Sqrt(x**2 + y**2)").to_python() 'np.sqrt(((x ** 2) + (y ** 2)))'
- property variables: OrderedSet[str]
The names the expression reads, in order of first appearance.
Named constants are excluded; see
named_constants. For aTTreeexpression this is the set of branches that have to be read.>>> import formulate >>> list(formulate.from_root("x + TMath::Pi() * y").variables) ['x', 'y']
- class formulate.AST.Literal(value: int | float)
Bases:
ASTA number written out in the expression text, such as
2or1.5.
- class formulate.AST.Symbol(name: str)
Bases:
ASTA value referred to by name: a variable, or a named constant.
Constants are held under their canonical name (
pi,exp1) and are exactly those names that appear informulate.identifiers.CONSTANTS; every other name is a variable.
- class formulate.AST.UnaryOperator(operator: str, operand: AST)
Bases:
ASTAn operation with a single operand.
operatoris one of the canonical names informulate.identifiers.UNARY_OPERATORS:"pos","neg", or"inv"for the logical NOT written!in ROOT and~in NumExpr.
- class formulate.AST.BinaryOperator(operator: str, left: AST, right: AST)
Bases:
ASTAn operation with two operands.
operatoris one of the canonical names informulate.identifiers.BINARY_OPERATORS—"add","lt","and"and so on — never a backend’s spelling of it.
- class formulate.AST.Matrix(var: AST, indices: tuple[AST, ...])
Bases:
ASTAn indexed access,
var[i]orvar[i][j].ROOT writes one bracket pair per index and Python writes a single comma-separated one, so the same node renders as
arr[1][2]for ROOT andarr[1, 2]for Python. NumExpr has no indexing at all and rejects it.