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, untyped]
- #syntax_node_definitions ⇒ Hash[String, Hash[Symbol, untyped]]
Instance Method Details
#append_repetition_accessors(lines, fields) ⇒ void
This method returns an undefined value.
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.
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.
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]
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_definitions ⇒ 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 |