Nasty.Utils.Traversal (Nasty v0.3.0)
View SourceAST traversal utilities using the visitor pattern.
This module provides flexible tree traversal for AST nodes, supporting both depth-first and breadth-first traversal strategies.
Visitor Pattern
The visitor pattern allows you to define custom behavior for each node type without modifying the node modules themselves.
Examples
# Collect all tokens
iex> visitor = fn
...> %Nasty.AST.Token{} = token, acc -> {:cont, [token | acc]}
...> _node, acc -> {:cont, acc}
...> end
iex> Nasty.Utils.Traversal.walk(document, [], visitor)
[token1, token2, ...]
# Find first noun
iex> visitor = fn
...> %Nasty.AST.Token{pos_tag: :noun} = token, _acc -> {:halt, token}
...> _node, acc -> {:cont, acc}
...> end
iex> Nasty.Utils.Traversal.walk(document, nil, visitor)
%Nasty.AST.Token{text: "cat", ...}
Summary
Types
Visitor function that processes nodes during traversal.
Functions
Collects all nodes matching a predicate.
Finds the first node matching a predicate.
Maps a function over all nodes, returning a transformed tree.
Reduces the AST to a single value.
Walks the AST using depth-first pre-order traversal.
Performs breadth-first traversal of the AST.
Walks the AST using depth-first post-order traversal.
Types
Visitor function that processes nodes during traversal.
The function receives the current node and an accumulator, and returns:
{:cont, new_acc}- Continue traversal with updated accumulator{:halt, result}- Stop traversal and return result{:skip, new_acc}- Skip children of this node but continue traversal
Functions
Collects all nodes matching a predicate.
Examples
iex> is_noun? = fn
...> %Nasty.AST.Token{pos_tag: :noun} -> true
...> _ -> false
...> end
iex> Nasty.Utils.Traversal.collect(document, is_noun?)
[token1, token2, ...]
Finds the first node matching a predicate.
Returns nil if no matching node is found.
Examples
iex> Nasty.Utils.Traversal.find(document, &match?(%Nasty.AST.Token{pos_tag: :verb}, &1))
%Nasty.AST.Token{text: "runs", pos_tag: :verb, ...}
Maps a function over all nodes, returning a transformed tree.
Examples
iex> lowercase = fn
...> %Nasty.AST.Token{} = token -> %{token | text: String.downcase(token.text)}
...> node -> node
...> end
iex> Nasty.Utils.Traversal.map(document, lowercase)
%Nasty.AST.Document{...}
Reduces the AST to a single value.
Similar to Enum.reduce/3 but for tree structures.
Examples
iex> count = fn _node, acc -> acc + 1 end
iex> Nasty.Utils.Traversal.reduce(document, 0, count)
127 # Total number of nodes
Walks the AST using depth-first pre-order traversal.
Visits parent nodes before their children.
Examples
iex> count_tokens = fn
...> %Nasty.AST.Token{}, acc -> {:cont, acc + 1}
...> _node, acc -> {:cont, acc}
...> end
iex> Nasty.Utils.Traversal.walk(document, 0, count_tokens)
42
Performs breadth-first traversal of the AST.
Visits all nodes at depth N before visiting nodes at depth N+1.
Examples
iex> visitor = fn node, acc -> {:cont, [node | acc]} end
iex> nodes = Nasty.Utils.Traversal.walk_breadth(document, [], visitor)
iex> Enum.reverse(nodes)
[document, paragraph1, paragraph2, sentence1, sentence2, ...]
Walks the AST using depth-first post-order traversal.
Visits children before their parent nodes.
Examples
iex> collect_depths = fn
...> %Nasty.AST.Token{}, depth -> {:cont, [depth]}
...> _node, depths -> {:cont, depths}
...> end
iex> Nasty.Utils.Traversal.walk_post(document, 0, collect_depths)
[3, 3, 2, 3, 3, 2, 1, ...]