Class: TreeHaver::Backends::Citrus::Node Private

Inherits:
TreeHaver::Base::Node show all
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[0]: rule name (Symbol) - used as type
  • offset: byte position
  • length: byte length
  • string: matched text
  • matches: child matches
  • captures: named groups

Inherits from Base::Node to get shared methods like #first_child, #last_child,
#to_s, #inspect, #==, #<=>, #source_position, #start_line, #end_line, etc.

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

Attributes inherited from TreeHaver::Base::Node

#inner_node, #lines, #source

Instance Method Summary collapse

Methods inherited from TreeHaver::Base::Node

#<=>, #==, #child_by_field_name, #each, #end_line, #first_child, #has_error?, #inspect, #last_child, #missing?, #named?, #next_sibling, #parent, #prev_sibling, #source_position, #start_line, #to_s

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.



319
320
321
322
# File 'lib/tree_haver/backends/citrus.rb', line 319

def initialize(match, source)
  @match = match
  super(match, source: source)
end

Instance Attribute Details

#matchObject (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.



317
318
319
# File 'lib/tree_haver/backends/citrus.rb', line 317

def match
  @match
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.

Override child to handle negative indices properly



381
382
383
384
385
386
387
# File 'lib/tree_haver/backends/citrus.rb', line 381

def child(index)
  return if index.negative?
  return unless @match.respond_to?(:matches)
  return if index >= @match.matches.size

  Node.new(@match.matches[index], @source)
end

#child_countObject

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.

Override child_count for efficiency (avoid building full children array)



376
377
378
# File 'lib/tree_haver/backends/citrus.rb', line 376

def child_count
  @match.respond_to?(:matches) ? @match.matches.size : 0
end

#childrenObject

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.



353
354
355
356
# File 'lib/tree_haver/backends/citrus.rb', line 353

def children
  return [] unless @match.respond_to?(:matches)
  @match.matches.map { |m| Node.new(m, @source) }
end

#end_byteObject

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.



349
350
351
# File 'lib/tree_haver/backends/citrus.rb', line 349

def end_byte
  @match.offset + @match.length
end

#end_pointObject

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.

Override end_point to calculate from source



366
367
368
# File 'lib/tree_haver/backends/citrus.rb', line 366

def end_point
  calculate_point(@match.offset + @match.length)
end

#start_byteObject

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.



345
346
347
# File 'lib/tree_haver/backends/citrus.rb', line 345

def start_byte
  @match.offset
end

#start_pointObject

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.

Override start_point to calculate from source



361
362
363
# File 'lib/tree_haver/backends/citrus.rb', line 361

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).

Returns:

  • (Boolean)

    true if this is a structural (non-terminal) node



396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/tree_haver/backends/citrus.rb', line 396

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

#textObject

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.

Override text to use Citrus match string



371
372
373
# File 'lib/tree_haver/backends/citrus.rb', line 371

def text
  @match.string
end

#typeString

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:

  1. Check if first event has a .name method (returns Symbol) - use that
  2. If first event is a Symbol directly - use that
  3. For compound rules (Repeat, Choice), recurse into first match

Returns:

  • (String)

    rule name from grammar



337
338
339
340
341
342
343
# File 'lib/tree_haver/backends/citrus.rb', line 337

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