Class: Peggy::Node

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/parse/ast.rb

Overview

A node in an Abstract Syntax Tree. Every node in the tree maps to a production found in the parse. You can navigate to the node’s parent, first child, or next sibling. Nodes know their range of the source text.

Direct Known Subclasses

AST

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Node

Constructor



21
22
23
# File 'lib/parse/ast.rb', line 21

def initialize name
  self._name = name
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object



151
152
153
# File 'lib/parse/ast.rb', line 151

def method_missing name, *args
  find {|node| name == node._name}
end

Instance Attribute Details

#_firstObject

Returns the value of attribute _first.



18
19
20
# File 'lib/parse/ast.rb', line 18

def _first
  @_first
end

#_nameObject

Returns the value of attribute _name.



18
19
20
# File 'lib/parse/ast.rb', line 18

def _name
  @_name
end

#_nextObject

Returns the value of attribute _next.



18
19
20
# File 'lib/parse/ast.rb', line 18

def _next
  @_next
end

#_parentObject

Returns the value of attribute _parent.



18
19
20
# File 'lib/parse/ast.rb', line 18

def _parent
  @_parent
end

#_rangeObject

Returns the value of attribute _range.



18
19
20
# File 'lib/parse/ast.rb', line 18

def _range
  @_range
end

#_sourceObject

Returns the value of attribute _source.



18
19
20
# File 'lib/parse/ast.rb', line 18

def _source
  @_source
end

Instance Method Details

#<<(child) ⇒ Object

Add a child.



26
27
28
29
30
31
32
33
34
# File 'lib/parse/ast.rb', line 26

def << child
  child._parent = self
#puts "#{_name}[first #{_first} last #{_last}] << child #{child._name}"
  if _first
    _last._next = child
  else
    self._first = child
  end
end

#[](name) ⇒ Object

Get the first node of the given name as a Symbol.



147
148
149
# File 'lib/parse/ast.rb', line 147

def [] name
  method_missing name.to_sym
end

#_count(name = nil) ⇒ Object

Count the children. If name is supplied only nodes matching the name are counted.



54
55
56
57
58
59
60
# File 'lib/parse/ast.rb', line 54

def _count name=nil
  c = 0
  each do |node|
    c += 1 if name.nil? || name == node._name
  end
  c
end

#_depthObject

Get the number of nodes up to the root.



63
64
65
66
67
68
# File 'lib/parse/ast.rb', line 63

def _depth
  depth = 0
  node = self
  depth += 1 while node=node._parent
  depth
end

#_formatObject

Format the node pretty printing.



99
100
101
102
103
104
105
# File 'lib/parse/ast.rb', line 99

def _format
  result = "#{'  '*_depth}#{_name} #{_sample}\n"
  each do |node|
    result << node._format
  end
  result
end

#_lastObject

Get the last child.



108
109
110
111
112
113
114
115
# File 'lib/parse/ast.rb', line 108

def _last
  node = _first
  return nil unless node
  while (n2 = node._next)
    node = n2
  end
  node
end

#_lengthObject

Get the length of the range.



87
88
89
# File 'lib/parse/ast.rb', line 87

def _length
  _range.last - _range.first
end

#_option(option, default = nil) ⇒ Object

Get an option set when tree was created.



80
81
82
83
84
# File 'lib/parse/ast.rb', line 80

def _option option, default=nil
  options = _root._options
  return nil unless options
  options[option] || options[option.to_sym] || default
end

#_rootObject

Get the root node.



71
72
73
74
75
76
77
# File 'lib/parse/ast.rb', line 71

def _root
  node = self
  while (n2 = node._parent)
    node = n2
  end
  node
end

#_sampleObject

Get some or all of the source text covered by this node, depending on the length.



92
93
94
95
96
# File 'lib/parse/ast.rb', line 92

def _sample
  return nil if _length == 0
  str = _source[_range]
  (str.length >= 40 ? str[0, 37] + '...' : str).inspect
end

#_stripObject

Get the source text minus any ignored nodes.



123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/parse/ast.rb', line 123

def _strip
  return @str if @str
  str0 = str = _source[_range]
  return @str = str unless (ignore = _option :ignore) && _first
  remove = find_all{|node| node._name == ignore}
  remove.reverse_each do |node|
    from = node._range.first - _range.first
    str = str[0, from] + str[from + node._length..-1]
  end
# puts "before #{str0.inspect}, after #{str.inspect}" unless remove.empty?
  @str = str
end

#children(name = nil) ⇒ Object



45
46
47
48
49
50
51
# File 'lib/parse/ast.rb', line 45

def children name=nil
  a = []
  each(name) do |node|
    a << node
  end
  a
end

#each(name = nil) ⇒ Object

Iterate over each child. If name is supplied only nodes matching the name are iterated.



37
38
39
40
41
42
43
# File 'lib/parse/ast.rb', line 37

def each name=nil
  child = _first
  while child
    yield child if name.nil? || name == child._name
    child = child._next
  end
end

#inspectObject

Get the contents for inspection.



118
119
120
# File 'lib/parse/ast.rb', line 118

def inspect
  "#{_name ? _name : self.class}[#{_range}] #{to_s.inspect}"
end

#to_sObject

Get the source text covered by this node.



137
138
139
# File 'lib/parse/ast.rb', line 137

def to_s
  _source[_range]
end

#to_symObject

Get the stripped text as a Symbol.



142
143
144
# File 'lib/parse/ast.rb', line 142

def to_sym
  _strip.to_sym
end