myco 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/myco/bootstrap/find_constant.rb +4 -11
  3. data/lib/myco/code_loader.rb +2 -1
  4. data/lib/myco/code_tools/AST/ConstantAccess.my +47 -3
  5. data/lib/myco/code_tools/AST/ConstantAccess.my.rb +13 -9
  6. data/lib/myco/code_tools/AST/ConstantAssignment.my +1 -5
  7. data/lib/myco/code_tools/AST/ConstantAssignment.my.rb +3 -9
  8. data/lib/myco/code_tools/AST/ToRuby.my +5 -2
  9. data/lib/myco/code_tools/AST/ToRuby.my.rb +7 -3
  10. data/lib/myco/code_tools/AST.my +1 -0
  11. data/lib/myco/code_tools/AST.my.rb +9 -1
  12. data/lib/myco/code_tools/Parser.my +24 -0
  13. data/lib/myco/code_tools/Parser.my.rb +25 -0
  14. data/lib/myco/code_tools/parser/MycoBuilder.my +67 -0
  15. data/lib/myco/code_tools/parser/MycoBuilder.my.rb +99 -0
  16. data/lib/myco/code_tools/parser/MycoCharacterClasses.my +20 -0
  17. data/lib/myco/code_tools/parser/MycoCharacterClasses.my.rb +56 -0
  18. data/lib/myco/code_tools/parser/MycoGrammar.my +564 -0
  19. data/lib/myco/code_tools/parser/MycoGrammar.my.rb +1851 -0
  20. data/lib/myco/code_tools/parser/MycoTokens.my +78 -0
  21. data/lib/myco/code_tools/parser/MycoTokens.my.rb +170 -0
  22. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my +4 -0
  23. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my.rb +5 -0
  24. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my +142 -0
  25. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my.rb +181 -0
  26. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my +420 -0
  27. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my.rb +415 -0
  28. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my +137 -0
  29. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my.rb +237 -0
  30. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my +183 -0
  31. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my.rb +370 -0
  32. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my +65 -0
  33. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my.rb +83 -0
  34. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my +139 -0
  35. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my.rb +284 -0
  36. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my +37 -0
  37. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my.rb +24 -0
  38. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my +42 -0
  39. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my.rb +52 -0
  40. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my +123 -0
  41. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my.rb +164 -0
  42. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my +236 -0
  43. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my.rb +339 -0
  44. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my +15 -0
  45. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my.rb +14 -0
  46. data/lib/myco/code_tools.rb +1 -1
  47. data/lib/myco/version.rb +1 -1
  48. data/lib/myco.rb +2 -0
  49. metadata +44 -25
  50. data/lib/myco/code_tools/parser/peg_parser.rb +0 -7182
  51. data/lib/myco/code_tools/parser.rb +0 -39
