Class: TreeHaver::Backends::Citrus::Node Private
- Inherits:
-
Object
- Object
- TreeHaver::Backends::Citrus::Node
- 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.
254 255 256 257 |
# File 'lib/tree_haver/backends/citrus.rb', line 254 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.
252 253 254 |
# File 'lib/tree_haver/backends/citrus.rb', line 252 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.
252 253 254 |
# File 'lib/tree_haver/backends/citrus.rb', line 252 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.
419 420 421 422 423 424 |
# File 'lib/tree_haver/backends/citrus.rb', line 419 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.
415 416 417 |
# File 'lib/tree_haver/backends/citrus.rb', line 415 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.
426 427 428 429 |
# File 'lib/tree_haver/backends/citrus.rb', line 426 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.
431 432 433 434 |
# File 'lib/tree_haver/backends/citrus.rb', line 431 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.
363 364 365 |
# File 'lib/tree_haver/backends/citrus.rb', line 363 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
385 386 387 |
# File 'lib/tree_haver/backends/citrus.rb', line 385 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.
371 372 373 |
# File 'lib/tree_haver/backends/citrus.rb', line 371 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
407 408 409 |
# File 'lib/tree_haver/backends/citrus.rb', line 407 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.
436 437 438 |
# File 'lib/tree_haver/backends/citrus.rb', line 436 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.
440 441 442 |
# File 'lib/tree_haver/backends/citrus.rb', line 440 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.
444 445 446 |
# File 'lib/tree_haver/backends/citrus.rb', line 444 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.
395 396 397 398 399 400 401 402 |
# File 'lib/tree_haver/backends/citrus.rb', line 395 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.
359 360 361 |
# File 'lib/tree_haver/backends/citrus.rb', line 359 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
378 379 380 |
# File 'lib/tree_haver/backends/citrus.rb', line 378 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.
367 368 369 |
# File 'lib/tree_haver/backends/citrus.rb', line 367 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).
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'lib/tree_haver/backends/citrus.rb', line 285 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.
411 412 413 |
# File 'lib/tree_haver/backends/citrus.rb', line 411 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
270 271 272 273 274 275 276 |
# File 'lib/tree_haver/backends/citrus.rb', line 270 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 |