public interface TreeWalker
A tree is made up of one or more nodes. Each node has at most one parent node. Each node can have 0 or more child nodes. Child nodes are ordered in a left to right manner based on a 0-based index position. The child at index position 0 is the left-most child, also known as the first child. The child node at the highest index position is the rightmost or last child.
A node with no children is a terminal or leaf node. At the "top" of the tree is a special node called the root node. It is special in that it is the only node that has no parent node. The root node is the ancestor for all other nodes in the tree.
Tree processing is done in a depth-first and left to right traversal, starting at the root. Depth-first means that the iteration will traverse the children of any given node before traversing that node's siblings. Left to right traversal means that siblings are processed first at the left and then later to the right.
Based on the above described traveral order of the tree, the following events/notifications/callbacks are defined:
pre(com.goldencode.trpl.WalkState)
walk(com.goldencode.trpl.WalkState)
descent(com.goldencode.trpl.WalkState)
nextChild(com.goldencode.trpl.WalkState, int)
ascent(com.goldencode.trpl.WalkState)
post(com.goldencode.trpl.WalkState)
In order to support multi-threaded access, it is necessary to be able to
duplicate a walker instance. This allows a list of walkers to be duplicated
as many times as may be needed to provide each tree processing thread
separate and independent instances of the walkers being executed. See
duplicate()
Modifier and Type | Method and Description |
---|---|
void |
ascent(WalkState state)
Called whenever a transition from the last child node to its parent takes
place during tree traversal.
|
void |
descent(WalkState state)
Called whenever a transition from a parent node to its first child
takes place during an AST walk.
|
TreeWalker |
duplicate()
Make a deep copy of this instance and return that new instance.
|
void |
nextChild(WalkState state,
int index)
Called whenever a transition from a child node (the "left sibling") to
its next right sibling takes place during tree traversal.
|
void |
post(WalkState state)
Called once per tree, after all other hooks have been invoked.
|
void |
pre(WalkState state)
Called once per tree, before any other hook is invoked.
|
void |
walk(WalkState state)
Called once per node, this notifies the registered code that the node
is being visited.
|
void pre(WalkState state)
This is useful for allocating resources or calculating/initializing any values that should be handled once per tree.
state
- Provides tree processing state including which node is being
processed and the current status of the tree processing.void walk(WalkState state)
pre(com.goldencode.trpl.WalkState)
completes. From there it will be called for each of the
nodes of the tree in a depth first traversal.
At the time this is called, the current node will be set to the node being "walked" or visited.
Most logic is inserted in these hooks. Anything that does not depend upon the order of child node processing is usually placed here.
state
- Provides tree processing state including which node is being
processed and the current status of the tree processing.void descent(WalkState state)
walk(com.goldencode.trpl.WalkState)
. This call never occurs for nodes that have no children.
At the time this is called, the parent node will be the current node.
This is very useful for implementing scope-aware data structures (such as a stack). Scopes are normally pushed (added) on descent.
state
- Provides tree processing state including which node is being
processed and the current status of the tree processing.void nextChild(WalkState state, int index)
walk(com.goldencode.trpl.WalkState)
. This will be called after all the
child nodes (if any) of the left sibling have been processed. If the
left sibling has child nodes, there will be an ascent(com.goldencode.trpl.WalkState)
call with
the left sibling in scope just before the next child call is executed.
This never occurs for nodes that have no children.
The parent node of the children is in scope at the time of the notification. This effectively mimics recursion by notifying the listener when one child node has been processed, before the next is visited. This allows the listener to perform parent-level processing between visits to child nodes.
This method is not invoked after the last child is visited,
since there is no next child to which to move. To obtain a callback
after the last child has processed, use the ascent
method.
This callback is highly useful for implementing differential processing based on the index of the child being processed. For example, in converting the tree form of a non-static Java method call (assume that the first child is the referent upon which the method is called) into a source code representation, one might need to output a ".methodName(" after the first child has been processed but before all other children are processed.
This is generally useful in any case where processing needs to occur between the processing of any two children.
state
- Provides tree processing state including which node is being
processed and the current status of the tree processing.index
- The 0-based index of the child which is about to be processed.void ascent(WalkState state)
walk(com.goldencode.trpl.WalkState)
AND
after all of the last child node's children are processed. This
never occurs for nodes that have no children.
At the time this is called, the parent node will be the current node.
This is very useful for implementing scope-aware data structures (such as a stack). Scopes are normally popped (deleted) on ascent.
In code that converts a tree to a human readable form, these hooks are highly useful for closing processing after all children are processed. For example, in converting the tree form of a function call (assume that the children each represent a function call parameter) into a source code version, one might need to output a closing ")" after all parameters are emitted.
state
- Provides tree processing state including which node is being
processed and the current status of the tree processing.void post(WalkState state)
This is useful for cleanup or termination processing. For example, this is the common location for clearing or saving any values or state that should be handled once per tree.
state
- Provides tree processing state including which node is being
processed and the current status of the tree processing.TreeWalker duplicate()