myco 0.1.0.dev

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +2 -0
  3. data/bin/myco +7 -0
  4. data/lib/myco/backtrace.rb +56 -0
  5. data/lib/myco/bootstrap/component.rb +142 -0
  6. data/lib/myco/bootstrap/empty_object.rb +4 -0
  7. data/lib/myco/bootstrap/file_toplevel.rb +5 -0
  8. data/lib/myco/bootstrap/find_constant.rb +86 -0
  9. data/lib/myco/bootstrap/instance.rb +52 -0
  10. data/lib/myco/bootstrap/meme.rb +160 -0
  11. data/lib/myco/bootstrap/void.rb +40 -0
  12. data/lib/myco/bootstrap.my +15 -0
  13. data/lib/myco/bootstrap.rb +10 -0
  14. data/lib/myco/command.my +33 -0
  15. data/lib/myco/core/BasicObject.my +46 -0
  16. data/lib/myco/core/Category.my +5 -0
  17. data/lib/myco/core/Decorator.my +18 -0
  18. data/lib/myco/core/FileToplevel.my +23 -0
  19. data/lib/myco/core/Object.my +24 -0
  20. data/lib/myco/core/Switch.my +31 -0
  21. data/lib/myco/eval.rb +63 -0
  22. data/lib/myco/parser/ast/constant_access.rb +29 -0
  23. data/lib/myco/parser/ast/constant_define.rb +40 -0
  24. data/lib/myco/parser/ast/constant_reopen.rb +47 -0
  25. data/lib/myco/parser/ast/declare_category.rb +51 -0
  26. data/lib/myco/parser/ast/declare_decorator.rb +35 -0
  27. data/lib/myco/parser/ast/declare_file.rb +54 -0
  28. data/lib/myco/parser/ast/declare_meme.rb +44 -0
  29. data/lib/myco/parser/ast/declare_object.rb +75 -0
  30. data/lib/myco/parser/ast/declare_string.rb +37 -0
  31. data/lib/myco/parser/ast/invoke.rb +66 -0
  32. data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +38 -0
  33. data/lib/myco/parser/ast/misc.rb +61 -0
  34. data/lib/myco/parser/ast/myco_module_scope.rb +58 -0
  35. data/lib/myco/parser/ast/quest.rb +82 -0
  36. data/lib/myco/parser/ast.rb +15 -0
  37. data/lib/myco/parser/builder.output +3995 -0
  38. data/lib/myco/parser/builder.racc +585 -0
  39. data/lib/myco/parser/builder.rb +1592 -0
  40. data/lib/myco/parser/lexer.rb +2306 -0
  41. data/lib/myco/parser/lexer.rl +393 -0
  42. data/lib/myco/parser/lexer_char_classes.rl +56 -0
  43. data/lib/myco/parser/lexer_common.rb +95 -0
  44. data/lib/myco/parser/lexer_skeleton.rl +154 -0
  45. data/lib/myco/parser/peg_parser.kpeg +759 -0
  46. data/lib/myco/parser/peg_parser.rb +7094 -0
  47. data/lib/myco/parser.rb +40 -0
  48. data/lib/myco/tools/OptionParser.my +38 -0
  49. data/lib/myco/tools/mycompile.my +51 -0
  50. data/lib/myco/toolset.rb +16 -0
  51. data/lib/myco/version.rb +22 -0
  52. data/lib/myco.rb +15 -0
  53. metadata +247 -0
