arpaka 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -2
- data/README.md +104 -7
- data/Rakefile +15 -1
- data/docs/architecture.dot +30 -0
- data/docs/architecture.md +96 -0
- data/docs/architecture.webp +0 -0
- data/docs/contributes.md +115 -0
- data/docs/usage.md +497 -0
- data/lib/arpaka/cli.rb +5 -53
- data/lib/arpaka/plugins/cli.rb +61 -0
- data/lib/arpaka/plugins/sample.rb +14 -0
- data/lib/arpaka/plugins/sample_runner.rb +21 -0
- data/lib/arpaka/{actions.rb → ruby/actions.rb} +230 -151
- data/lib/arpaka/ruby/class_name_parser.rb +97 -0
- data/lib/arpaka/ruby/cli.rb +64 -0
- data/lib/arpaka/ruby/frontend_emitter.rb +59 -0
- data/lib/arpaka/ruby/generator.rb +41 -0
- data/lib/arpaka/{ruby_grammar.rb → ruby/grammar.rb} +5 -56
- data/lib/arpaka/ruby/grammar_emitter.rb +71 -0
- data/lib/arpaka/ruby/profile.rb +129 -0
- data/lib/arpaka/{profile → ruby/profiles}/ruby_3_3.rb +21 -21
- data/lib/arpaka/{profile → ruby/profiles}/ruby_3_4.rb +21 -21
- data/lib/arpaka/{runtime → ruby/runtime/detailed}/ast.rb.erb +41 -5
- data/lib/arpaka/ruby/runtime/detailed/builder.rb.erb +1177 -0
- data/lib/arpaka/{runtime → ruby/runtime}/frontend.rb.erb +17 -4
- data/lib/arpaka/{runtime → ruby/runtime}/lexer.rb.erb +576 -99
- data/lib/arpaka/ruby/runtime/structured.rb.erb +111 -0
- data/lib/arpaka/ruby.rb +23 -0
- data/lib/arpaka.rb +6 -9
- data/lib/lrama/ruby/backend.rb +4 -9
- data/lib/lrama/ruby/parser.rb.erb +35 -9
- data/lib/lrama/ruby/parser_emitter.rb +41 -0
- data/lib/lrama/ruby/table_codec.rb +50 -0
- data/lib/lrama/ruby/version.rb +1 -1
- data/lib/lrama/ruby.rb +1 -0
- data/sig/arpaka.rbs +8 -3
- metadata +32 -16
- data/lib/arpaka/generator.rb +0 -51
- data/lib/arpaka/profile/ruby.rb +0 -49
- data/lib/arpaka/runtime/builder.rb.erb +0 -323
- /data/lib/arpaka/{BSDL → ruby/BSDL} +0 -0
- /data/lib/arpaka/{COPYING → ruby/COPYING} +0 -0
- /data/lib/arpaka/{source.json → ruby/source.json} +0 -0
- /data/lib/arpaka/{upstream_rules.json → ruby/upstream_rules.json} +0 -0
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
class Builder
|
|
2
|
-
RULES = <%= rules.inspect %>.to_h { |rule| [rule.fetch("id"), rule.freeze] }.freeze
|
|
3
|
-
private_constant :RULES
|
|
4
|
-
|
|
5
|
-
def initialize
|
|
6
|
-
@locals = {}
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def program(statements)
|
|
10
|
-
AST::Program.new(statements.freeze)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def integer(value)
|
|
14
|
-
raise ArgumentError, "tINTEGER requires an Integer value" unless value.is_a?(Integer)
|
|
15
|
-
AST::Literal.new(value)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def float(value)
|
|
19
|
-
raise ArgumentError, "tFLOAT requires a Float value" unless value.is_a?(Float)
|
|
20
|
-
AST::Literal.new(value)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def literal(value)
|
|
24
|
-
AST::Literal.new(value)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def reserved_word(value)
|
|
28
|
-
value.to_sym
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def binary(operator, left, right)
|
|
32
|
-
AST::Binary.new(operator, left, right)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def operator(value)
|
|
36
|
-
value.to_sym
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def range(operator, begin_value, end_value)
|
|
40
|
-
AST::RangeLiteral.new(operator, begin_value, end_value)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def ternary(condition, then_value, else_value)
|
|
44
|
-
AST::Ternary.new(condition, then_value, else_value)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def call(name, arguments)
|
|
48
|
-
AST::Call.new(name, arguments.freeze)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def receiver_call(receiver, operator, name, arguments)
|
|
52
|
-
AST::ReceiverCall.new(receiver, operator, name, (arguments || []).freeze)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def block_call(call, body)
|
|
56
|
-
AST::BlockCall.new(call, body_nodes(body))
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def append_arguments(arguments, argument)
|
|
60
|
-
list = arguments.is_a?(Array) ? arguments : [arguments]
|
|
61
|
-
(list + [argument]).freeze
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def string(value)
|
|
65
|
-
if value.is_a?(Array)
|
|
66
|
-
return AST::InterpolatedString.new(value.freeze) if value.any? { |part| !part.is_a?(String) }
|
|
67
|
-
value = value.join
|
|
68
|
-
end
|
|
69
|
-
AST::StringLiteral.new(value.to_s)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def regexp(value)
|
|
73
|
-
AST::RegexpLiteral.new(value.is_a?(Array) ? value.join : value.to_s)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def xstring(value)
|
|
77
|
-
AST::XStringLiteral.new(value.is_a?(Array) ? value.join : value.to_s)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def for_node(variable, enumerable, body)
|
|
81
|
-
AST::For.new(variable, enumerable, body)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def def_node(name, arguments, body)
|
|
85
|
-
AST::Def.new(name.to_sym, (arguments || []).freeze, body || [].freeze)
|
|
86
|
-
end
|
|
87
|
-
<% if runtime.fetch("builder_methods", []).include?("singleton_method") -%>
|
|
88
|
-
def singleton_method_node(receiver, name, arguments, body)
|
|
89
|
-
AST::SingletonMethodDef.new(receiver, name.to_sym, (arguments || []).freeze,
|
|
90
|
-
body_nodes(body))
|
|
91
|
-
end
|
|
92
|
-
<% end -%>
|
|
93
|
-
|
|
94
|
-
def class_node(name, superclass, body)
|
|
95
|
-
AST::ClassDef.new(name.to_sym, superclass, body_nodes(body))
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def module_node(name, body)
|
|
99
|
-
AST::ModuleDef.new(name.to_sym, body_nodes(body))
|
|
100
|
-
end
|
|
101
|
-
<% if runtime.fetch("builder_methods", []).include?("singleton_class") -%>
|
|
102
|
-
def singleton_class_node(receiver, body)
|
|
103
|
-
AST::SingletonClassDef.new(receiver, body_nodes(body))
|
|
104
|
-
end
|
|
105
|
-
<% end -%>
|
|
106
|
-
|
|
107
|
-
def body_nodes(body)
|
|
108
|
-
value = body
|
|
109
|
-
while value.is_a?(Array) && value.length == 1 && value.first.is_a?(Array)
|
|
110
|
-
value = value.first
|
|
111
|
-
end
|
|
112
|
-
value || [].freeze
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def symbol(value)
|
|
116
|
-
value = value.map { |part| part.is_a?(String) ? part : part.to_s }.join if value.is_a?(Array)
|
|
117
|
-
value = value.name if value.is_a?(AST::Variable)
|
|
118
|
-
AST::Literal.new(value.to_sym)
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def join_strings(parts)
|
|
122
|
-
parts
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def interpolation(value)
|
|
126
|
-
value.is_a?(Array) && value.length == 1 ? value.first : value
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def concat_strings(left, right)
|
|
130
|
-
left_parts = left.is_a?(AST::InterpolatedString) ? left.parts : [left.value]
|
|
131
|
-
right_parts = right.is_a?(AST::InterpolatedString) ? right.parts : [right.value]
|
|
132
|
-
parts = left_parts + right_parts
|
|
133
|
-
parts.all? { |part| part.is_a?(String) } ? AST::StringLiteral.new(parts.join) : AST::InterpolatedString.new(parts.freeze)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def index(receiver, arguments)
|
|
137
|
-
AST::Index.new(receiver, arguments.freeze)
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def loop(kind, condition, body)
|
|
141
|
-
AST::Loop.new(kind, condition, body)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
def control(kind)
|
|
145
|
-
AST::Control.new(kind)
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def variable(kind, name)
|
|
149
|
-
AST::Variable.new(kind, name.is_a?(String) ? name.to_sym : name)
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def rescue_modifier(expression, fallback)
|
|
153
|
-
AST::Rescue.new(expression, fallback)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def when_node(patterns, body)
|
|
157
|
-
AST::When.new(patterns.freeze, body)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def case_node(expression, whens, else_body)
|
|
161
|
-
AST::Case.new(expression, whens.freeze, else_body)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def case_clauses(value)
|
|
165
|
-
value.is_a?(Array) ? value : [value]
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def case_parts(value)
|
|
169
|
-
values = case_clauses(value)
|
|
170
|
-
if values.all? { |item| item.is_a?(AST::When) }
|
|
171
|
-
[values, nil]
|
|
172
|
-
else
|
|
173
|
-
[values.grep(AST::When), values.reject { |item| item.is_a?(AST::When) }]
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def case_chain(when_node, rest)
|
|
178
|
-
[when_node] + (rest.nil? ? [] : case_clauses(rest))
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
def lambda_node(arguments, body)
|
|
182
|
-
AST::Lambda.new((arguments || []).freeze, body_nodes(body))
|
|
183
|
-
end
|
|
184
|
-
<% if runtime.fetch("builder_methods", []).include?("rescue") -%>
|
|
185
|
-
def body_statement(body, clauses, else_body, ensure_body)
|
|
186
|
-
clauses = clauses.nil? ? [] : Array(clauses)
|
|
187
|
-
if clauses.empty? && else_body.nil? && ensure_body.nil?
|
|
188
|
-
body_nodes(body)
|
|
189
|
-
else
|
|
190
|
-
full_rescue(body, clauses, else_body, ensure_body)
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def rescue_chain(clause, rest)
|
|
195
|
-
[clause] + (rest.nil? ? [] : Array(rest))
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def pattern(kind, values)
|
|
199
|
-
AST::Pattern.new(kind.to_sym, Array(values).freeze)
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def rescue_clause(exceptions, variable, body)
|
|
203
|
-
AST::RescueClause.new(Array(exceptions).freeze, variable, body_nodes(body))
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
def full_rescue(body, clauses, else_body, ensure_body)
|
|
207
|
-
AST::FullRescue.new(body_nodes(body), Array(clauses).freeze,
|
|
208
|
-
else_body.nil? ? nil : body_nodes(else_body),
|
|
209
|
-
ensure_body.nil? ? nil : body_nodes(ensure_body))
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def begin_block(body)
|
|
213
|
-
AST::BeginBlock.new(body_nodes(body))
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
def end_block(body)
|
|
217
|
-
AST::EndBlock.new(body_nodes(body))
|
|
218
|
-
end
|
|
219
|
-
<% end -%>
|
|
220
|
-
|
|
221
|
-
def unary(operator, operand)
|
|
222
|
-
AST::Unary.new(operator, operand)
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def if_node(condition, then_body, else_body)
|
|
226
|
-
AST::If.new(condition, then_body, else_body)
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
def unless_node(condition, then_body, else_body)
|
|
230
|
-
AST::If.new(AST::Unary.new(:!, condition), then_body, else_body)
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def elsif_node(condition, then_body, else_body)
|
|
234
|
-
AST::If.new(condition, then_body, else_body)
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
def parentheses(statements, rule_id)
|
|
238
|
-
return statements.first if statements.length == 1
|
|
239
|
-
AST::Sequence.new(statements.freeze)
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def identifier(value)
|
|
243
|
-
unless value.is_a?(Symbol) || value.is_a?(String)
|
|
244
|
-
raise ArgumentError, "tIDENTIFIER requires a Symbol or String value"
|
|
245
|
-
end
|
|
246
|
-
value.to_sym
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
def declare_local(name)
|
|
250
|
-
@locals[name] = true
|
|
251
|
-
name
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
def read_local(name)
|
|
255
|
-
return name if name.is_a?(AST::Variable)
|
|
256
|
-
(@locals.key?(name) ? AST::LocalRead : AST::BareCall).new(name)
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def assign(name, value)
|
|
260
|
-
AST::LocalWrite.new(name, value)
|
|
261
|
-
end
|
|
262
|
-
<% if runtime.fetch("builder_methods", []).include?("assignment") -%>
|
|
263
|
-
def assignment(name, value)
|
|
264
|
-
if name.is_a?(AST::Field) || name.is_a?(AST::Index)
|
|
265
|
-
AST::Assignment.new(name, value)
|
|
266
|
-
else
|
|
267
|
-
AST::LocalWrite.new(name, value)
|
|
268
|
-
end
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
def opassign(target, operator, value)
|
|
272
|
-
AST::OpAssign.new(target, operator.to_sym, value)
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
def multiple_assign(targets, value)
|
|
276
|
-
AST::MultipleAssign.new(Array(targets).freeze, value)
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
def field(receiver, operator, name)
|
|
280
|
-
AST::Field.new(receiver, operator.to_sym, name.to_sym)
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
def alias_node(new_name, old_name)
|
|
284
|
-
AST::Alias.new(new_name, old_name)
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
def undef_node(names)
|
|
288
|
-
AST::Undef.new(Array(names).freeze)
|
|
289
|
-
end
|
|
290
|
-
<% end -%>
|
|
291
|
-
|
|
292
|
-
def array(elements)
|
|
293
|
-
AST::ArrayLiteral.new(elements.freeze)
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
def word_array(elements, symbols: false)
|
|
297
|
-
elements ||= []
|
|
298
|
-
elements = elements.elements if elements.is_a?(AST::ArrayLiteral)
|
|
299
|
-
values = elements.map do |value|
|
|
300
|
-
value = value.value if value.is_a?(AST::StringLiteral)
|
|
301
|
-
symbols ? value.to_sym : AST::StringLiteral.new(value.to_s)
|
|
302
|
-
end
|
|
303
|
-
AST::ArrayLiteral.new(values.freeze)
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
def hash(pairs)
|
|
307
|
-
AST::HashLiteral.new(pairs.freeze)
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
def pair(key, value)
|
|
311
|
-
AST::Pair.new(key, value)
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
def append(list, value)
|
|
315
|
-
value.nil? ? list : (list + [value]).freeze
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
def unsupported(id)
|
|
319
|
-
rule = RULES.fetch(id)
|
|
320
|
-
raise UnsupportedSyntax.new(rule.fetch("rule"), rule.fetch("line"))
|
|
321
|
-
end
|
|
322
|
-
end
|
|
323
|
-
private_constant :Builder
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|