Class: Ibex::Codegen::ActionSource
- Inherits:
-
Object
- Object
- Ibex::Codegen::ActionSource
show all
- Includes:
- RubyAST
- Defined in:
- lib/ibex/codegen/action_source.rb,
sig/ibex/codegen/action_source.rbs
Overview
Generates static-check-only Ruby containing semantic action methods.
Instance Method Summary
collapse
Methods included from RubyAST
#append_ast, #append_listener, #append_listener_dispatch, #append_visit_children, #append_visitor, #ast_method_name, #ast_node_action_source, #ast_node_definitions
Constructor Details
#initialize(automaton, omit_action_call: nil) ⇒ ActionSource
Returns a new instance of ActionSource.
19
20
21
22
23
24
|
# File 'lib/ibex/codegen/action_source.rb', line 19
def initialize(automaton, omit_action_call: nil)
@automaton = automaton
@grammar = automaton.grammar
@omit_action_call = omit_action_call.nil? ? @grammar.options[:omit_action_call] : omit_action_call
@method_source = ActionMethodSource.new(@grammar)
end
|
Instance Method Details
#append_action(lines, production) ⇒ void
This method returns an undefined value.
85
86
87
88
|
# File 'lib/ibex/codegen/action_source.rb', line 85
def append_action(lines, production)
location = production.action&.location || production.origin.fetch(:loc)
append_method(lines, location, @method_source.compiled_action_method_source(production))
end
|
#append_actions(lines) ⇒ void
This method returns an undefined value.
57
58
59
60
61
62
63
64
65
66
67
|
# File 'lib/ibex/codegen/action_source.rb', line 57
def append_actions(lines)
@grammar.productions.each do |production|
if production.node
append_method(lines, production.node.fetch(:loc), ast_node_action_source(production))
elsif composed_action?(production)
append_composed_actions(lines, production)
elsif production.action || !@omit_action_call
append_action(lines, production)
end
end
end
|
#append_composed_actions(lines, production) ⇒ void
This method returns an undefined value.
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/ibex/codegen/action_source.rb', line 70
def append_composed_actions(lines, production)
plan = production.action&.composition&.dig(:plan)
raise Ibex::Error, "missing action composition plan" unless plan
plan.fetch(:steps).each_with_index do |step, index|
next unless step[:code]
append_method(
lines, step.fetch(:loc),
@method_source.composed_fragment_method_source(production, step, index)
)
end
end
|
#append_method(lines, location, source) ⇒ void
This method returns an undefined value.
91
92
93
94
95
96
97
98
99
|
# File 'lib/ibex/codegen/action_source.rb', line 91
def append_method(lines, location, source)
lines << ""
lines << " # Grammar action: #{location.fetch(:file).inspect}:" \
"#{location.fetch(:line)}:#{location.fetch(:column)}"
lines << source
end
|
#append_value_printers(lines) ⇒ void
This method returns an undefined value.
49
50
51
52
53
54
|
# File 'lib/ibex/codegen/action_source.rb', line 49
def append_value_printers(lines)
@grammar.value_printers.each do |printer|
symbol = @grammar.symbol(printer[:symbol]) || raise(Ibex::Error, "missing printer symbol #{printer[:symbol]}")
append_method(lines, printer[:loc], @method_source.value_printer_method_source(symbol.id, printer))
end
end
|
#class_parts ⇒ [ Array[String], String ]
107
108
109
110
|
# File 'lib/ibex/codegen/action_source.rb', line 107
def class_parts
parts = @grammar.class_name.split("::")
[parts.take(parts.length - 1), parts.fetch(-1)]
end
|
#composed_action?(production) ⇒ Boolean
102
103
104
|
# File 'lib/ibex/codegen/action_source.rb', line 102
def composed_action?(production)
production.action&.composition&.dig(:plan, :version) == 1
end
|
#generate ⇒ String
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
# File 'lib/ibex/codegen/action_source.rb', line 27
def generate
lines = [
"# frozen_string_literal: true",
"# Generated by Ibex #{}.",
"# Static-check-only semantic action shadow source.",
"# DO NOT LOAD OR EXECUTE: runtime wiring and user code are intentionally absent.",
""
]
modules, class_name = class_parts
modules.each { |name| lines << "module #{name}" }
lines << "class #{class_name}"
append_ast(lines)
append_value_printers(lines)
append_actions(lines)
lines << "end"
modules.reverse_each { lines << "end" }
"#{lines.join("\n")}\n"
end
|
113
114
115
|
# File 'lib/ibex/codegen/action_source.rb', line 113
def
@automaton.grammar_digest.delete_prefix("sha256:").chars.first(12).join
end
|