Module: Parsby::Tree

Included in:
ParsedRange
Defined in:
lib/parsby.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#childrenObject



131
132
133
# File 'lib/parsby.rb', line 131

def children
  @children ||= []
end

#markersObject (readonly)

Returns the value of attribute markers.



120
121
122
# File 'lib/parsby.rb', line 120

def markers
  @markers
end

#parentObject

Returns the value of attribute parent.



119
120
121
# File 'lib/parsby.rb', line 119

def parent
  @parent
end

Instance Method Details

#<<(*ts) ⇒ Object



135
136
137
138
139
140
# File 'lib/parsby.rb', line 135

def <<(*ts)
  ts.each do |t|
    t.parent = self
    children << t
  end
end

#dup(currently_descending: false) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/parsby.rb', line 186

def dup(currently_descending: false)
  self_path = path
  if parent && !currently_descending
    root.dup.get self_path
  else
    super().tap do |d|
      d.children = d.children.map do |c|
        c.dup(currently_descending: true).tap do |dc|
          dc.parent = d
        end
      end
    end
  end
end

#each(&b) ⇒ Object



168
169
170
171
172
# File 'lib/parsby.rb', line 168

def each(&b)
  b.call self
  children.each {|c| c.each(&b) }
  self
end

#flattenObject Also known as: self_and_descendants



158
159
160
# File 'lib/parsby.rb', line 158

def flatten
  [self, *children.map(&:flatten).flatten]
end

#get(path) ⇒ Object



255
256
257
258
259
260
# File 'lib/parsby.rb', line 255

def get(path)
  return self if path.empty?
  idx, *sub_path = path
  child = children[idx]
  child&.get sub_path
end

#pathObject



164
165
166
# File 'lib/parsby.rb', line 164

def path
  [*parent&.path, *sibling_index]
end

#right_tree_sliceObject



182
183
184
# File 'lib/parsby.rb', line 182

def right_tree_slice
  "*" + "|" * right_uncles
end

#right_unclesObject



174
175
176
177
178
179
180
# File 'lib/parsby.rb', line 174

def right_uncles
  if parent
    sibling_reverse_index + parent.right_uncles
  else
    0
  end
end

#rootObject



142
143
144
145
146
147
148
# File 'lib/parsby.rb', line 142

def root
  if parent == nil
    self 
  else
    parent.root
  end
end

#select(&b) ⇒ Object



238
239
240
241
242
243
244
245
246
# File 'lib/parsby.rb', line 238

def select(&b)
  r = []
  each do |n|
    if b.call n
      r << n
    end
  end
  r
end

#select_paths(&b) ⇒ Object



248
249
250
251
252
253
# File 'lib/parsby.rb', line 248

def select_paths(&b)
  root_path = path
  select(&b).map do |n|
    n.path.drop root_path.length
  end
end

#self_and_ancestorsObject



262
263
264
# File 'lib/parsby.rb', line 262

def self_and_ancestors
  [self, *parent&.self_and_ancestors]
end

#sibling_indexObject



154
155
156
# File 'lib/parsby.rb', line 154

def sibling_index
  parent&.children&.index self
end

#sibling_reverse_indexObject



150
151
152
# File 'lib/parsby.rb', line 150

def sibling_reverse_index
  parent&.children&.reverse&.index self
end

#splice(*paths) ⇒ Object



215
216
217
# File 'lib/parsby.rb', line 215

def splice(*paths)
  dup.splice!(*paths)
end

#splice!(*paths) ⇒ Object



208
209
210
211
212
213
# File 'lib/parsby.rb', line 208

def splice!(*paths)
  self.children = paths
    .map {|p| get(p)&.tap {|d| d.parent = self } }
    .reject(&:nil?)
  self
end

#splice_self!Object



201
202
203
204
205
206
# File 'lib/parsby.rb', line 201

def splice_self!
  idx = sibling_index
  parent.children.delete_at(idx)
  parent.children.insert(idx, *children.each {|c| c.parent = parent })
  parent
end

#splice_to!(marker) ⇒ Object



127
128
129
# File 'lib/parsby.rb', line 127

def splice_to!(marker)
  splice!(*select_paths {|n| n.markers.include? marker })
end

#trim_to_just!(*paths, &rejecting) ⇒ Object



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/parsby.rb', line 219

def trim_to_just!(*paths, &rejecting)
  max_sibling = paths.map(&:first).reject(&:nil?).max
  self.children = if max_sibling.nil?
    []
  else
    children[0..max_sibling]
      .map.with_index {|c, i| [c, i] }
      .reject {|(c, i)| rejecting.call c, i, max_sibling if rejecting }
      .each do |(child, i)|
        subpaths = paths
          .select {|p| p.first == i}
          .map {|p| p.drop 1 }
        child.trim_to_just!(*subpaths, &rejecting)
      end
      .map(&:first)
  end
  self
end