@@ -0,0 +1,564 @@
1
+
2
+ import 'MycoCharacterClasses.my'
3
+ import 'MycoTokens.my'
4
+
5
+ MycoGrammar: Pegleromyces::Grammar {
6
+ C: MycoCharacterClasses
7
+ T: MycoTokens
8
+
9
+ [rules]
10
+
11
+ ##
12
+ # Toplevel Terminal Categorizations
13
+
14
+ rule root:
15
+ (r(declobj_expr_body[:n0])
16
+ { ast.declfile(n0, n0) })[:root]
17
+
18
+ # Declarations
19
+ rule decl:
20
+ declobj
21
+ / declstr
22
+ / copen
23
+
24
+ # Expressions allowable inside object declarations
25
+ rule declobj_expr:
26
+ category
27
+ / declobj_expr_not_category
28
+
29
+ # Expressions allowable inside object declarations that is not a category
30
+ rule declobj_expr_not_category:
31
+ decl
32
+ / cdefn
33
+ / cmeme
34
+ / constant
35
+ / meme
36
+
37
+ # Expressions allowable inside memes
38
+ rule meme_expr:
39
+ arg_expr
40
+
41
+ # Expressions allowable as function arguments
42
+ rule arg_expr:
43
+ assignment
44
+ / left_chained_atoms
45
+ / dyn_string
46
+ / dyn_symstr
47
+ / expr_atom
48
+
49
+ # TODO: make expr_atom not redundant with below rules
50
+ # Expression atoms
51
+ rule expr_atom:
52
+ decl
53
+ / left_chained_invocations
54
+ / lit_string
55
+ / lit_symstr
56
+ / unary_operation
57
+ / paren_expr
58
+ / constant
59
+ / lit_simple
60
+ / lit_array
61
+ / invoke
62
+
63
+ # Expression atoms that are not invocation chains
64
+ rule expr_atom_not_chained:
65
+ decl
66
+ / lit_string
67
+ / lit_symstr
68
+ / unary_operation
69
+ / paren_expr
70
+ / constant
71
+ / lit_simple
72
+ / lit_array
73
+ / invoke
74
+
75
+ # Expression atoms that are not strings
76
+ rule expr_atom_not_string:
77
+ decl
78
+ / left_chained_invocations
79
+ / unary_operation
80
+ / paren_expr
81
+ / constant
82
+ / lit_simple
83
+ / lit_array
84
+ / invoke
85
+
86
+ ##
87
+ # Simple literals
88
+
89
+ rule lit_simple:
90
+ r(T.null[:t0]) { ast.null(t0) }
91
+ / r(T.void[:t0]) { ast.void(t0) }
92
+ / r(T.true[:t0]) { ast.true(t0) }
93
+ / r(T.false[:t0]) { ast.false(t0) }
94
+ / r(T.self[:t0]) { ast.self(t0) }
95
+ / r(T.float[:t0]) { ast.lit(t0, t0.float) }
96
+ / r(T.integer[:t0]) { ast.lit(t0, t0.integer) }
97
+ / r(T.symbol[:t0]) { ast.lit(t0, t0.text.slice(::Range.new(1,-1)).to_sym) } # TODO: more succinct here
98
+
99
+ ##
100
+ # Enclosed literals
101
+
102
+ rule lit_string:
103
+ r((T.string_begin + T.string_body[:tb] + T.string_end) /
104
+ (T.sstring_begin + T.sstring_body[:tb] + T.sstring_end))
105
+ { ast.lit(tb, encode_escapes(tb.text)) }
106
+
107
+ rule lit_string_as_symbol:
108
+ r((T.string_begin + T.string_body[:tb] + T.string_end) /
109
+ (T.sstring_begin + T.sstring_body[:tb] + T.sstring_end))
110
+ { ast.lit(tb, encode_escapes(tb.text).to_sym) }
111
+
112
+ rule lit_symstr:
113
+ r(T.symstr_begin + T.string_body[:tb] + T.string_end)
114
+ { ast.lit(tb, encode_escapes(tb.text).to_sym) }
115
+
116
+ rule category_name:
117
+ r(T.catgry_begin + T.catgry_body[:tb] + T.catgry_end)
118
+ { ast.lit(tb, encode_escapes(tb.text).to_sym) }
119
+
120
+ ##
121
+ # String interpolations / juxtapositions
122
+
123
+ rule dyn_string_part:
124
+ r(C.spc.* + expr_atom_not_string[:n0] + C.spc.* + lit_string[:n1])
125
+ { [n0,n1] }
126
+
127
+ rule dyn_string_parts:
128
+ r(dyn_string_part.+[:nlist])
129
+ { nlist.flatten }
130
+
131
+ rule dyn_string:
132
+ r(lit_string[:n0] + dyn_string_parts[:nrest])
133
+ { ast.dstr(n0, [n0] + nrest) }
134
+
135
+ rule dyn_symstr:
136
+ r(lit_symstr[:n0] + dyn_string_parts[:nrest])
137
+ { ast.dsym(n0, [n0] + nrest) }
138
+
139
+ ##
140
+ # Constants
141
+
142
+ rule colon_const:
143
+ r(T.scope + T.constant[:tc])
144
+ { tc }
145
+
146
+ rule constant:
147
+ r(T.scope.-[:ts] + T.constant[:tc] + colon_const.*[:trest])
148
+ { ast.const((ts||tc), !!ts, [tc.sym, *trest.map(&:sym)]) }
149
+
150
+ rule const_sep: (C.spc_nl.* + T.const_sep + C.spc_nl.*).+
151
+
152
+ rule sepd_constant:
153
+ r(const_sep + constant[:n0])
154
+ { n0 }
155
+
156
+ rule constant_list:
157
+ r(constant[:n0] + sepd_constant.*[:nrest])
158
+ { ast.arrass(n0, [n0, *nrest]) }
159
+
160
+ ##
161
+ # Bare identifiers
162
+
163
+ # Used in contexts where a bare identifier is a symbol
164
+ rule id_as_symbol:
165
+ r(T.identifier[:t0]) { ast.lit(t0, t0.sym) }
166
+
167
+ ##
168
+ # Object declarations
169
+
170
+ rule declobj_sepd_expr:
171
+ r(arg_sep + declobj_expr[:n0]) { n0 }
172
+
173
+ rule declobj_sepd_exprs:
174
+ r(declobj_expr[:n0] + declobj_sepd_expr.*[:nrest] + arg_sep_opt)
175
+ { [n0, *nrest] }
176
+
177
+ rule declobj_expr_body:
178
+ r(arg_sep_opt + declobj_sepd_exprs[:nlist] + T.declare_end[:te])
179
+ { ast.block(nlist.first, nlist) }
180
+ / r(arg_sep_opt + T.declare_end[:te])
181
+ { ast.null(te) }
182
+
183
+ rule declobj:
184
+ r(constant_list[:n0] + C.spc_nl.* + T.declare_begin[:tb] + declobj_expr_body[:n1])
185
+ { ast.declobj(tb, n0, n1) }
186
+
187
+ rule category_expr:
188
+ declobj_expr_not_category
189
+
190
+ rule category_sepd_expr:
191
+ r(arg_sep + category_expr[:n0]) { n0 }
192
+
193
+ rule category_sepd_exprs:
194
+ r(arg_sep + category_expr[:n0] + category_sepd_expr.*[:nrest])
195
+ { [n0, *nrest] }
196
+
197
+ rule category:
198
+ r(category_name[:n0] + category_sepd_exprs.-[:nlist]
199
+ + !!(arg_sep_opt + (T.catgry_begin / T.declare_end)))
200
+ { ast.category(n0, n0.value,
201
+ (nlist &? ast.block(nlist.first, nlist) ?? ast.null(n0))) }
202
+
203
+ rule copen:
204
+ r(constant[:n0] + C.spc_nl.* + T.reopen[:tb] + C.spc_nl.* + T.declare_begin + declobj_expr_body[:n1])
205
+ { ast.copen(tb, n0, n1) }
206
+
207
+ rule cdefn:
208
+ r(constant[:n0] + C.spc_nl.* + T.define[:tb] + C.spc_nl.* + declobj[:n1])
209
+ { ast.cdefn(tb, n0, n1) }
210
+
211
+ ##
212
+ # String object declarations
213
+
214
+ rule declstr_body:
215
+ r(T.declstr_begin[:tb] + C.spc.* + C.nl
216
+ + T.declstr_body[:ts] + C.spc_nl.* + T.declstr_end)
217
+ { ast.str(tb, ts.text) }
218
+
219
+ rule declstr:
220
+ r(constant_list[:nc] + C.spc.+ + declstr_body[:nb])
221
+ { ast.declstr(nc, nc, nb) }
222
+
223
+ ##
224
+ # Assignment
225
+
226
+ rule assignment:
227
+ local_assignment
228
+ / invoke_assignment
229
+
230
+ rule assign_rhs:
231
+ arg_expr
232
+
233
+ rule local_assignment:
234
+ r(T.identifier[:ti] + C.spc_nl.* + T.assign[:to] + C.spc_nl.* + assign_rhs[:rhs])
235
+ { ast.lasgn(to, ti.sym, rhs) }
236
+
237
+ rule invoke_assignment_lhs:
238
+ left_chained_invocations
239
+ / invoke
240
+
241
+ rule invoke_assignment:
242
+ r(invoke_assignment_lhs[:lhs] + C.spc_nl.* + T.assign[:to] + C.spc_nl.* + assign_rhs[:rhs])
243
+ {
244
+ lhs.name = (""lhs.name"=").to_sym
245
+ orig_arguments = lhs.arguments &? lhs.arguments.body ?? []
246
+ arg_order = lhs.name==:"[]=" &? [*orig_arguments, rhs] ?? [rhs, *orig_arguments]
247
+ lhs.arguments = ast.argass(rhs, arg_order)
248
+ lhs
249
+ }
250
+
251
+
252
+ ##
253
+ # Invoke - Results in a :lambig, :call, or :iter with a :call within
254
+
255
+ rule invoke_body:
256
+ r(C.spc_nl.* + param_list.-[:np] + C.spc_nl.* + meme_enclosed_expr_body[:nb])
257
+ { [np, nb] }
258
+
259
+ opt_arg_list: (r(C.spc.* + arg_list[:n]) { n }).-
260
+ opt_invoke_body: (r(C.spc_nl.* + invoke_body[:nx]) { nx }).-
261
+
262
+ rule invoke:
263
+ r(T.identifier[:tn] + opt_arg_list[:na] + opt_invoke_body[:nlist])
264
+ { ast.invoke(tn, null, tn.sym, na, *(nlist || [])) }
265
+
266
+ rule op_invoke: # Allow some binary operators to be invoked with a dot
267
+ r(op_invoke_id[:tn] + opt_arg_list[:na] + opt_invoke_body[:nlist])
268
+ { ast.invoke(tn, null, tn.sym, na, *(nlist || [])) }
269
+
270
+ rule elem_invoke:
271
+ r(lit_array[:na] + opt_invoke_body[:nlist])
272
+ { ast.invoke(na, null, :"[]", ast.argass(na, na.body), *(nlist || [])) }
273
+
274
+ rule op_invoke_id:
275
+ left_op_normal
276
+
277
+ ##
278
+ # Argument lists
279
+
280
+ arg_sep: (C.spc.* + T.arg_sep + C.spc.*).+
281
+ arg_sep_opt: (C.spc / T.arg_sep).*
282
+
283
+ rule in_arg_normal:
284
+ in_arg_splat
285
+ / r(arg_expr[:n0] + !in_arg_kwarg_mark) { n0 }
286
+
287
+ rule in_arg_sepd_normal:
288
+ r(arg_sep + in_arg_normal[:n0]) { n0 }
289
+
290
+ rule in_arg_normals:
291
+ r(in_arg_normal[:n0] + in_arg_sepd_normal.*[:nrest])
292
+ { [n0,*nrest] }
293
+
294
+ rule in_arg_sepd_kwarg:
295
+ r(arg_sep + in_arg_kwarg[:n0]) { n0 }
296
+
297
+ rule in_arg_kwargs:
298
+ r(in_arg_kwarg[:n0] + in_arg_sepd_kwarg.*[:nrest])
299
+ { ast.hash(n0.first, [n0,*nrest].flatten) }
300
+
301
+ rule in_arg_kwarg_mark: C.spc_nl.* + T.meme_mark
302
+
303
+ rule in_arg_kwarg:
304
+ r(id_as_symbol[:n0] + in_arg_kwarg_mark + C.spc_nl.* + arg_expr[:n1])
305
+ { [n0, n1] }
306
+
307
+ rule in_arg_splat:
308
+ r(T.op_mult[:to] + expr_atom[:n0])
309
+ { ast.splat(to, n0) }
310
+
311
+ rule in_arg_block:
312
+ r(T.op_toproc[:to] + expr_atom[:n0])
313
+ { ast.blkarg(to, n0) }
314
+
315
+ rule in_arg_list:
316
+ r(in_arg_normals[:n0] + arg_sep + in_arg_kwargs[:n1] + arg_sep + in_arg_block[:n2]) { [*n0,n1,n2] }
317
+ / r(in_arg_normals[:n0] + arg_sep + in_arg_kwargs[:n1]) { [*n0,n1] }
318
+ / r(in_arg_normals[:n0] + arg_sep + in_arg_block[:n1]) { [*n0,n1] }
319
+ / r(in_arg_kwargs[:n0] + arg_sep + in_arg_block[:n1]) { [n0,n1] }
320
+ / r(in_arg_normals[:n0]) { [*n0] }
321
+ / r(in_arg_kwargs[:n0]) { [n0] }
322
+ / r(in_arg_block[:n0]) { [n0] }
323
+
324
+ rule arg_list:
325
+ r(T.args_begin[:tb] + arg_sep_opt + in_arg_list.-[:nlist] + arg_sep_opt + T.args_end)
326
+ { ast.argass(tb, (nlist || [])) }
327
+
328
+ rule lit_array:
329
+ r(T.array_begin[:tb] + arg_sep_opt + in_arg_list.-[:nlist] + arg_sep_opt + T.array_end)
330
+ { ast.arrass(tb, (nlist || [])) }
331
+
332
+ ##
333
+ # Parameter lists
334
+
335
+ rule param:
336
+ r(T.identifier[:ti] + C.spc_nl.* + T.assign[:to] + C.spc_nl.* + arg_expr[:nv])
337
+ { [:optional, ast.lasgn(ti, ti.sym, nv)] }
338
+ / r(T.identifier[:ti] + C.spc_nl.* + T.meme_mark[:to] + C.spc_nl.* + arg_expr.-[:nv])
339
+ { [:kwargs, ast.lasgn(ti, ti.sym, nv || ast.lit(to, :"*"))] }
340
+ / r(T.op_exp + C.spc_nl.* + T.identifier[:ti])
341
+ { [:kwrest, ti.sym] }
342
+ / r(T.op_mult + C.spc_nl.* + T.identifier[:ti])
343
+ { [:rest, ti.sym] }
344
+ / r(T.op_toproc + C.spc_nl.* + T.identifier[:ti])
345
+ { [:block, ti.sym] }
346
+ / r(T.identifier[:ti])
347
+ { [:required, ti.sym] }
348
+
349
+ rule param_sepd:
350
+ r(arg_sep + param[:n0]) { n0 }
351
+
352
+ rule param_sepds:
353
+ r(param[:n0] + param_sepd.*[:nrest] + arg_sep_opt) { [n0, *nrest] }
354
+
355
+ rule param_list:
356
+ r(T.params_begin[:tb] + T.params_end)
357
+ { ast.args(tb, [], [], null, [], [], null, null) } # TODO: investigate removing
358
+ / r(T.params_begin[:tb] + param_sepds[:plist] + T.params_end)
359
+ {
360
+ required = []
361
+ optional = []
362
+ rest = []
363
+ post = []
364
+ kwargs = []
365
+ kwrest = []
366
+ block = []
367
+
368
+ loop { plist[0] && plist[0][0] == :required || break; required.push(plist.shift[1]) }
369
+ loop { plist[0] && plist[0][0] == :optional || break; optional.push(plist.shift[1]) }
370
+ loop { plist[0] && plist[0][0] == :rest || break; rest .push(plist.shift[1]) }
371
+ loop { plist[0] && plist[0][0] == :required || break; post .push(plist.shift[1]) }
372
+ loop { plist[0] && plist[0][0] == :kwargs || break; kwargs .push(plist.shift[1]) }
373
+ loop { plist[0] && plist[0][0] == :kwrest || break; kwrest .push(plist.shift[1]) }
374
+ loop { plist[0] && plist[0][0] == :block || break; block .push(plist.shift[1]) }
375
+
376
+ required = required
377
+ optional = optional
378
+ rest = rest.first
379
+ post = post
380
+ kwargs = kwargs
381
+ kwrest = kwrest.first
382
+ block = block.first
383
+
384
+ # TODO: move these conversions to their respective reductions
385
+ block = block && ast.blkprm(tb, block)
386
+
387
+ ast.args(tb, required, optional, rest, post, kwargs, kwrest, block)
388
+ }
389
+
390
+ ##
391
+ # Two-term operators
392
+
393
+ left_op_normal:
394
+ T.op_exp
395
+ / T.op_mult / T.op_div / T.op_mod
396
+ / T.op_plus / T.op_minus
397
+ / T.op_compare
398
+ / T.op_and / T.op_or
399
+
400
+ left_op_branch:
401
+ T.op_and / T.op_or
402
+ / T.op_and_q / T.op_or_q / T.op_void_q
403
+
404
+ rule left_op: left_op_normal / left_op_branch
405
+
406
+ # Achieve left-associativity through iteration.
407
+ #
408
+ # PEG parsers get tripped up by left recursion
409
+ # (in contrast to LALR parsers, which prefer left recursion).
410
+ # This is a well-understood limitation, but refer to:
411
+ # http://www.dalnefre.com/wp/2011/05/parsing-expression-grammars-part-4/
412
+ # for an easy-to-understand explanation of this problem and this solution.
413
+ #
414
+ rule sepd_chained_atom:
415
+ r(C.spc_nl.* + left_op[:to] + C.spc_nl.* + expr_atom[:n1])
416
+ { [to, n1] }
417
+
418
+ rule left_chained_atoms:
419
+ r(expr_atom[:n0] + sepd_chained_atom.+[:nlist])
420
+ {
421
+ nlist.unshift(n0)
422
+ nlist.flatten!
423
+
424
+ collapse(nlist, :t_op_exp)
425
+ collapse(nlist, :t_op_mult, :t_op_div, :t_op_mod)
426
+ collapse(nlist, :t_op_plus, :t_op_minus)
427
+ collapse(nlist, :t_op_compare)
428
+ collapse(nlist, :t_op_and, :t_op_or,
429
+ :t_op_and_q, :t_op_or_q, :t_op_void_q) |n0,op,n1| {
430
+ ast.branch_op(op, op.sym, n0, n1)
431
+ }
432
+
433
+ # There should only be one resulting node left
434
+ (nlist.count == 1)
435
+ || raise("Failed to fully collapse left_chained_atoms: "nlist"")
436
+
437
+ nlist.first
438
+ }
439
+
440
+ ##
441
+ # Invocations and Quests (soft-failing invocations)
442
+
443
+ rule left_invoke_op:
444
+ T.quest
445
+ / T.dot
446
+
447
+ # Achieve left-associativity through iteration.
448
+ # (see left_chained_atoms).
449
+ #
450
+ rule sepd_chained_invocation:
451
+ r(C.spc_nl.* + left_invoke_op[:t0] + C.spc_nl.* + (invoke / op_invoke)[:n1])
452
+ { [t0, n1] }
453
+ / r(C.spc.*.token(:t_dot)[:t0] + elem_invoke[:n1])
454
+ { [t0, n1] }
455
+
456
+ rule left_chained_invocations:
457
+ r(expr_atom_not_chained[:n0] + sepd_chained_invocation.+[:nlist])
458
+ {
459
+ nlist.unshift(n0)
460
+ nlist.send(:"flatten!")
461
+
462
+ collapse(nlist, :t_dot, :t_quest) |n0,op,n1| {
463
+ (op.type == :t_dot)
464
+ &? (n1.receiver=n0; n1)
465
+ ?? ast.quest(op, n0, n1)
466
+ }
467
+
468
+ # There should only be one resulting node left
469
+ (nlist.count == 1)
470
+ || raise("Failed to fully collapse left_chained_invocations: "nlist"")
471
+
472
+ nlist.first
473
+ }
474
+
475
+ ##
476
+ # Unary operators
477
+
478
+ rule unary_operation:
479
+ r(T.op_not[:to] + expr_atom[:n0])
480
+ { ast.invoke(to, n0, :"!", null) }
481
+
482
+ ##
483
+ # Memes and etc..
484
+
485
+ # TODO: this should work without the call to 'inner'
486
+ # Currently, without this call, an unbalanced tidx_stack occurs
487
+ # in the Processor due to an extra :t_start capture symbol emitted
488
+ # by the BytecodeParser with no matching :t_end to clear it.
489
+ rule t_inln_sep: !T.arg_sep.inner + T.expr_sep
490
+
491
+ rule inln_sep: (C.spc.* + t_inln_sep + C.spc.*).+
492
+ rule inln_sep_opt: (C.spc / t_inln_sep).*
493
+
494
+ rule expr_sep: (C.spc.* + T.expr_sep + C.spc.*).+
495
+ rule expr_sep_opt: (C.spc / T.expr_sep).*
496
+
497
+ rule meme_inline_sepd_expr:
498
+ r(inln_sep + meme_expr[:n]) { n }
499
+
500
+ rule meme_inline_sepd_exprs:
501
+ r(meme_expr[:n0] + meme_inline_sepd_expr.*[:nrest] + inln_sep_opt)
502
+ { [n0, *nrest] }
503
+
504
+ rule meme_sepd_expr:
505
+ r(expr_sep + meme_expr[:n]) { n }
506
+
507
+ rule meme_sepd_exprs:
508
+ r(meme_expr[:n0] + meme_sepd_expr.*[:nrest] + expr_sep_opt)
509
+ { [n0, *nrest] }
510
+
511
+ rule meme_inline_expr_body:
512
+ r(inln_sep_opt + meme_inline_sepd_exprs[:nlist])
513
+ { ast.block(nlist.first, nlist) }
514
+
515
+ rule meme_expr_body:
516
+ r(expr_sep_opt + meme_sepd_exprs[:nlist] + T.meme_end[:te])
517
+ { ast.block(nlist.first, nlist) }
518
+ / r(expr_sep_opt + T.meme_end[:te])
519
+ { ast.null(te) }
520
+
521
+ rule paren_expr_body:
522
+ r(expr_sep_opt + meme_sepd_exprs[:nlist] + T.paren_end[:te])
523
+ { nlist.count==1 &? nlist.first ?? ast.block(nlist.first, nlist) }
524
+ / r(expr_sep_opt + T.paren_end[:te])
525
+ { ast.null(te) }
526
+
527
+ rule paren_expr:
528
+ r(T.paren_begin + paren_expr_body[:n0]) { n0 }
529
+
530
+ rule meme_enclosed_expr_body:
531
+ r(T.meme_begin + meme_expr_body[:n0]) { n0 }
532
+
533
+ rule meme_either_body:
534
+ meme_enclosed_expr_body
535
+ / meme_inline_expr_body
536
+
537
+ rule cmeme:
538
+ r(constant[:n0] + C.spc.* + T.meme_mark[:tm] + C.spc_nl.* + meme_inline_expr_body[:n1])
539
+ { ast.cdecl(tm, n0, n1) }
540
+
541
+ rule meme_name:
542
+ id_as_symbol
543
+ / lit_string_as_symbol
544
+
545
+ rule decorator:
546
+ r(meme_name[:ni] + arg_list.-[:na])
547
+ { ast.deco(ni, ni, na) }
548
+
549
+ rule sepd_decorator:
550
+ r(C.spc.* + decorator[:n]) { n }
551
+
552
+ rule decorators_and_meme_name:
553
+ r(decorator[:n0] + sepd_decorator.*[:nrest])
554
+ { ast.arrass(n0, [n0, *nrest].reverse) }
555
+
556
+ rule meme:
557
+ r(decorators_and_meme_name[:nd]
558
+ + C.spc.* + T.meme_mark[:tm]
559
+ + (r(C.spc_nl.* + param_list.-[:n]) { n })[:np]
560
+ + C.spc_nl.* + meme_either_body[:nb])
561
+ { ast.meme(tm, nd.body.shift.name, nd, np, nb) }
562
+ / r(decorators_and_meme_name[:nd])
563
+ { ast.meme(nd, nd.body.shift.name, nd, null, null) }
564
+ }