class Gullah::Node

a node in an AST

Attributes

attributes[R]

A hash of attributes, including indicators of tests that passed or failed. The atts alias of attributes exists for when a more telegraphic coding style is useful.

atts[R]

A hash of attributes, including indicators of tests that passed or failed. The atts alias of attributes exists for when a more telegraphic coding style is useful.

children[R]

The children of this node, if any, as an array.

parent[R]

The parent node of this node, if any.

summary[R]

A concise stringification of the structure of this node's subtree.

Public Instance Methods

ancestors() click to toggle source

Returns an Enumerable enumerating the nodes immediately above this node in the tree: its parent, its parent's parent, etc.

# File lib/gullah/node.rb, line 254
def ancestors
  _ancestors self
end
boundary?() click to toggle source

Is this node one that cannot be the child of another node?

# File lib/gullah/node.rb, line 88
def boundary?
  false
end
contains?(offset) click to toggle source

Does this node contain the given text offset?

# File lib/gullah/node.rb, line 208
def contains?(offset)
  start <= offset && offset < self.end
end
dbg(so: false) click to toggle source

Produces a simplified representation of the node to facilitate debugging. The so named parameter, if true, will cause the representation to drop ignored nodes. The name “so” stands for “significant only”.

> pp root.dbg

{:name=>:S,
 :pos=>{:start=>0, :end=>11, :depth=>0},
 :children=>
  [{:name=>:NP,
    :pos=>{:start=>0, :end=>7, :depth=>1},
    :children=>
     [{:name=>:D, :pos=>{:start=>0, :end=>3, :depth=>2}, :text=>"the"},
      {:name=>:_ws,
       :pos=>{:start=>3, :end=>4, :depth=>2},
       :ignorable=>true,
       :text=>" "},
      {:name=>:N, :pos=>{:start=>4, :end=>7, :depth=>2}, :text=>"cat"}]},
   {:name=>:_ws,
    :pos=>{:start=>7, :end=>8, :depth=>1},
    :ignorable=>true,
    :text=>" "},
   {:name=>:VP,
    :pos=>{:start=>8, :end=>11, :depth=>1},
    :children=>
     [{:name=>:V, :pos=>{:start=>8, :end=>11, :depth=>2}, :text=>"sat"}]}]}

> pp root.dbg so: true

{:name=>:S,
 :pos=>{:start=>0, :end=>11, :depth=>0},
 :children=>
  [{:name=>:NP,
    :pos=>{:start=>0, :end=>7, :depth=>1},
    :children=>
     [{:name=>:D, :pos=>{:start=>0, :end=>3, :depth=>2}, :text=>"the"},
      {:name=>:_ws, :pos=>{:start=>3, :end=>4, :depth=>2}, :text=>" "},
      {:name=>:N, :pos=>{:start=>4, :end=>7, :depth=>2}, :text=>"cat"}]},
   {:name=>:_ws, :pos=>{:start=>7, :end=>8, :depth=>1}, :text=>" "},
   {:name=>:VP,
    :pos=>{:start=>8, :end=>11, :depth=>1},
    :children=>
     [{:name=>:V, :pos=>{:start=>8, :end=>11, :depth=>2}, :text=>"sat"}]}]}
# File lib/gullah/node.rb, line 399
def dbg(so: false)
  {
    name: name,
    pos: {
      start: start,
      end: self.end,
      depth: depth
    }
  }.tap do |simpleton|
    simpleton[:failed] = true if @failed_test
    simpleton[:attributes] = deep_clone attributes if attributes.any?
    if leaf?
      simpleton[:trash] = true if trash?
      simpleton[:ignorable] = true unless so || significant?
      simpleton[:text] = text
    else
      simpleton[:children] = children.map { |c| c.dbg so: so }
    end
  end
end
depth() click to toggle source

Distance of the node from the root node of the parse tree. During parsing, while nodes are being added, this distance may change, unlike the height.

The root node has a depth of 0. It's children have a depth of 1. Their children have a depth of 2. And so forth.

# File lib/gullah/node.rb, line 187
def depth
  parent ? 1 + parent.depth : 0
end
descendants() click to toggle source

Returns an Enumerable over the descendants of this node: its children, its children's children, etc. This enumeration is depth-first.

# File lib/gullah/node.rb, line 261
def descendants
  _descendants self
end
end() click to toggle source

The node's end text offset. For a non-terminal node, this will be the same as the end of the last leaf node of its subtree.

# File lib/gullah/node.rb, line 176
def end
  @end ||= @children[-1].end
end
error?() click to toggle source

Does this node have some failed test?

# File lib/gullah/node.rb, line 112
def error?
  @failed_test
end
failed?() click to toggle source

Does this node have some failed test or does it represent characters no leaf rule mached?

# File lib/gullah/node.rb, line 100
def failed?
  trash? || error?
end
find(pos) click to toggle source

Finds the node at the given position within this node's subtree.

# File lib/gullah/node.rb, line 214
def find(pos)
  offset = pos.first
  return nil unless contains?(offset)

  return self if pos == position

  if (child = children&.find { |c| c.contains? offset })
    child.find(pos)
  end
end
first_child?() click to toggle source

Is this node the first of its parent's children?

# File lib/gullah/node.rb, line 304
def first_child?
  sibling_index.zero?
end
full_text() click to toggle source

A reference to the full text the node's text is embedded in.

# File lib/gullah/node.rb, line 150
def full_text
  @text
end
height() click to toggle source

