The SyntaxTree::Visitor class implements the double dispatch visitor pattern, allowing you to operate on specific nodes without manually walking the entire tree. You define visit_* methods for the node types you are interested in.
When you define a handler for a node, you must decide how to continue the descent:
- Call
super to visit all child nodes using default behavior. - Call
visit_child_nodes manually. - Call
visit(child) for specific children. - Call nothing if you want to stop descending into that branch.
By default, SyntaxTree::Visitor walks the entire tree even if you don't define handlers for every node type.
class ArithmeticVisitor < SyntaxTree::Visitor
def visit_binary(node)
if node in { left: SyntaxTree::Int, operator: :+ | :- | :* | :/, right: SyntaxTree::Int }
puts "The result is: #{node.left.value.to_i.public_send(node.operator, node.right.value.to_i)}"
end
end
end
visitor = ArithmeticVisitor.new
visitor.visit(SyntaxTree.parse("1 + 1"))
# The result is: 2