Module: Ibex::Codegen::RubyActions
- Includes:
- RubyAST
- Included in:
- Ruby
- Defined in:
- lib/ibex/codegen/ruby_actions.rb,
sig/ibex/codegen/ruby_actions.rbs
Overview
Semantic-action method generation shared by direct and source-mapped
Ruby output.
Instance Method Summary
collapse
-
#action_method?(production) ⇒ Boolean
-
#action_method_source ⇒ ActionMethodSource
-
#append_action_method(lines, production) ⇒ void
-
#append_actions(lines) ⇒ void
-
#append_compiled_action_method(lines, production) ⇒ void
-
#append_composed_action_method(lines, production) ⇒ void
-
#append_composed_fragment_method(lines, production, step, index) ⇒ void
-
#append_composed_orchestrator(lines, production, plan) ⇒ void
-
#append_composed_step(lines, production, step, index) ⇒ void
-
#composed_action?(production) ⇒ Boolean
-
#composed_fragment_name(production, index) ⇒ String
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
Instance Method Details
#action_method?(production) ⇒ Boolean
126
127
128
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 126
def action_method?(production)
!!(production.node || production.action || !@omit_action_call)
end
|
136
137
138
139
140
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 136
def action_method_source
@action_method_source ||= ActionMethodSource.new(
@grammar, generated_action_abi: @generated_action_abi
)
end
|
#append_action_method(lines, production) ⇒ void
This method returns an undefined value.
115
116
117
118
119
120
121
122
123
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 115
def append_action_method(lines, production)
source = action_method_source.direct_action_method_source(production)
if production.action && action_method_source.column_sensitive?(production.action.code)
lines << source
else
source.lines.each { |line| lines << " #{line.rstrip}" }
end
lines << ""
end
|
#append_actions(lines) ⇒ void
This method returns an undefined value.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 22
def append_actions(lines)
@grammar.productions.each do |production|
next unless action_method?(production)
if production.node
source = ast_node_action_source(production)
source.lines.each { |line| lines << " #{line.rstrip}" }
lines << ""
elsif composed_action?(production)
append_composed_action_method(lines, production)
elsif production.action && @line_convert
append_compiled_action_method(lines, production)
else
append_action_method(lines, production)
end
end
end
|
#append_compiled_action_method(lines, production) ⇒ void
This method returns an undefined value.
107
108
109
110
111
112
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 107
def append_compiled_action_method(lines, production)
action = production.action || raise(Ibex::Error, "missing semantic action")
source = action_method_source.compiled_action_method_source(production)
lines << " class_eval(#{source.dump}, #{action.location[:file].inspect}, #{action.location[:line]})"
lines << ""
end
|
#append_composed_action_method(lines, production) ⇒ void
This method returns an undefined value.
41
42
43
44
45
46
47
48
49
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 41
def append_composed_action_method(lines, production)
action = production.action || raise(Ibex::Error, "missing composed semantic action")
plan = action.composition&.dig(:plan) || raise(Ibex::Error, "missing action composition plan")
steps = plan.fetch(:steps)
steps.each_with_index do |step, index|
append_composed_fragment_method(lines, production, step, index) if step[:code]
end
append_composed_orchestrator(lines, production, plan)
end
|
#append_composed_fragment_method(lines, production, step, index) ⇒ void
This method returns an undefined value.
52
53
54
55
56
57
58
59
60
61
62
63
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 52
def append_composed_fragment_method(lines, production, step, index)
source = action_method_source.composed_fragment_method_source(production, step, index)
if @line_convert
location = step.fetch(:loc)
lines << " class_eval(#{source.dump}, #{location[:file].inspect}, #{location[:line]})"
elsif action_method_source.column_sensitive?(step.fetch(:code))
lines << source
else
source.lines.each { |line| lines << " #{line.rstrip}" }
end
lines << ""
end
|
#append_composed_orchestrator(lines, production, plan) ⇒ void
This method returns an undefined value.
71
72
73
74
75
76
77
78
79
80
81
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 71
def append_composed_orchestrator(lines, production, plan)
lines << " private def _ibex_action_#{production.id}" \
"(val, _values, _ibex_locations, _ibex_location_stack, _ibex_location, " \
"_ibex_lookahead_location)"
lines << " _ibex_composed_values = val.dup"
lines << " _ibex_composed_locations = _ibex_locations.dup"
plan.fetch(:steps).each_with_index do |step, index|
append_composed_step(lines, production, step, index)
end
lines.push(" _ibex_composed_values.last", " end", "")
end
|
#append_composed_step(lines, production, step, index) ⇒ void
This method returns an undefined value.
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 84
def append_composed_step(lines, production, step, index)
inputs = step.fetch(:inputs)
lines << " _ibex_step_values = _ibex_composed_values.values_at(#{inputs.join(', ')})"
lines << " _ibex_step_locations = _ibex_composed_locations.values_at(#{inputs.join(', ')})"
lookahead = step[:lookahead]
boundary = lookahead ? "_ibex_locations[#{lookahead}]" : "_ibex_lookahead_location"
lines << " _ibex_step_location = Ibex::Runtime::LocationSpan.for_reduction(" \
"_ibex_step_locations, lookahead: #{boundary})"
result = if step[:code]
stack_inputs = step.fetch(:stack_inputs)
"#{composed_fragment_name(production, index)}(" \
"_ibex_step_values, _values + _ibex_composed_values.values_at(#{stack_inputs.join(', ')}), " \
"_ibex_step_locations, _ibex_location_stack + " \
"_ibex_composed_locations.values_at(#{stack_inputs.join(', ')}), _ibex_step_location)"
else
"_ibex_step_values[0]"
end
lines << " _ibex_composed_values << #{result}"
lines << " _ibex_composed_locations << _ibex_step_location"
lines << " return _ibex_composed_values.last if @accept_requested || @semantic_error"
end
|
#composed_action?(production) ⇒ Boolean
131
132
133
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 131
def composed_action?(production)
production.action&.composition&.dig(:plan, :version) == 1
end
|
#composed_fragment_name(production, index) ⇒ String
66
67
68
|
# File 'lib/ibex/codegen/ruby_actions.rb', line 66
def composed_fragment_name(production, index)
action_method_source.composed_fragment_name(production, index)
end
|