@@ -0,0 +1,585 @@
1
+ class CodeTools::Builder
2
+ token T_CONSTANT T_IDENTIFIER T_SYMBOL
3
+ T_NULL T_VOID T_TRUE T_FALSE
4
+ T_INTEGER T_FLOAT
5
+ T_SELF
6
+ T_OP_PLUS T_OP_MINUS T_OP_MULT T_OP_DIV T_OP_MOD T_OP_EXP
7
+ T_OP_COMPARE T_OP_AND T_OP_OR
8
+ T_OP_TOPROC
9
+ T_DOT T_QUEST
10
+ T_DEFINE T_CONST_SEP T_EXPR_SEP T_ARG_SEP T_SCOPE T_ASSIGN
11
+ T_DECLARE_BEGIN T_DECLARE_END
12
+ T_DECLSTR_BEGIN T_DECLSTR_END T_DECLSTR_BODY
13
+ T_STRING_BEGIN T_STRING_END T_STRING_BODY
14
+ T_SYMSTR_BEGIN T_SYMSTR_END T_SYMSTR_BODY
15
+ T_DECLID_TAG T_DECLID_VALUE
16
+ T_CATEGORY_BEGIN T_CATEGORY_END T_CATEGORY_BODY
17
+ T_MEME_BEGIN T_MEME_END
18
+ T_PARAMS_BEGIN T_PARAMS_END
19
+ T_ARGS_BEGIN T_ARGS_END
20
+ T_PAREN_BEGIN T_PAREN_END
21
+ T_ARRAY_BEGIN T_ARRAY_END
22
+ T_FILE_END
23
+
24
+ options no_result_var
25
+
26
+
27
+ prechigh
28
+ left T_SCOPE
29
+ left T_DOT T_QUEST
30
+ left T_OP_EXP
31
+ left T_OP_MULT T_OP_DIV T_OP_MOD
32
+ left T_OP_PLUS T_OP_MINUS
33
+ left T_OP_COMPARE
34
+ left T_OP_AND T_OP_OR
35
+ left T_ASSIGN
36
+ preclow
37
+
38
+
39
+ rule
40
+ main:
41
+ declobj_expr_body { ast(:declfile, val[0], val[0]) }
42
+ ;
43
+
44
+
45
+ # Expressions allowable inside object declarations
46
+ declobj_expr:
47
+ cdefn
48
+ | cmeme
49
+ | meme
50
+ | deco
51
+ | declobj
52
+ | declstr
53
+ | declid
54
+ | category
55
+ | constant
56
+ ;
57
+
58
+ # Expressions allowable inside memes
59
+ meme_expr:
60
+ declobj
61
+ | declstr
62
+ | arg_expr
63
+ ;
64
+
65
+ # Expressions allowable as function arguments
66
+ arg_expr:
67
+ arg_expr_atom
68
+ | two_term_expr
69
+ | assignment
70
+ | nest_assignment
71
+ | quest_self
72
+ | lit_string
73
+ | lit_symstr
74
+ | dyn_string
75
+ | dyn_symstr
76
+ ;
77
+
78
+ # Expressions allowable as function arguments and in other assemblies
79
+ arg_expr_atom:
80
+ paren_expr
81
+ | call
82
+ | quest
83
+ | constant
84
+ | id_as_lambig
85
+ | lit_null
86
+ | lit_void
87
+ | lit_true
88
+ | lit_false
89
+ | lit_integer
90
+ | lit_float
91
+ | lit_symbol
92
+ | lit_array
93
+ | lit_self
94
+ ;
95
+
96
+ ##
97
+ # Simple literals
98
+
99
+ lit_null:
100
+ T_NULL { ast(:null, val[0]) }
101
+ ;
102
+
103
+ lit_void:
104
+ T_VOID { ast(:void, val[0]) }
105
+ ;
106
+
107
+ lit_true:
108
+ T_TRUE { ast(:true, val[0]) }
109
+ ;
110
+
111
+ lit_false:
112
+ T_FALSE { ast(:false, val[0]) }
113
+ ;
114
+
115
+ lit_integer:
116
+ T_INTEGER { ast(:lit, val[0], Integer(val[0][1])) }
117
+ ;
118
+
119
+ lit_float:
120
+ T_FLOAT { ast(:lit, val[0], Float(val[0][1])) }
121
+ ;
122
+
123
+ lit_symbol:
124
+ T_SYMBOL { ast(:lit, val[0], val[0][1].to_sym) }
125
+ ;
126
+
127
+ lit_string:
128
+ T_STRING_BEGIN T_STRING_BODY T_STRING_END { val[1] }
129
+ { ast(:lit, val[1], encode_escapes(val[1][1])) }
130
+ ;
131
+
132
+ lit_string_as_symbol: # Used in contexts where a bare string is a symbol
133
+ T_STRING_BEGIN T_STRING_BODY T_STRING_END { val[1] }
134
+ { ast(:lit, val[1], encode_escapes(val[1][1]).to_sym) }
135
+ ;
136
+
137
+ lit_symstr:
138
+ T_SYMSTR_BEGIN T_SYMSTR_BODY T_SYMSTR_END
139
+ { ast(:lit, val[1], encode_escapes(val[1][1]).to_sym) }
140
+ ;
141
+
142
+ lit_self:
143
+ T_SELF { ast(:self, val[0]) }
144
+ ;
145
+
146
+ ##
147
+ # String interpolations / juxtapositions
148
+
149
+ dyn_string_part:
150
+ arg_expr_atom lit_string { [ast(:evstr, val[0], val[0]), val[1]] }
151
+ ;
152
+
153
+ dyn_string_parts:
154
+ dyn_string_parts dyn_string_part { [*val[0], *val[1]] }
155
+ | dyn_string_part { val[0] }
156
+ ;
157
+
158
+ dyn_string:
159
+ lit_string dyn_string_parts { ast(:dstr, val[0], val[0].value, val[1]) }
160
+ ;
161
+
162
+ dyn_symstr:
163
+ lit_symstr dyn_string_parts { ast(:dsym, val[0], val[0].value.to_s, val[1])}
164
+ ;
165
+
166
+ ##
167
+ # Constants
168
+
169
+ constant:
170
+ constant T_SCOPE T_CONSTANT { ast(:colon2, val[1], val[0], val[2][1].to_sym) }
171
+ | T_SCOPE T_CONSTANT { ast(:colon3, val[0], val[1][1].to_sym) }
172
+ | T_CONSTANT { ast(:const, val[0], val[0][1].to_sym) }
173
+ ;
174
+
175
+ constant_list_:
176
+ constant_list_ T_CONST_SEP constant { [*val[0], val[2]] }
177
+ | constant { val }
178
+ ;
179
+
180
+ constant_list:
181
+ constant_list_
182
+ { ast(:array, val[0][0], val[0]) }
183
+ ;
184
+
185
+ ##
186
+ # Bare identifiers
187
+
188
+ id_as_symbol: # Used in contexts where a bare identifier is a symbol
189
+ T_IDENTIFIER
190
+ { ast(:lit, val[0], val[0][1].to_sym) }
191
+ ;
192
+
193
+ id_as_lambig: # Ambiguous - could be local variable or call without args
194
+ T_IDENTIFIER
195
+ { ast(:lambig, val[0], val[0][1].to_sym) }
196
+ ;
197
+
198
+ ##
199
+ # Assignment
200
+
201
+ assignment:
202
+ T_IDENTIFIER T_ASSIGN arg_expr
203
+ { ast(:lasgn, val[1], val[0][1].to_sym, val[2]) }
204
+ ;
205
+
206
+ nest_assignment:
207
+ arg_expr T_DOT T_IDENTIFIER T_ASSIGN arg_expr
208
+ { ast(:call, val[3], val[0], :"#{val[2][1]}=", ast(:array, val[4], [val[4]])) }
209
+ ;
210
+
211
+
212
+ ##
213
+ # Method calls
214
+
215
+ call:
216
+ nest_call
217
+ | call_with_args
218
+ | nest_call_with_args
219
+ | call_iter
220
+ | nest_call_iter
221
+ ;
222
+
223
+ nest_call:
224
+ arg_expr T_DOT T_IDENTIFIER
225
+ { ast(:call, val[2], val[0], val[2][1].to_sym, ast(:array, val[2], [])) }
226
+ ;
227
+
228
+ call_with_args:
229
+ T_IDENTIFIER arg_list
230
+ { ast(:call, val[1], ast(:self, val[0]), val[0][1].to_sym, val[1]) }
231
+ ;
232
+
233
+ nest_call_with_args:
234
+ arg_expr T_DOT T_IDENTIFIER arg_list
235
+ { ast(:call, val[3], val[0], val[2][1].to_sym, val[3]) }
236
+ ;
237
+
238
+ call_iter_body:
239
+ T_MEME_BEGIN meme_expr_body
240
+ { ast(:scope, val[0], nil, val[1], nil) }
241
+ | param_list T_MEME_BEGIN meme_expr_body
242
+ { ast(:scope, val[1], val[0], val[2], nil) }
243
+ ;
244
+
245
+ call_iter:
246
+ T_IDENTIFIER call_iter_body
247
+ { ast(:iter, val[0], ast(:call, val[0], ast(:self, val[0]), val[0][1].to_sym, nil), val[1]) }
248
+ | T_IDENTIFIER arg_list call_iter_body
249
+ { ast(:iter, val[0], ast(:call, val[0], ast(:self, val[0]), val[0][1].to_sym, val[1]), val[2]) }
250
+ ;
251
+
252
+ nest_call_iter:
253
+ arg_expr T_DOT T_IDENTIFIER call_iter_body
254
+ { ast(:iter, val[2], ast(:call, val[2], val[0], val[2][1].to_sym, nil), val[3]) }
255
+ | arg_expr T_DOT T_IDENTIFIER arg_list call_iter_body
256
+ { ast(:iter, val[2], ast(:call, val[2], val[0], val[2][1].to_sym, val[3]), val[4]) }
257
+ ;
258
+
259
+ ##
260
+ # Method quests
261
+
262
+ questable:
263
+ T_IDENTIFIER
264
+ { ast(:quest, val[0], ast(:self, val[0]), ast(:call, val[0], ast(:self, val[0]), val[0][1].to_sym, nil)) }
265
+ | call_with_args
266
+ { ast(:quest, val[0], ast(:self, val[0]), val[0]) }
267
+ | call_iter
268
+ { ast(:quest, val[0], ast(:self, val[0]), val[0]) }
269
+ ;
270
+
271
+ quest_self:
272
+ T_QUEST questable { val[1] }
273
+ ;
274
+
275
+ quest:
276
+ arg_expr_atom T_QUEST questable { val[2].receiver = val[0]; val[2] }
277
+ ;
278
+
279
+ ##
280
+ # Argument lists
281
+
282
+ arg_to_proc:
283
+ T_OP_TOPROC arg_expr_atom { ast(:block_pass, val[0], nil, val[1]) }
284
+ ;
285
+
286
+ arg_splat:
287
+ T_OP_MULT arg_expr_atom { ast(:splat, val[0], val[1]) }
288
+ ;
289
+
290
+ in_arg_expr:
291
+ arg_expr
292
+ | arg_splat
293
+ | arg_to_proc
294
+ ;
295
+
296
+ in_arg_sepd_expr:
297
+ T_ARG_SEP { nil }
298
+ | T_ARG_SEP in_arg_expr { val[1] }
299
+ ;
300
+
301
+ in_arg_sepd_exprs:
302
+ in_arg_sepd_exprs in_arg_sepd_expr { [*val[0], val[1]].compact }
303
+ | in_arg_sepd_expr { val.compact }
304
+ ;
305
+
306
+ arg_list_:
307
+ in_arg_expr in_arg_sepd_exprs T_ARGS_END { ast(:array, val[0], [val[0], *val[1]]) }
308
+ | in_arg_sepd_exprs T_ARGS_END { val[0].empty? ? ast(:null, val[1]) : ast(:array, val[0][0], val[0]) }
309
+ | in_arg_expr T_ARGS_END { ast(:array, val[0], [val[0]]) }
310
+ | T_ARGS_END { ast(:array, val[0], []) }
311
+ ;
312
+
313
+ arg_list:
314
+ T_ARGS_BEGIN arg_list_ { args_assemble(val[0], val[1]) }
315
+ ;
316
+
317
+ ##
318
+ # Parameter lists
319
+
320
+ param:
321
+ T_IDENTIFIER
322
+ { [:required, val[0][1].to_sym] }
323
+ | T_IDENTIFIER T_ASSIGN arg_expr
324
+ { [:optional, ast(:lasgn, val[1], val[0][1].to_sym, val[2])] }
325
+ | T_OP_MULT T_IDENTIFIER
326
+ { [:rest, val[1][1].to_sym] }
327
+ | T_OP_TOPROC T_IDENTIFIER
328
+ { [:block, val[1][1].to_sym] }
329
+ ;
330
+
331
+ param_sepd:
332
+ T_ARG_SEP param { val[1] }
333
+ | T_ARG_SEP { nil }
334
+ ;
335
+
336
+ param_sepds:
337
+ param_sepds param_sepd { [*val[0], val[1]].compact }
338
+ | param_sepd { val.compact }
339
+ ;
340
+
341
+ param_list_:
342
+ param param_sepds T_PARAMS_END { [val[0], *val[1]] }
343
+ | param_sepds T_PARAMS_END { val[0] }
344
+ | param T_PARAMS_END { [val[0]] }
345
+ | T_PARAMS_END { [] }
346
+ ;
347
+
348
+ param_list:
349
+ T_PARAMS_BEGIN param_list_
350
+ {
351
+ required, optional, rest, block = 4.times.map { Array.new }
352
+
353
+ required << val[1].shift[1] while val[1][0] && val[1][0][0] == :required
354
+ optional << val[1].shift[1] while val[1][0] && val[1][0][0] == :optional
355
+ optional = optional.empty? ? nil : ast(:block, val[0], optional)
356
+ rest << val[1].shift[1] while val[1][0] && val[1][0][0] == :rest
357
+ block << val[1].shift[1] while val[1][0] && val[1][0][0] == :block
358
+
359
+ ast(:args, val[0], required, optional, rest.first, nil, nil, nil, block.first)
360
+ }
361
+ ;
362
+
363
+ ##
364
+ # Array literals
365
+
366
+ lit_array_:
367
+ in_arg_expr in_arg_sepd_exprs T_ARRAY_END { ast(:array, val[0], [val[0], *val[1]]) }
368
+ | in_arg_sepd_exprs T_ARRAY_END { val[0].empty? ? ast(:null, val[1]) : ast(:array, val[0][0], val[0]) }
369
+ | in_arg_expr T_ARRAY_END { ast(:array, val[0], [val[0]]) }
370
+ | T_ARRAY_END { ast(:array, val[0], []) }
371
+ ;
372
+
373
+ lit_array:
374
+ T_ARRAY_BEGIN lit_array_ { args_assemble(val[0], val[1]) }
375
+ ;
376
+
377
+ ##
378
+ # Two-term operators
379
+
380
+ two_term_expr:
381
+ arg_expr T_OP_PLUS arg_expr
382
+ { ast(:call, val[1], val[0], :'+', ast(:array, val[2], [val[2]])) }
383
+ | arg_expr T_OP_MINUS arg_expr
384
+ { ast(:call, val[1], val[0], :'-', ast(:array, val[2], [val[2]])) }
385
+ | arg_expr T_OP_MULT arg_expr
386
+ { ast(:call, val[1], val[0], :'*', ast(:array, val[2], [val[2]])) }
387
+ | arg_expr T_OP_DIV arg_expr
388
+ { ast(:call, val[1], val[0], :'/', ast(:array, val[2], [val[2]])) }
389
+ | arg_expr T_OP_MOD arg_expr
390
+ { ast(:call, val[1], val[0], :'%', ast(:array, val[2], [val[2]])) }
391
+ | arg_expr T_OP_EXP arg_expr
392
+ { ast(:call, val[1], val[0], :'**', ast(:array, val[2], [val[2]])) }
393
+ | arg_expr T_OP_COMPARE arg_expr
394
+ { ast(:call, val[1], val[0], val[1][1].to_sym, ast(:array, val[2], [val[2]])) }
395
+ | arg_expr T_OP_AND arg_expr
396
+ { ast(:and, val[1], val[0], val[2]) }
397
+ | arg_expr T_OP_OR arg_expr
398
+ { ast(:or, val[1], val[0], val[2]) }
399
+ ;
400
+
401
+ ##
402
+ # Object declarations
403
+
404
+ declobj_sepd_expr:
405
+ T_EXPR_SEP declobj_expr { val[1] }
406
+ | T_EXPR_SEP { nil }
407
+ ;
408
+
409
+ declobj_sepd_exprs:
410
+ declobj_sepd_exprs declobj_sepd_expr { [*val[0], val[1]].compact }
411
+ | declobj_sepd_expr { val.compact }
412
+ ;
413
+
414
+ declobj_expr_body:
415
+ declobj_expr declobj_sepd_exprs T_DECLARE_END { ast(:block, val[0], [val[0], *val[1]]) }
416
+ | declobj_sepd_exprs T_DECLARE_END { val[0].empty? ? ast(:null, val[1]) : ast(:block, val[0][0], val[0]) }
417
+ | declobj_expr T_DECLARE_END { ast(:block, val[0], [val[0]]) }
418
+ | T_DECLARE_END { ast(:null, val[0]) }
419
+ ;
420
+
421
+ declobj:
422
+ constant_list T_DECLARE_BEGIN declobj_expr_body
423
+ { ast(:declobj, val[1], val[0], val[2]) }
424
+ ;
425
+
426
+ cdefn:
427
+ constant T_DEFINE declobj
428
+ { ast(:cdefn, val[1], val[0], val[2]) }
429
+ ;
430
+
431
+ ##
432
+ # String declarations
433
+
434
+ declstr_body:
435
+ T_DECLSTR_BODY
436
+ { ast(:str, val[0], val[0][1]) }
437
+ ;
438
+
439
+ declstr:
440
+ constant_list T_DECLSTR_BEGIN declstr_body T_DECLSTR_END
441
+ { ast(:declstr, val[1], val[0], val[2]) }
442
+ ;
443
+
444
+ ##
445
+ # Memes and etc..
446
+
447
+ meme_sepd_expr:
448
+ T_EXPR_SEP meme_expr { val[1] }
449
+ | T_EXPR_SEP { nil }
450
+ ;
451
+
452
+ meme_sepd_exprs:
453
+ meme_sepd_exprs meme_sepd_expr { [*val[0], val[1]].compact }
454
+ | meme_sepd_expr { val.compact }
455
+ ;
456
+
457
+ meme_expr_body:
458
+ meme_expr meme_sepd_exprs T_MEME_END { ast(:block, val[0], [val[0], *val[1]]) }
459
+ | meme_sepd_exprs T_MEME_END { val[0].empty? ? ast(:null, val[1]) : ast(:block, val[0][0], val[0]) }
460
+ | meme_expr T_MEME_END { ast(:block, val[0], [val[0]]) }
461
+ | T_MEME_END { ast(:null, val[0]) }
462
+ ;
463
+
464
+ paren_expr_body:
465
+ meme_expr meme_sepd_exprs T_PAREN_END { ast(:block, val[0], [val[0], *val[1]]) }
466
+ | meme_sepd_exprs T_PAREN_END { val[0].empty? ? ast(:null, val[1]) : ast(:block, val[0][0], val[0]) }
467
+ | meme_expr T_PAREN_END { val[0] }
468
+ | T_PAREN_END { ast(:null, val[0]) }
469
+ ;
470
+
471
+ paren_expr:
472
+ T_PAREN_BEGIN paren_expr_body { val[1] }
473
+ ;
474
+
475
+ cmeme:
476
+ constant T_MEME_BEGIN meme_expr_body
477
+ { ast(:cdecl, val[1], val[0], val[2]) }
478
+ ;
479
+
480
+ meme_name:
481
+ id_as_symbol
482
+ | lit_string_as_symbol
483
+ ;
484
+
485
+ meme:
486
+ meme_name param_list T_MEME_BEGIN meme_expr_body
487
+ { ast(:meme, val[1], val[0], nil, val[1], val[3]) }
488
+ | meme_name T_MEME_BEGIN meme_expr_body
489
+ { ast(:meme, val[1], val[0], nil, nil, val[2]) }
490
+ | meme_name
491
+ { ast(:meme, val[0], val[0], nil, nil, nil) }
492
+ ;
493
+
494
+ deco_able:
495
+ meme
496
+ | deco
497
+ ;
498
+
499
+ deco:
500
+ T_IDENTIFIER deco_able
501
+ {
502
+ val[1].decorations.body.push ast(:lit, val[0], val[0][1].to_sym)
503
+ val[1]
504
+ }
505
+ ;
506
+
507
+ declid:
508
+ T_DECLID_TAG T_DECLID_VALUE
509
+ { ast(:declid, val[0], ast(:lit, val[1], val[1][1].to_sym)) }
510
+ ;
511
+
512
+ category:
513
+ T_CATEGORY_BEGIN T_CATEGORY_BODY T_CATEGORY_END
514
+ { ast(:category, val[0], ast(:lit, val[1], val[1][1].to_sym)) }
515
+ ;
516
+
517
+ ---- inner
518
+ attr_accessor :processor
519
+
520
+ def parse string
521
+ @tokens = Myco::ToolSet::Parser::Lexer.new(string).lex
522
+ do_parse
523
+ end
524
+
525
+ def next_token
526
+ tok = @tokens.shift
527
+ [ tok[0], tok ] if tok
528
+ end
529
+
530
+ # Generate an AST::Node of the given type
531
+ #
532
+ # @param type [Symbol] The type of AST::Node to generate
533
+ # @param locator [Array,AST::Node] The object from which to determine the
534
+ # source location where the AST::Node is to reference as its location.
535
+ # If it is an lexer token (Array), the location is pulled from it;
536
+ # if it is an AST::Node, the location for this node will be copied from it.
537
+ # @param args [Array] The arguments to pass to the processor method that
538
+ # will generate the AST::Node; usually the same as the arguments that will
539
+ # eventually be passed to the AST::Node's constructor.
540
+ #
541
+ def ast type, locator, *args
542
+ # TODO: integrate columns from location instead of just rows
543
+ line = locator.is_a?(Array) ? locator[2].first : locator.line
544
+ @processor.send :"process_#{type}", line, *args
545
+ end
546
+
547
+ def encode_escapes str
548
+ str.gsub /\\(.)/ do "#{$1}" end
549
+ end
550
+
551
+ # Given a locator and an ast(:array) node, refactor the splat-related nodes
552
+ # in a copy of the original node body and return a replacement for the node.
553
+ def args_assemble loc, orig_node
554
+ list = orig_node.body.dup
555
+ tmp = []
556
+
557
+ special_type_check = Proc.new { |x|
558
+ case x
559
+ when AST::SplatValue; :splat
560
+ when AST::ConcatArgs; :argscat
561
+ when AST::PushArgs; :argspush
562
+ when AST::BlockPass; :block_pass
563
+ else; nil
564
+ end
565
+ }
566
+
567
+ # Get the original value in the new_node
568
+ tmp << list.shift until list.empty? or special_type_check.call(list.first)
569
+ new_node = tmp.empty? ? list.shift : ast(:array, loc, tmp)
570
+
571
+ # Continue to reduce until all elements have been used
572
+ until list.empty?
573
+ arg = list.shift
574
+ type = special_type_check.call(arg)
575
+ if type == :block_pass
576
+ new_node = arg.tap { |n| n.arguments = new_node }
577
+ elsif type != nil
578
+ new_node = ast(:argscat, loc, new_node, arg)
579
+ else
580
+ new_node = ast(:argspush, loc, new_node, arg)
581
+ end
582
+ end
583
+
584
+ new_node || orig_node
585
+ end