The distance of a node from the first leaf node in its subtree. If the node is the immediate parent of this leaf, its distance will be one. Leaves have a height of zero.

# File lib/gullah/node.rb, line 195
def height
  @height ||= @leaf ? 0 : 1 + children[0].height
end
ignorable?() click to toggle source

Was this node created by an ignore rule?

# File lib/gullah/node.rb, line 125
def ignorable?
  @leaf && rule.ignorable
end
last_child?() click to toggle source

Is this node the last of its parent's children?

# File lib/gullah/node.rb, line 298
def last_child?
  parent && sibling_index == parent.children.length - 1
end
later() click to toggle source

The collection of nodes in the subtree containing this node whose start offset is at or after its end offset.

# File lib/gullah/node.rb, line 339
def later
  root.descendants.select { |n| n.start >= self.end }
end
later_sibling() click to toggle source

The immediately following sibling to this node.

# File lib/gullah/node.rb, line 318
def later_sibling
  parent && parent.children[sibling_index + 1]
end
later_siblings() click to toggle source

Returns the children of this node's parent that follow it.

# File lib/gullah/node.rb, line 292
def later_siblings
  parent && siblings[(sibling_index + 1)..]
end
leaf?() click to toggle source

Is this a leaf node?

# File lib/gullah/node.rb, line 94
def leaf?
  @leaf
end
leaves() click to toggle source

The leaves of this node's subtree. If the node is a leaf, this returns a single-member array containing the node itself.

# File lib/gullah/node.rb, line 325
def leaves
  @leaf ? [self] : descendants.select(&:leaf?)
end
name() click to toggle source

The name of the rule that created this node.

# File lib/gullah/node.rb, line 76
def name
  rule.name
end
nonterminal?() click to toggle source

Is this a node that has other nodes as children?

# File lib/gullah/node.rb, line 137
def nonterminal?
  !@leaf
end
pending_tests?() click to toggle source

Does this node's subtree contain unsatisfied syntactic requirements? These are tests that depend on nodes not in the node's own subtree.

# File lib/gullah/node.rb, line 119
def pending_tests?
  !!attributes[:pending]
end
position() click to toggle source

A pair consisting of the nodes start and height. This will be a unique identifier for the node in its parse and is constant at all stages of parsing.

# File lib/gullah/node.rb, line 202
def position
  @position ||= [start, height]
end
prior() click to toggle source

The collection of nodes in the subtree containing this node that do not contain the node and whose start offset precedes its start offset.

# File lib/gullah/node.rb, line 332
def prior
  root.descendants.reject { |n| n.contains? start }.select { |n| n.start < start }
end
prior_sibling() click to toggle source

The immediately prior sibling to this node.

# File lib/gullah/node.rb, line 310
def prior_sibling
  if parent
    first_child? ? nil : parent.children[sibling_index - 1]
  end
end
prior_siblings() click to toggle source

Returns the children of this node's parent that precede it.

# File lib/gullah/node.rb, line 286
def prior_siblings
  parent && siblings[0...sibling_index]
end
root() click to toggle source

The root of this node's current parse tree.

Note, if you use this in a node test the root will always be the same as the node itself because these tests are run when the node is being added to the tree. If you use it in structure tests, it will be some ancestor of the node but not necessarily the final root. The current root is always the first argument to structure tests. Using this argument is more efficient than using the root method. Really, the root method is only useful in completed parses.

# File lib/gullah/node.rb, line 241
def root
  parent ? parent.root : self
end
root?() click to toggle source

Does this node have any parent? If not, it is a root.

# File lib/gullah/node.rb, line 247
def root?
  parent.nil?
end
sibling_index() click to toggle source

The index of this node among its parent's children.

# File lib/gullah/node.rb, line 280
def sibling_index
  @sibling_index ||= parent.children.index self if parent
end
siblings() click to toggle source

Returns the children of this node's parent's children minus this node itself.

# File lib/gullah/node.rb, line 274
def siblings
  parent&.children&.reject { |n| n == self }
end
significant?() click to toggle source

Was this node created by something other than an ignore rule?

# File lib/gullah/node.rb, line 131
def significant?
  !ignorable?
end
size() click to toggle source

The number of nodes in this node's subtree. Leaves always have a size of 1.

# File lib/gullah/node.rb, line 227
def size
  @size ||= @leaf ? 1 : @children.map(&:size).sum + 1
end
start() click to toggle source

The node's start text offset. For a non-terminal node, this will be the same as the start of the first leaf node of its subtree.

# File lib/gullah/node.rb, line 169
def start
  @start ||= @children[0].start
end
subtree() click to toggle source

Returns an Enumerable over this node and its descendants. The node itself is the first node returned.

# File lib/gullah/node.rb, line 268
def subtree
  _descendants nil
end
text() click to toggle source

The portion of the original text covered by this node. This is in effect the text of the leaves of its subtree.

# File lib/gullah/node.rb, line 144
def text
  @text[start...self.end]
end
text_after() click to toggle source

The text following this node's text. Useful for lookaround tests and preconditions.

# File lib/gullah/node.rb, line 162
def text_after
  @text[self.end..]
end
text_before() click to toggle source

The text preceding this node's text. Useful for lookaround tests and preconditions.

# File lib/gullah/node.rb, line 156
def text_before
  @text[0...start]
end
trash?() click to toggle source

Does this node represent a character sequence no leaf rule matched?

# File lib/gullah/node.rb, line 82
def trash?
  false
end