Nodes#
The parser turns source code into a tree of nodes. Each node is a dataclass with a
type string; the renderer dispatches on that string, so type is the name you
register handlers under.
What a tree looks like#
>>> from handcalcs.parsing.sequence import HcSequence
>>> tree = HcSequence.from_source("a = 2\nb = a * 3 # note\n", hc_globals={"a": 2, "b": 6}, hc_locals={})
>>> tree.sequence
deque([CalcsBlock(lines=deque([
CalcLine(assigns=deque([Name(identifier='a', value=2)]),
expression_tree=deque([Constant(value=2)]),
comment=None),
CalcLine(assigns=deque([Name(identifier='b', value=6)]),
expression_tree=deque([MultOp(left=Name(identifier='a', value=2),
right=Constant(value=3),
symbol='*')]),
comment=InlineComment(content='note')),
]))])
(Abbreviated: fields at their defaults are left out.) After a call, HandCalcs.hc_ast
holds the tree it rendered, so you can inspect the tree for any source.
Node types#
The tables below list every node type, its class and the attributes a handler typically
reads. All classes live in handcalcs.parsing.
Lines#
Defined in line_nodes. Every line node has level (nesting
depth) and pre/post strings.
|
Class |
Attributes |
Source |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Blocks#
Defined in block_nodes. Every block has lines (its children),
level, and four strings the built-in block handler wraps around its output:
header_pre, header_post, body_pre, body_post.
|
Class |
Attributes |
Made from |
|---|---|---|---|
|
|
|
consecutive calc/expr lines (by |
|
|
|
consecutive comment lines |
|
|
|
|
|
|
|
an |
|
|
|
one |
|
|
|
the |
|
|
|
a |
Expressions#
Defined in nodes, inline_nodes and
operator_nodes.
|
Class |
Attributes |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(none) |
Operators#
Every operator has symbol (initially the Python symbol) and pre/post strings, which
the built-in handlers place around the rendered operation.
|
Class |
Attributes |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
The root#
The root is an HcSequence with
type = "root" and the top-level nodes in sequence. render_root handles it; it is
not dispatched to a handler, but you can register root:pre and root:post rules to add
items at the start and end of the output.
Values#
A Name (or Attribute) carries its value in value. A value can be any Python object;
the built-in name handler renders it in numeric mode by turning it into a Constant
(or a collection node) and rendering that, so the constant handler is where values are
formatted.
NoValue() marks a name without a value (not in the namespace). It renders as an empty
string.
Next: Handlers and rules.