myco 0.1.4 → 0.1.5

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.
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
+ }