Class: Astrolabe::Node
- Inherits:
-
Parser::AST::Node
- Object
- Parser::AST::Node
- Astrolabe::Node
- Defined in:
- lib/astrolabe/node.rb
Overview
Astrolabe::Node
is a subclass of Parser::AST::Node
. It provides an access to parent node and
an object-oriented way to handle AST with the power of Enumerable
.
Though not described in the auto-generated API documentation, it has predicate methods for every
node type. These methods would be useful especially when combined with Enumerable
methods.
Instance Method Summary collapse
-
#each_ancestor {|node| ... } ⇒ self, Enumerator
Calls the given block for each ancestor node in the order from parent to root.
-
#each_child_node {|node| ... } ⇒ self, Enumerator
Calls the given block for each child node.
-
#each_descendant {|node| ... } ⇒ self, Enumerator
Calls the given block for each descendant node with depth first order.
-
#each_node {|node| ... } ⇒ self, Enumerator
Calls the given block for the receiver and each descendant node with depth first order.
-
#initialize(type, children = [], properties = {}) ⇒ Node
constructor
A new instance of Node.
-
#parent ⇒ Node?
Returns the parent node, or
nil
if the receiver is a root node. -
#root? ⇒ Boolean
Returns whether the receiver is a root node or not.
Constructor Details
#initialize(type, children = [], properties = {}) ⇒ Node
Returns a new instance of Node.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/astrolabe/node.rb', line 23 def initialize(type, children = [], properties = {}) @mutable_attributes = {} # ::AST::Node#initialize freezes itself. super # #parent= would be invoked multiple times for a node because there are pending nodes while # constructing AST and they are replaced later. # For example, `lvar` and `send` type nodes are initially created as an `ident` type node and # fixed to each type later. # So, the #parent attribute needs to be mutable. each_child_node do |child_node| child_node.parent = self end end |
Instance Method Details
#each_ancestor {|node| ... } ⇒ self, Enumerator
Calls the given block for each ancestor node in the order from parent to root.
If no block is given, an Enumerator
is returned.
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/astrolabe/node.rb', line 72 def each_ancestor return to_enum(__method__) unless block_given? last_node = self while (current_node = last_node.parent) yield current_node last_node = current_node end self end |
#each_child_node {|node| ... } ⇒ self, Enumerator
Calls the given block for each child node.
If no block is given, an Enumerator
is returned.
Note that this is different from node.children.each { |child| ... }
which yields all
children including non-node element.
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/astrolabe/node.rb', line 94 def each_child_node return to_enum(__method__) unless block_given? children.each do |child| next unless child.is_a?(Node) yield child end self end |
#each_descendant {|node| ... } ⇒ self, Enumerator
Calls the given block for each descendant node with depth first order.
If no block is given, an Enumerator
is returned.
111 112 113 114 115 |
# File 'lib/astrolabe/node.rb', line 111 def each_descendant(&block) return to_enum(__method__) unless block_given? visit_descendants(&block) self end |
#each_node {|node| ... } ⇒ self, Enumerator
Calls the given block for the receiver and each descendant node with depth first order.
If no block is given, an Enumerator
is returned.
This method would be useful when you treat the receiver node as a root of tree and want to iterate all nodes in the tree.
126 127 128 129 130 |
# File 'lib/astrolabe/node.rb', line 126 def each_node(&block) return to_enum(__method__) unless block_given? yield self each_descendant(&block) end |
#parent ⇒ Node?
Returns the parent node, or nil
if the receiver is a root node.
49 50 51 |
# File 'lib/astrolabe/node.rb', line 49 def parent @mutable_attributes[:parent] end |
#root? ⇒ Boolean
Returns whether the receiver is a root node or not.
62 63 64 |
# File 'lib/astrolabe/node.rb', line 62 def root? parent.nil? end |