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.
286 287 288 289 |
# File 'lib/tree_haver/backends/citrus.rb', line 286 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.
284 285 286 |
# File 'lib/tree_haver/backends/citrus.rb', line 284 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.
284 285 286 |
# File 'lib/tree_haver/backends/citrus.rb', line 284 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.
451 452 453 454 455 456 |
# File 'lib/tree_haver/backends/citrus.rb', line 451 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.
447 448 449 |
# File 'lib/tree_haver/backends/citrus.rb', line 447 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.
458 459 460 461 |
# File 'lib/tree_haver/backends/citrus.rb', line 458 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.
463 464 465 466 |
# File 'lib/tree_haver/backends/citrus.rb', line 463 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.
395 396 397 |
# File 'lib/tree_haver/backends/citrus.rb', line 395 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
417 418 419 |
# File 'lib/tree_haver/backends/citrus.rb', line 417 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.
403 404 405 |
# File 'lib/tree_haver/backends/citrus.rb', line 403 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
439 440 441 |
# File 'lib/tree_haver/backends/citrus.rb', line 439 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.
468 469 470 |
# File 'lib/tree_haver/backends/citrus.rb', line 468 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.
472 473 474 |
# File 'lib/tree_haver/backends/citrus.rb', line 472 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.
476 477 478 |
# File 'lib/tree_haver/backends/citrus.rb', line 476 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.
427 428 429 430 431 432 433 434 |
# File 'lib/tree_haver/backends/citrus.rb', line 427 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.
391 392 393 |
# File 'lib/tree_haver/backends/citrus.rb', line 391 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
410 411 412 |
# File 'lib/tree_haver/backends/citrus.rb', line 410 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.
399 400 401 |
# File 'lib/tree_haver/backends/citrus.rb', line 399 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).
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/tree_haver/backends/citrus.rb', line 317 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.
443 444 445 |
# File 'lib/tree_haver/backends/citrus.rb', line 443 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
302 303 304 305 306 307 308 |
# File 'lib/tree_haver/backends/citrus.rb', line 302 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 |