math_spec.expression_parser
pyparsing-based expression parser for math expressions.
Parses strings like sum(p * cost, over=generator) == load into an AST
that can be evaluated against a namespace of linopy variables and xarray
parameters.
ArithmeticNode is the arithmetic-only union: every nested expression
position (operands, args, kwargs) accepts it and nothing else, and
ComparisonNode appears only at the top of a parsed expression.
ArithmeticNode = NumberNode | NameNode | NameListNode | VariableNode | ParameterNode | DimensionNode | LookupNode | EdgeNode | KeywordNode | UnaryOperatorNode | BinaryOperatorNode | FunctionCallNode | CasesNode
module-attribute
#
BranchNode = UnaryOperatorNode | BinaryOperatorNode | ComparisonNode | FunctionCallNode | CasesNode
module-attribute
#
ComparisonOperator = Literal['<=', '>=', '==']
module-attribute
#
ExpressionNode = ArithmeticNode | ComparisonNode
module-attribute
#
KwargNode = DimensionNode | LookupNode | EdgeNode
module-attribute
#
LeafNode = NumberNode | VariableNode | ParameterNode | KwargNode | UnresolvedNode
module-attribute
#
REAL = '\\d+\\.\\d*([eE][+-]?\\d+)?|\\d+[eE][+-]?\\d+'
module-attribute
#
UnresolvedNode = NameNode | NameListNode | KeywordNode
module-attribute
#
BinaryOperatorNode(op, left, right)
dataclass
#
CaseArm(label, when, value)
dataclass
#
CasesNode(name, arms)
dataclass
#
A value defined by region — a named expression's cases:, inlined.
Built by :mod:math_spec.expansion where a reference to a cased expression
stood; there is no grammar for it, since a file writes the cases on the
declaration rather than at the use site.
The arms are ordered and the last is the fallback, so exactly one applies at every coordinate without a checker having to establish it. The frame is not carried here: it is on the declaration, which every consumer needing it already holds.
ComparisonNode(op, left, right)
dataclass
#
DimensionNode(name)
dataclass
#
A resolved reference to a declared dimension.
Only legal in operator kwarg values (sum(x, over=generator)), never as
a value in arithmetic — a dimension is a coordinate space, not data.
name
instance-attribute
#
EdgeNode(policy)
dataclass
#
A resolved edge policy, legal only as an edge= value.
A number in the same position stays a :class:NumberNode: the value the
vacated positions contribute.
policy
instance-attribute
#
FunctionCallNode(name, args=list(), kwargs=dict())
dataclass
#
KeywordNode(value)
dataclass
#
A quoted closed keyword in a kwarg value — shift(..., edge='wrap').
Unresolved: which keywords the kwarg accepts is the operator's business.
value
instance-attribute
#
LookupNode(names, dimension, into)
dataclass
#
A resolved reference to one or more declared lookups, legal only in a kwarg value.
dimension is the one every lookup is over — what sum consumes and
at produces — and into the targets, one per name in the order
written; sum(x, by=[gen_bus, gen_tech]) is one grouping, not two.
NameListNode(names)
dataclass
#
NameNode(name)
dataclass
#
An unresolved token — a name whose kind is not yet known.
The parser cannot know whether p is a variable, a parameter or a
dimension; only the schema knows. resolution.py rewrites every one of
these into one of the typed nodes below, so a NameNode never reaches a
backend. If you find one there, resolution was skipped.
name
instance-attribute
#
ParameterNode(name)
dataclass
#
A resolved reference to a declared parameter.
name
instance-attribute
#
VariableNode(name)
dataclass
#
A resolved reference to a declared decision variable.
name
instance-attribute
#
children(node)
#
The sub-expressions of node — the structural half of any walk.
Every pass that recurses the whole tree and acts only at certain leaves
goes through here, so a node added later reaches all of them. A pass whose
answer differs per node type dispatches itself and keeps its
assert_never; this is for the ones that only need to get everywhere.
An operator's kwargs are children too — a dimension or coordinate is an ordinary node in a kwarg value, which is what lets a macro bind a formal.
Source code in src/math_spec/expression_parser.py
parse_expression(text)
#
Parse a math expression string into an AST.
| RAISES | DESCRIPTION |
|---|---|
SchemaError
|
If text is not an expression of the language. |
Source code in src/math_spec/expression_parser.py
shown(names)
#
Names as a kwarg value is written: bare when one, bracketed when several.