Class: Astrolabe::Node

Inherits:
Parser::AST::Node
  • Object
show all
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.

Examples:

node.send_type?    # Equivalent to: `node.type == :send`
node.op_asgn_type? # Equivalent to: `node.type == :op_asgn`

# Non-word characters (other than a-zA-Z0-9_) in type names are omitted.
node.defined_type? # Equivalent to: `node.type == :defined?`

# Collect all lvar nodes under the receiver node.
lvar_nodes = node.each_descendant.select(&:lvar_type?)

Instance Method Summary collapse

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.

Yield Parameters:

  • node (Node)

    each ancestor node

Returns:

  • (self)

    if a block is given

  • (Enumerator)

    if no block is given



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.

Yield Parameters:

  • node (Node)

    each child node

Returns:

  • (self)

    if a block is given

  • (Enumerator)

    if no block is given



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.

Yield Parameters:

  • node (Node)

    each descendant node

Returns:

  • (self)

    if a block is given

  • (Enumerator)

    if no block is given



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.

Yield Parameters:

  • node (Node)

    each node

Returns:

  • (self)

    if a block is given

  • (Enumerator)

    if no block is given



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

#parentNode?

Returns the parent node, or nil if the receiver is a root node.

Returns:

  • (Node, nil)

    the parent node or nil



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.

Returns:

  • (Boolean)

    whether the receiver is a root node or not



62
63
64
# File 'lib/astrolabe/node.rb', line 62

def root?
  parent.nil?
end