Class: TreeHaver::Backends::Citrus::Node Private
- Inherits:
-
Object
- Object
- TreeHaver::Backends::Citrus::Node
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/tree_haver/backends/citrus.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Citrus node wrapper
Wraps Citrus::Match objects to provide tree-sitter-compatible node API.
Citrus::Match provides:
-
events: rule name (Symbol) - used as type
-
offset: byte position
-
length: byte length
-
string: matched text
-
matches: child matches
-
captures: named groups
Language-specific helpers can be mixed in for convenience:
require "tree_haver/backends/citrus/toml_helpers"
TreeHaver::Backends::Citrus::Node.include(TreeHaver::Backends::Citrus::TomlHelpers)
Instance Attribute Summary collapse
- #match ⇒ Object readonly private
- #source ⇒ Object readonly private
Instance Method Summary collapse
- #child(index) ⇒ Object private
- #child_count ⇒ Object private
- #children ⇒ Object private
- #each(&block) ⇒ Object private
- #end_byte ⇒ Object private
-
#end_line ⇒ Integer
private
Get the 1-based line number where this node ends.
- #end_point ⇒ Object private
-
#first_child ⇒ Node?
private
Get the first child node.
- #has_error? ⇒ Boolean private
-
#initialize(match, source) ⇒ Node
constructor
private
A new instance of Node.
- #missing? ⇒ Boolean private
- #named? ⇒ Boolean private
-
#source_position ⇒ Hash{Symbol => Integer}
private
Get position information as a hash.
- #start_byte ⇒ Object private
-
#start_line ⇒ Integer
private
Get the 1-based line number where this node starts.
- #start_point ⇒ Object private
-
#structural? ⇒ Boolean
private
Check if this node represents a structural element vs a terminal/token.
- #text ⇒ Object private
-
#type ⇒ String
private
Get node type from Citrus rule name.
Constructor Details
#initialize(match, source) ⇒ Node
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Node.
257 258 259 260 |
# File 'lib/tree_haver/backends/citrus.rb', line 257 def initialize(match, source) @match = match @source = source end |
Instance Attribute Details
#match ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
255 256 257 |
# File 'lib/tree_haver/backends/citrus.rb', line 255 def match @match end |
#source ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
255 256 257 |
# File 'lib/tree_haver/backends/citrus.rb', line 255 def source @source end |
Instance Method Details
#child(index) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
422 423 424 425 426 427 |
# File 'lib/tree_haver/backends/citrus.rb', line 422 def child(index) return unless @match.respond_to?(:matches) return if index >= @match.matches.size Node.new(@match.matches[index], @source) end |
#child_count ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
418 419 420 |
# File 'lib/tree_haver/backends/citrus.rb', line 418 def child_count @match.respond_to?(:matches) ? @match.matches.size : 0 end |
#children ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
429 430 431 432 |
# File 'lib/tree_haver/backends/citrus.rb', line 429 def children return [] unless @match.respond_to?(:matches) @match.matches.map { |m| Node.new(m, @source) } end |
#each(&block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
434 435 436 437 |
# File 'lib/tree_haver/backends/citrus.rb', line 434 def each(&block) return to_enum(__method__) unless block_given? children.each(&block) end |
#end_byte ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
366 367 368 |
# File 'lib/tree_haver/backends/citrus.rb', line 366 def end_byte @match.offset + @match.length end |
#end_line ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the 1-based line number where this node ends
388 389 390 |
# File 'lib/tree_haver/backends/citrus.rb', line 388 def end_line end_point[:row] + 1 end |
#end_point ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
374 375 376 |
# File 'lib/tree_haver/backends/citrus.rb', line 374 def end_point calculate_point(@match.offset + @match.length) end |
#first_child ⇒ Node?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the first child node
410 411 412 |
# File 'lib/tree_haver/backends/citrus.rb', line 410 def first_child child(0) end |
#has_error? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
439 440 441 |
# File 'lib/tree_haver/backends/citrus.rb', line 439 def has_error? false # Citrus raises on parse error, so successful parse has no errors end |
#missing? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
443 444 445 |
# File 'lib/tree_haver/backends/citrus.rb', line 443 def missing? false # Citrus doesn't have the concept of missing nodes end |
#named? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
447 448 449 |
# File 'lib/tree_haver/backends/citrus.rb', line 447 def named? true # Citrus matches are typically "named" in tree-sitter terminology end |
#source_position ⇒ Hash{Symbol => Integer}
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get position information as a hash
Returns a hash with 1-based line numbers and 0-based columns. Compatible with *-merge gems’ FileAnalysisBase.
398 399 400 401 402 403 404 405 |
# File 'lib/tree_haver/backends/citrus.rb', line 398 def source_position { start_line: start_line, end_line: end_line, start_column: start_point[:column], end_column: end_point[:column], } end |
#start_byte ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
362 363 364 |
# File 'lib/tree_haver/backends/citrus.rb', line 362 def start_byte @match.offset end |
#start_line ⇒ Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get the 1-based line number where this node starts
381 382 383 |
# File 'lib/tree_haver/backends/citrus.rb', line 381 def start_line start_point[:row] + 1 end |
#start_point ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
370 371 372 |
# File 'lib/tree_haver/backends/citrus.rb', line 370 def start_point calculate_point(@match.offset) end |
#structural? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if this node represents a structural element vs a terminal/token
Uses Citrus grammar’s terminal? method to determine if this is a structural rule (like “table”, “keyvalue”) vs a terminal token (like “[”, “=”, whitespace).
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/tree_haver/backends/citrus.rb', line 288 def structural? return false unless @match.respond_to?(:events) return false if @match.events.empty? first_event = @match.events.first # Check if event has terminal? method (Citrus rule object) if first_event.respond_to?(:terminal?) return !first_event.terminal? end # For Symbol events, try to look up in grammar if first_event.is_a?(Symbol) && @match.respond_to?(:grammar) grammar = @match.grammar if grammar.respond_to?(:rules) && grammar.rules.key?(first_event) rule = grammar.rules[first_event] return !rule.terminal? if rule.respond_to?(:terminal?) end end # Default: assume structural if not a simple string/regex terminal true end |
#text ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
414 415 416 |
# File 'lib/tree_haver/backends/citrus.rb', line 414 def text @match.string end |
#type ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Get node type from Citrus rule name
Uses Citrus grammar introspection to dynamically determine node types. Works with any Citrus grammar without language-specific knowledge.
Strategy:
-
Check if first event has a .name method (returns Symbol) - use that
-
If first event is a Symbol directly - use that
-
For compound rules (Repeat, Choice), recurse into first match
273 274 275 276 277 278 279 |
# File 'lib/tree_haver/backends/citrus.rb', line 273 def type return "unknown" unless @match.respond_to?(:events) return "unknown" unless @match.events.is_a?(Array) return "unknown" if @match.events.empty? extract_type_from_event(@match.events.first) end |