class Gullah::Node
a node in an AST
Attributes
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.
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.
The children of this node, if any, as an array.
The parent node of this node, if any.
A concise stringification of the structure of this node's subtree.
Public Instance Methods
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
Is this node one that cannot be the child of another node?
# File lib/gullah/node.rb, line 88 def boundary? false end
Does this node contain the given text offset?
# File lib/gullah/node.rb, line 208 def contains?(offset) start <= offset && offset < self.end end
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
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
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
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
Does this node have some failed test?
# File lib/gullah/node.rb, line 112 def error? @failed_test end
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
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
Is this node the first of its parent's children?
# File lib/gullah/node.rb, line 304 def first_child? sibling_index.zero? end
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
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
Was this node created by an ignore
rule?
# File lib/gullah/node.rb, line 125 def ignorable? @leaf && rule.ignorable end
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
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
The immediately following sibling to this node.
# File lib/gullah/node.rb, line 318 def later_sibling parent && parent.children[sibling_index + 1] end
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
Is this a leaf node?
# File lib/gullah/node.rb, line 94 def leaf? @leaf end
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
The name of the rule that created this node.
# File lib/gullah/node.rb, line 76 def name rule.name end
Is this a node that has other nodes as children?
# File lib/gullah/node.rb, line 137 def nonterminal? !@leaf end
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
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
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
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
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
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
Does this node have any parent? If not, it is a root.
# File lib/gullah/node.rb, line 247 def root? parent.nil? end
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
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
Was this node created by something other than an ignore
rule?
# File lib/gullah/node.rb, line 131 def significant? !ignorable? end
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
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
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
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
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
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
Does this node represent a character sequence no leaf rule matched?
# File lib/gullah/node.rb, line 82 def trash? false end