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
- #append_repetition_accessors(lines, fields) ⇒ void
- #append_syntax(lines) ⇒ void
- #append_syntax_node(lines, definition) ⇒ void
- #merge_syntax_fields(left, right) ⇒ Hash[String, CSTMetadata::field_slot]
- #syntax_node_definitions ⇒ Hash[String, syntax_definition]
Instance Method Details
#append_repetition_accessors(lines, fields) ⇒ void
This method returns an undefined value.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/ibex/codegen/ruby_syntax.rb', line 73 def append_repetition_accessors(lines, fields) repeated = fields.select { |_field, slot| slot.is_a?(Hash) && slot[:extraction] } repeated.each do |field, slot| typed_slot = slot #: Hash[Symbol, untyped] index = typed_slot.fetch(:index) #: Integer separated = typed_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 typed_slot = slot #: Hash[Symbol, untyped] lines << " alias each_element each_#{field}_element" return unless typed_slot.fetch(:extraction) == :separated_list lines << " alias each_separator each_#{field}_separator" end |
#append_syntax(lines) ⇒ void
This method returns an undefined value.
14 15 16 17 18 19 20 21 22 |
# File 'lib/ibex/codegen/ruby_syntax.rb', line 14 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.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/ibex/codegen/ruby_syntax.rb', line 56 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, CSTMetadata::field_slot]
44 45 46 47 48 49 50 51 52 53 |
# File 'lib/ibex/codegen/ruby_syntax.rb', line 44 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_definitions ⇒ Hash[String, syntax_definition]
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/ibex/codegen/ruby_syntax.rb', line 25 def syntax_node_definitions # @type self: Ruby = #: CSTMetadata::metadata slots = .fetch(:slots) definitions = {} #: Hash[String, syntax_definition] @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 |