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.
287 288 289 290 |
# File 'lib/tree_haver/backends/citrus.rb', line 287 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.
285 286 287 |
# File 'lib/tree_haver/backends/citrus.rb', line 285 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.
285 286 287 |
# File 'lib/tree_haver/backends/citrus.rb', line 285 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.
452 453 454 455 456 457 |
# File 'lib/tree_haver/backends/citrus.rb', line 452 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.
448 449 450 |
# File 'lib/tree_haver/backends/citrus.rb', line 448 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.
459 460 461 462 |
# File 'lib/tree_haver/backends/citrus.rb', line 459 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.
464 465 466 467 |
# File 'lib/tree_haver/backends/citrus.rb', line 464 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.
396 397 398 |
# File 'lib/tree_haver/backends/citrus.rb', line 396 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
418 419 420 |
# File 'lib/tree_haver/backends/citrus.rb', line 418 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.
404 405 406 |
# File 'lib/tree_haver/backends/citrus.rb', line 404 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
440 441 442 |
# File 'lib/tree_haver/backends/citrus.rb', line 440 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.
469 470 471 |
# File 'lib/tree_haver/backends/citrus.rb', line 469 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.
473 474 475 |
# File 'lib/tree_haver/backends/citrus.rb', line 473 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.
477 478 479 |
# File 'lib/tree_haver/backends/citrus.rb', line 477 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.
428 429 430 431 432 433 434 435 |
# File 'lib/tree_haver/backends/citrus.rb', line 428 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.
392 393 394 |
# File 'lib/tree_haver/backends/citrus.rb', line 392 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
411 412 413 |
# File 'lib/tree_haver/backends/citrus.rb', line 411 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.
400 401 402 |
# File 'lib/tree_haver/backends/citrus.rb', line 400 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).
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/tree_haver/backends/citrus.rb', line 318 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.
444 445 446 |
# File 'lib/tree_haver/backends/citrus.rb', line 444 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
303 304 305 306 307 308 309 |
# File 'lib/tree_haver/backends/citrus.rb', line 303 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 |