Module: Ibex::Codegen::RubySyntax

Included in:
Ruby
Defined in:
lib/ibex/codegen/ruby_syntax.rb,
sig/ibex/codegen/ruby_syntax.rbs

Overview

Generates typed Red syntax views from @node metadata.

Instance Method Summary collapse

Instance Method Details

#append_repetition_accessors(lines, fields) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines, Hash[String, untyped] fields) -> void

Parameters:

  • lines (Array[String])
  • fields (Hash[String, untyped])


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/ibex/codegen/ruby_syntax.rb', line 69

def append_repetition_accessors(lines, fields)
  repeated = fields.select { |_field, slot| slot.is_a?(Hash) && slot[:extraction] }
  repeated.each do |field, slot|
    index = slot.fetch(:index)
    separated = slot.fetch(:extraction) == :separated_list
    lines << "      def each_#{field}_element = list_items(#{index}, separated: #{separated})"
    next unless separated

    method = "each_#{field}_separator"
    lines << "      def #{method} = list_items(#{index}, separated: true, separators: true)"
  end
  return unless repeated.one?

  field, slot = repeated.first
  lines << "      alias each_element each_#{field}_element"
  return unless slot.fetch(:extraction) == :separated_list

  lines << "      alias each_separator each_#{field}_separator"
end

#append_syntax(lines) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines) -> void

Parameters:

  • lines (Array[String])


11
12
13
14
15
16
17
18
19
# File 'lib/ibex/codegen/ruby_syntax.rb', line 11

def append_syntax(lines)
  # @type self: Ruby
  definitions = syntax_node_definitions
  return if definitions.empty? || !cst?

  lines << "  module Syntax"
  definitions.each_value { |definition| append_syntax_node(lines, definition) }
  lines.push("  end", "")
end

#append_syntax_node(lines, definition) ⇒ void

This method returns an undefined value.

RBS:

  • (Array[String] lines, Hash[Symbol, untyped] definition) -> void

Parameters:

  • lines (Array[String])
  • definition (Hash[Symbol, untyped])


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ibex/codegen/ruby_syntax.rb', line 52

def append_syntax_node(lines, definition)
  name = definition.fetch(:name)
  fields = definition.fetch(:fields)
  lines.push(
    "    class #{name} < Ibex::Runtime::CST::TypedNode",
    "      KIND = #{definition.fetch(:kind)}",
    "      def self.cast(node) = node.kind == KIND ? new(node) : nil"
  )
  fields.each do |field, slot|
    index = slot.is_a?(Hash) ? slot.fetch(:index) : slot
    lines << "      def #{field} = child_at_slot(#{index})"
  end
  append_repetition_accessors(lines, fields)
  lines.push("    end", "")
end

#merge_syntax_fields(left, right) ⇒ Hash[String, untyped]

RBS:

  • (Hash[String, untyped] left, Hash[String, untyped] right) -> Hash[String, untyped]

Parameters:

  • left (Hash[String, untyped])
  • right (Hash[String, untyped])

Returns:

  • (Hash[String, untyped])


40
41
42
43
44
45
46
47
48
49
# File 'lib/ibex/codegen/ruby_syntax.rb', line 40

def merge_syntax_fields(left, right)
  left.to_h do |name, left_slot|
    right_slot = right.fetch(name)
    left_index = left_slot.is_a?(Hash) ? left_slot.fetch(:index) : left_slot
    right_index = right_slot.is_a?(Hash) ? right_slot.fetch(:index) : right_slot
    raise Ibex::Error, "inconsistent CST slot for #{name}" unless left_index == right_index

    [name, left_slot == right_slot ? left_slot : left_index]
  end.freeze
end

#syntax_node_definitionsHash[String, Hash[Symbol, untyped]]

RBS:

  • () -> Hash[String, Hash[Symbol, untyped]]

Returns:

  • (Hash[String, Hash[Symbol, untyped]])


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ibex/codegen/ruby_syntax.rb', line 22

def syntax_node_definitions
  # @type self: Ruby
  slots = .fetch(:slots)
  definitions = {} #: Hash[String, Hash[Symbol, untyped]]
  @grammar.productions.each do |production|
    node = production.node
    next unless node

    slot = slots.fetch(production.id)
    name = node.fetch(:name)
    previous = definitions[name]
    fields = previous ? merge_syntax_fields(previous.fetch(:fields), slot.fetch(:fields)) : slot.fetch(:fields)
    definitions[name] = { name: name, kind: slot.fetch(:node_kind), fields: fields }.freeze
  end
  definitions
end