ruby_parser 3.0.0 → 3.19.1

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 (58) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.autotest +36 -19
  4. data/History.rdoc +1297 -0
  5. data/Manifest.txt +35 -7
  6. data/{README.txt → README.rdoc} +44 -14
  7. data/Rakefile +308 -110
  8. data/bin/ruby_parse +3 -1
  9. data/bin/ruby_parse_extract_error +36 -16
  10. data/compare/normalize.rb +218 -0
  11. data/debugging.md +190 -0
  12. data/gauntlet.md +107 -0
  13. data/lib/.document +1 -0
  14. data/lib/rp_extensions.rb +53 -0
  15. data/lib/rp_stringscanner.rb +33 -0
  16. data/lib/ruby20_parser.rb +10973 -0
  17. data/lib/ruby20_parser.y +2683 -0
  18. data/lib/ruby21_parser.rb +10980 -0
  19. data/lib/ruby21_parser.y +2700 -0
  20. data/lib/ruby22_parser.rb +11123 -0
  21. data/lib/ruby22_parser.y +2711 -0
  22. data/lib/ruby23_parser.rb +11132 -0
  23. data/lib/ruby23_parser.y +2713 -0
  24. data/lib/ruby24_parser.rb +11231 -0
  25. data/lib/ruby24_parser.y +2721 -0
  26. data/lib/ruby25_parser.rb +11231 -0
  27. data/lib/ruby25_parser.y +2721 -0
  28. data/lib/ruby26_parser.rb +11253 -0
  29. data/lib/ruby26_parser.y +2736 -0
  30. data/lib/ruby27_parser.rb +12980 -0
  31. data/lib/ruby27_parser.y +3324 -0
  32. data/lib/ruby30_parser.rb +13242 -0
  33. data/lib/ruby30_parser.y +3447 -0
  34. data/lib/ruby31_parser.rb +13622 -0
  35. data/lib/ruby31_parser.y +3481 -0
  36. data/lib/ruby3_parser.yy +3536 -0
  37. data/lib/ruby_lexer.rb +933 -1232
  38. data/lib/ruby_lexer.rex +185 -0
  39. data/lib/ruby_lexer.rex.rb +399 -0
  40. data/lib/ruby_lexer_strings.rb +638 -0
  41. data/lib/ruby_parser.rb +97 -3
  42. data/lib/ruby_parser.yy +3465 -0
  43. data/lib/ruby_parser_extras.rb +1216 -687
  44. data/test/test_ruby_lexer.rb +2249 -1092
  45. data/test/test_ruby_parser.rb +5156 -975
  46. data/test/test_ruby_parser_extras.rb +47 -77
  47. data/tools/munge.rb +250 -0
  48. data/tools/ripper.rb +44 -0
  49. data.tar.gz.sig +1 -1
  50. metadata +200 -155
  51. metadata.gz.sig +0 -0
  52. data/.gemtest +0 -0
  53. data/History.txt +0 -482
  54. data/lib/gauntlet_rubyparser.rb +0 -120
  55. data/lib/ruby18_parser.rb +0 -5747
  56. data/lib/ruby18_parser.y +0 -1873
  57. data/lib/ruby19_parser.rb +0 -6110
  58. data/lib/ruby19_parser.y +0 -2078
@@ -0,0 +1,3481 @@
1
+ # -*- racc -*-
2
+
3
+ class Ruby31Parser
4
+
5
+ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
6
+ kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
7
+ kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
8
+ kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
9
+ kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
10
+ k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
11
+ tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
12
+ tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
13
+ tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
14
+ tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
15
+ tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
16
+ tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
17
+ tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
18
+ tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
19
+ tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
20
+ tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA
21
+ tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND
22
+ tRATIONAL tIMAGINARY
23
+ tLABEL_END
24
+ tLONELY
25
+ tBDOT2 tBDOT3
26
+
27
+ preclow
28
+ nonassoc tLOWEST
29
+ nonassoc tLBRACE_ARG
30
+ nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
31
+ left kOR kAND
32
+ right kNOT
33
+ nonassoc kDEFINED
34
+ right tEQL tOP_ASGN
35
+ left kRESCUE_MOD
36
+ right tEH tCOLON
37
+ nonassoc tDOT2 tDOT3 tBDOT2 tBDOT3
38
+ left tOROP
39
+ left tANDOP
40
+ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
41
+ left tGT tGEQ tLT tLEQ
42
+ left tPIPE tCARET
43
+ left tAMPER2
44
+ left tLSHFT tRSHFT
45
+ left tPLUS tMINUS
46
+ left tSTAR2 tDIVIDE tPERCENT # TODO: tSTAR2 -> tMULT
47
+ right tUMINUS_NUM tUMINUS
48
+ right tPOW
49
+ right tBANG tTILDE tUPLUS
50
+ prechigh
51
+
52
+ rule
53
+
54
+ program: {
55
+ self.lexer.lex_state = EXPR_BEG
56
+ }
57
+ top_compstmt
58
+ {
59
+ result = new_compstmt val
60
+
61
+ lexer.cond.pop # local_pop
62
+ lexer.cmdarg.pop
63
+ }
64
+
65
+ top_compstmt: top_stmts opt_terms
66
+ {
67
+ stmt, _ = val
68
+ result = stmt
69
+ }
70
+
71
+ top_stmts: none
72
+ | top_stmt
73
+ | top_stmts terms top_stmt
74
+ {
75
+ result = self.block_append val[0], val[2]
76
+ }
77
+ | error top_stmt
78
+
79
+ top_stmt: stmt
80
+ | klBEGIN
81
+ {
82
+ if (self.in_def || self.in_single > 0) then
83
+ debug 1
84
+ yyerror "BEGIN in method"
85
+ end
86
+ self.env.extend
87
+ }
88
+ begin_block
89
+ {
90
+ (_, lineno), _, iter = val
91
+ iter.line lineno
92
+
93
+ (_, preexe,) = iter
94
+ preexe.line lineno
95
+
96
+ result = iter
97
+ }
98
+
99
+ begin_block: tLCURLY { result = lexer.lineno } top_compstmt tRCURLY
100
+ {
101
+ _, line, stmt, _ = val
102
+ result = new_iter s(:preexe).line(line), 0, stmt
103
+ }
104
+
105
+ bodystmt: compstmt opt_rescue k_else
106
+ {
107
+ res = _values[-2]
108
+ yyerror "else without rescue is useless" unless res
109
+ }
110
+ compstmt
111
+ opt_ensure
112
+ {
113
+ body, resc, _, _, els, ens = val
114
+
115
+ result = new_body [body, resc, els, ens]
116
+ }
117
+ | compstmt opt_rescue opt_ensure
118
+ {
119
+ body, resc, ens = val
120
+
121
+ result = new_body [body, resc, nil, ens]
122
+ }
123
+
124
+ compstmt: stmts opt_terms
125
+ {
126
+ result = new_compstmt val
127
+ }
128
+
129
+ stmts: none
130
+ | stmt_or_begin # TODO: newline_node ?
131
+ | stmts terms stmt_or_begin
132
+ {
133
+ result = self.block_append val[0], val[2]
134
+ }
135
+ | error stmt
136
+ {
137
+ result = val[1]
138
+ debug 2
139
+ }
140
+
141
+ stmt_or_begin: stmt
142
+ | klBEGIN
143
+ {
144
+ yyerror "BEGIN is permitted only at toplevel"
145
+ }
146
+ begin_block
147
+ {
148
+ result = val[2] # wtf?
149
+ }
150
+
151
+ stmt: kALIAS fitem
152
+ {
153
+ lexer.lex_state = EXPR_FNAME
154
+ }
155
+ fitem
156
+ {
157
+ (_, line), lhs, _, rhs = val
158
+ result = s(:alias, lhs, rhs).line(line).line line
159
+ }
160
+ | kALIAS tGVAR tGVAR
161
+ {
162
+ (_, line), (lhs, _), (rhs, _) = val
163
+ result = s(:valias, lhs.to_sym, rhs.to_sym).line line
164
+ }
165
+ | kALIAS tGVAR tBACK_REF
166
+ {
167
+ (_, line), (lhs, _), (rhs, _) = val
168
+ result = s(:valias, lhs.to_sym, :"$#{rhs}").line line
169
+ }
170
+ | kALIAS tGVAR tNTH_REF
171
+ {
172
+ yyerror "can't make alias for the number variables"
173
+ }
174
+ | kUNDEF undef_list
175
+ {
176
+ result = val[1]
177
+ }
178
+ | stmt kIF_MOD expr_value
179
+ {
180
+ t, _, c = val
181
+ result = new_if c, t, nil
182
+ }
183
+ | stmt kUNLESS_MOD expr_value
184
+ {
185
+ f, _, c = val
186
+ result = new_if c, nil, f
187
+ }
188
+ | stmt kWHILE_MOD expr_value
189
+ {
190
+ e, _, c = val
191
+ result = new_while e, c, true
192
+ }
193
+ | stmt kUNTIL_MOD expr_value
194
+ {
195
+ e, _, c = val
196
+ result = new_until e, c, true
197
+ }
198
+ | stmt kRESCUE_MOD stmt
199
+ {
200
+ body, _, resbody = val
201
+
202
+ resbody = new_resbody s(:array).line(resbody.line), resbody
203
+ result = new_rescue body, resbody
204
+ }
205
+ | klEND tLCURLY compstmt tRCURLY
206
+ {
207
+ (_, line), _, stmt, _ = val
208
+
209
+ if (self.in_def || self.in_single > 0) then
210
+ debug 3
211
+ yyerror "END in method; use at_exit"
212
+ end
213
+
214
+ result = new_iter s(:postexe).line(line), 0, stmt
215
+ }
216
+ | command_asgn
217
+ | mlhs tEQL command_call
218
+ {
219
+ result = new_masgn val[0], val[2], :wrap
220
+ }
221
+ | lhs tEQL mrhs
222
+ {
223
+ lhs, _, rhs = val
224
+ result = new_assign lhs, s(:svalue, rhs).line(rhs.line)
225
+ }
226
+ | mlhs tEQL mrhs_arg kRESCUE_MOD stmt
227
+ {
228
+ # unwraps s(:to_ary, rhs)
229
+ lhs, _, (_, rhs), _, resbody = val
230
+
231
+ resbody = new_resbody s(:array).line(resbody.line), resbody
232
+
233
+ result = new_masgn lhs, new_rescue(rhs, resbody), :wrap
234
+ }
235
+ | mlhs tEQL mrhs_arg
236
+ {
237
+ result = new_masgn val[0], val[2]
238
+ }
239
+ | expr
240
+
241
+ command_asgn: lhs tEQL command_rhs
242
+ {
243
+ result = new_assign val[0], val[2]
244
+ }
245
+ # | lhs tEQL command_asgn
246
+ # {
247
+ # result = new_assign val[0], val[2]
248
+ # }
249
+ | var_lhs tOP_ASGN command_rhs
250
+ {
251
+ result = new_op_asgn val
252
+ }
253
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_rhs
254
+ {
255
+ result = new_op_asgn1 val
256
+ }
257
+ | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
258
+ {
259
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
260
+
261
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
262
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
263
+ result.line prim.line
264
+ }
265
+ | primary_value call_op tCONSTANT tOP_ASGN command_rhs
266
+ {
267
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
268
+
269
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
270
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
271
+ result.line prim.line
272
+ }
273
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
274
+ {
275
+ lhs1, _, (lhs2, line), (id, _), rhs = val
276
+
277
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
278
+ }
279
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
280
+ {
281
+ lhs1, _, (lhs2, line), (id, _), rhs = val
282
+
283
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
284
+ }
285
+ | defn_head f_opt_paren_args tEQL command
286
+ {
287
+ result = new_endless_defn val
288
+ }
289
+ | defn_head f_opt_paren_args tEQL command kRESCUE_MOD arg
290
+ {
291
+ result = new_endless_defn val
292
+ }
293
+ | defs_head f_opt_paren_args tEQL command
294
+ {
295
+ result = new_endless_defs val
296
+ }
297
+ | defs_head f_opt_paren_args tEQL command kRESCUE_MOD arg
298
+ {
299
+ result = new_endless_defs val
300
+ }
301
+ | backref tOP_ASGN command_rhs
302
+ {
303
+ self.backref_assign_error val[0]
304
+ }
305
+
306
+ command_rhs: command_call =tOP_ASGN
307
+ {
308
+ expr, = val
309
+ result = value_expr expr
310
+ }
311
+ | command_call kRESCUE_MOD stmt
312
+ {
313
+ expr, (_, line), resbody = val
314
+
315
+ expr = value_expr expr
316
+ ary = s(:array).line line
317
+ result = new_rescue(expr, new_resbody(ary, resbody))
318
+ }
319
+ | command_asgn
320
+
321
+ expr: command_call
322
+ | expr kAND expr
323
+ {
324
+ lhs, _, rhs = val
325
+ result = logical_op :and, lhs, rhs
326
+ }
327
+ | expr kOR expr
328
+ {
329
+ lhs, _, rhs = val
330
+ result = logical_op :or, lhs, rhs
331
+ }
332
+ | kNOT opt_nl expr
333
+ {
334
+ (_, line), _, expr = val
335
+ result = new_call(expr, :"!").line line
336
+ # REFACTOR: call_uni_op
337
+ }
338
+ | tBANG command_call
339
+ {
340
+ _, cmd = val
341
+ result = new_call(cmd, :"!").line cmd.line
342
+ # TODO: fix line number to tBANG... but causes BAD shift/reduce conflict
343
+ # REFACTOR: call_uni_op -- see parse26.y
344
+ }
345
+ | arg tASSOC
346
+ {
347
+ # value_expr($1);
348
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
349
+ self.lexer.command_start = false
350
+ result = self.in_kwarg
351
+ self.in_kwarg = true
352
+ self.env.extend
353
+ }
354
+ p_top_expr_body
355
+ {
356
+ lhs, _, in_kwarg, rhs = val
357
+
358
+ self.env.unextend
359
+ self.in_kwarg = in_kwarg
360
+
361
+ rhs = new_in rhs, nil, nil, rhs.line
362
+ result = new_case lhs, rhs, rhs.line
363
+ }
364
+ | arg
365
+ kIN
366
+ {
367
+ # TODO? value_expr($1);
368
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
369
+ self.lexer.command_start = false
370
+ result = self.in_kwarg
371
+ self.in_kwarg = true
372
+ self.env.extend
373
+ }
374
+ p_top_expr_body
375
+ {
376
+ self.env.unextend
377
+
378
+ expr, _, old_kwarg, pat = val
379
+
380
+ expr = value_expr expr
381
+
382
+ self.in_kwarg = old_kwarg
383
+ pat_in = new_in pat, nil, nil, expr.line
384
+ result = new_case expr, pat_in, expr.line
385
+ }
386
+ | arg =tLBRACE_ARG
387
+
388
+ def_name: fname
389
+ {
390
+ # TODO: numparam_name(p, fname);
391
+
392
+ (id, line), = val
393
+ old_in_def = self.in_def
394
+
395
+ self.in_def = true # group = local_push
396
+ self.env.extend
397
+ lexer.cmdarg.push false
398
+ lexer.cond.push false
399
+
400
+ result = [id.to_sym, line, old_in_def]
401
+ }
402
+ defn_head: k_def def_name
403
+ {
404
+ _, name = val
405
+ result = name
406
+ }
407
+ defs_head: k_def singleton dot_or_colon
408
+ {
409
+ lexer.lex_state = EXPR_FNAME
410
+ }
411
+ def_name
412
+ {
413
+ lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
414
+ self.in_single += 1 # TODO: remove?
415
+
416
+ # self.in_def = true # local_push
417
+ # self.env.extend
418
+ # lexer.cmdarg.push false
419
+ # lexer.cond.push false
420
+
421
+ _, recv, _, _, name = val
422
+
423
+ result = [recv, name]
424
+ }
425
+
426
+ expr_value: expr
427
+ {
428
+ result = value_expr(val[0])
429
+ }
430
+
431
+ expr_value_do: {
432
+ lexer.cond.push true
433
+ }
434
+ expr_value do
435
+ {
436
+ lexer.cond.pop
437
+ }
438
+ {
439
+ _, expr, _, _ = val
440
+ result = expr
441
+ }
442
+
443
+ command_call: command
444
+ | block_command
445
+
446
+ block_command: block_call
447
+ | block_call call_op2 operation2 command_args
448
+ {
449
+ blk, _, (msg, _line), args = val
450
+ result = new_call(blk, msg.to_sym, args).line blk.line
451
+ }
452
+
453
+ cmd_brace_block: tLBRACE_ARG
454
+ {
455
+ # self.env.extend(:dynamic)
456
+ result = self.lexer.lineno
457
+ }
458
+ brace_body tRCURLY
459
+ {
460
+ _, line, body, _ = val
461
+
462
+ result = body
463
+ result.line line
464
+
465
+ # self.env.unextend
466
+ }
467
+
468
+ fcall: operation
469
+ {
470
+ (msg, line), = val
471
+ result = new_call(nil, msg.to_sym).line line
472
+ }
473
+
474
+ command: fcall command_args =tLOWEST
475
+ {
476
+ call, args = val
477
+ result = call.concat args.sexp_body
478
+ }
479
+ | fcall command_args cmd_brace_block
480
+ {
481
+ call, args, block = val
482
+
483
+ result = call.concat args.sexp_body
484
+
485
+ if block then
486
+ block_dup_check result, block
487
+
488
+ result, operation = block, result
489
+ result.insert 1, operation
490
+ end
491
+ }
492
+ | primary_value call_op operation2 command_args =tLOWEST
493
+ {
494
+ lhs, callop, (op, _), args = val
495
+
496
+ result = new_call lhs, op.to_sym, args, callop
497
+ result.line lhs.line
498
+ }
499
+ | primary_value call_op operation2 command_args cmd_brace_block
500
+ {
501
+ recv, _, (msg, _line), args, block = val
502
+ call = new_call recv, msg.to_sym, args, val[1]
503
+
504
+ block_dup_check call, block
505
+
506
+ block.insert 1, call
507
+ result = block
508
+ }
509
+ | primary_value tCOLON2 operation2 command_args =tLOWEST
510
+ {
511
+ lhs, _, (id, line), args = val
512
+
513
+ result = new_call lhs, id.to_sym, args
514
+ result.line line
515
+ }
516
+ | primary_value tCOLON2 operation2 command_args cmd_brace_block
517
+ {
518
+ recv, _, (msg, _line), args, block = val
519
+ call = new_call recv, msg.to_sym, args
520
+
521
+ block_dup_check call, block
522
+
523
+ block.insert 1, call
524
+ result = block
525
+ }
526
+ | kSUPER command_args
527
+ {
528
+ result = new_super val[1]
529
+ }
530
+ | kYIELD command_args
531
+ {
532
+ (_, line), args = val
533
+ result = new_yield args
534
+ result.line line # TODO: push to new_yield
535
+ }
536
+ | k_return call_args
537
+ {
538
+ line = val[0].last
539
+ result = s(:return, ret_args(val[1])).line(line)
540
+ }
541
+ | kBREAK call_args
542
+ {
543
+ (_, line), args = val
544
+ result = s(:break, ret_args(args)).line line
545
+ }
546
+ | kNEXT call_args
547
+ {
548
+ line = val[0].last
549
+ result = s(:next, ret_args(val[1])).line(line)
550
+ }
551
+
552
+ mlhs: mlhs_basic
553
+ | tLPAREN mlhs_inner rparen
554
+ {
555
+ result = val[1]
556
+ }
557
+
558
+ mlhs_inner: mlhs_basic
559
+ | tLPAREN mlhs_inner rparen
560
+ {
561
+ _, arg, _ = val
562
+ l = arg.line
563
+
564
+ result = s(:masgn, s(:array, arg).line(l)).line l
565
+ }
566
+
567
+ mlhs_basic: mlhs_head
568
+ {
569
+ head, = val
570
+ result = s(:masgn, head).line head.line
571
+ }
572
+ | mlhs_head mlhs_item
573
+ {
574
+ lhs, rhs = val
575
+ result = s(:masgn, lhs << rhs.compact).line lhs.line
576
+ }
577
+ | mlhs_head tSTAR mlhs_node
578
+ {
579
+ head, _, tail = val
580
+ head << s(:splat, tail).line(tail.line)
581
+ result = s(:masgn, head).line head.line
582
+ }
583
+ | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
584
+ {
585
+ ary1, _, splat, _, ary2 = val
586
+
587
+ result = list_append ary1, s(:splat, splat).line(splat.line)
588
+ result.concat ary2.sexp_body
589
+ result = s(:masgn, result).line result.line
590
+ }
591
+ | mlhs_head tSTAR
592
+ {
593
+ head, _ = val
594
+ l = head.line
595
+ result = s(:masgn, head << s(:splat).line(l)).line l
596
+ }
597
+ | mlhs_head tSTAR tCOMMA mlhs_post
598
+ {
599
+ head, _, _, post = val
600
+ ary = list_append head, s(:splat).line(head.line)
601
+ ary.concat post.sexp_body
602
+ result = s(:masgn, ary).line ary.line
603
+ }
604
+ | tSTAR mlhs_node
605
+ {
606
+ _, node = val
607
+ l = node.line
608
+ splat = s(:splat, node).line l
609
+ ary = s(:array, splat).line l
610
+ result = s(:masgn, ary).line l
611
+ }
612
+ | tSTAR mlhs_node tCOMMA mlhs_post
613
+ {
614
+ _, node, _, post = val
615
+
616
+ splat = s(:splat, node).line node.line
617
+ ary = s(:array, splat).line splat.line
618
+ ary.concat post.sexp_body
619
+ result = s(:masgn, ary).line ary.line
620
+ }
621
+ | tSTAR
622
+ {
623
+ l = lexer.lineno
624
+ result = s(:masgn, s(:array, s(:splat).line(l)).line(l)).line l
625
+ }
626
+ | tSTAR tCOMMA mlhs_post
627
+ {
628
+ _, _, post = val
629
+ l = post.line
630
+
631
+ splat = s(:splat).line l
632
+ ary = s(:array, splat, *post.sexp_body).line l
633
+ result = s(:masgn, ary).line l
634
+ }
635
+
636
+ mlhs_item: mlhs_node
637
+ | tLPAREN mlhs_inner rparen
638
+ {
639
+ result = val[1]
640
+ }
641
+
642
+ mlhs_head: mlhs_item tCOMMA
643
+ {
644
+ lhs, _ = val
645
+ result = s(:array, lhs).line lhs.line
646
+ }
647
+ | mlhs_head mlhs_item tCOMMA
648
+ {
649
+ result = val[0] << val[1].compact
650
+ }
651
+
652
+ mlhs_post: mlhs_item
653
+ {
654
+ item, = val
655
+ result = s(:array, item).line item.line
656
+ }
657
+ | mlhs_post tCOMMA mlhs_item
658
+ {
659
+ result = list_append val[0], val[2]
660
+ }
661
+
662
+ mlhs_node: user_variable
663
+ {
664
+ result = self.assignable val[0]
665
+ }
666
+ | keyword_variable
667
+ {
668
+ result = self.assignable val[0]
669
+ }
670
+ | primary_value tLBRACK2 opt_call_args rbracket
671
+ {
672
+ result = self.aryset val[0], val[2]
673
+ }
674
+ | primary_value call_op tIDENTIFIER
675
+ {
676
+ lhs, call_op, (id, _line) = val
677
+
678
+ result = new_attrasgn lhs, id, call_op
679
+ }
680
+ | primary_value tCOLON2 tIDENTIFIER
681
+ {
682
+ recv, _, (id, _line) = val
683
+ result = new_attrasgn recv, id
684
+ }
685
+ | primary_value call_op tCONSTANT
686
+ {
687
+ lhs, call_op, (id, _line) = val
688
+
689
+ result = new_attrasgn lhs, id, call_op
690
+ }
691
+ | primary_value tCOLON2 tCONSTANT
692
+ {
693
+ if (self.in_def || self.in_single > 0) then
694
+ debug 4
695
+ yyerror "dynamic constant assignment"
696
+ end
697
+
698
+ expr, _, (id, _line) = val
699
+ l = expr.line
700
+
701
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l), nil).line l
702
+ }
703
+ | tCOLON3 tCONSTANT
704
+ {
705
+ if (self.in_def || self.in_single > 0) then
706
+ debug 5
707
+ yyerror "dynamic constant assignment"
708
+ end
709
+
710
+ _, (id, l) = val
711
+
712
+ result = s(:const, nil, s(:colon3, id.to_sym).line(l)).line l
713
+ }
714
+ | backref
715
+ {
716
+ ref, = val
717
+
718
+ self.backref_assign_error ref
719
+ }
720
+
721
+ lhs: user_variable
722
+ {
723
+ var, = val
724
+
725
+ result = self.assignable var
726
+ }
727
+ | keyword_variable
728
+ {
729
+ var, = val
730
+
731
+ result = self.assignable var
732
+
733
+ debug 6
734
+ }
735
+ | primary_value tLBRACK2 opt_call_args rbracket
736
+ {
737
+ lhs, _, args, _ = val
738
+
739
+ result = self.aryset lhs, args
740
+ }
741
+ | primary_value call_op tIDENTIFIER # REFACTOR
742
+ {
743
+ lhs, op, (id, _line) = val
744
+
745
+ result = new_attrasgn lhs, id, op
746
+ }
747
+ | primary_value tCOLON2 tIDENTIFIER
748
+ {
749
+ lhs, _, (id, _line) = val
750
+
751
+ result = new_attrasgn lhs, id
752
+ }
753
+ | primary_value call_op tCONSTANT # REFACTOR?
754
+ {
755
+ lhs, call_op, (id, _line) = val
756
+
757
+ result = new_attrasgn lhs, id, call_op
758
+ }
759
+ | primary_value tCOLON2 tCONSTANT
760
+ {
761
+ expr, _, (id, _line) = val
762
+
763
+ if (self.in_def || self.in_single > 0) then
764
+ debug 7
765
+ yyerror "dynamic constant assignment"
766
+ end
767
+
768
+ l = expr.line
769
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l)).line l
770
+ }
771
+ | tCOLON3 tCONSTANT
772
+ {
773
+ _, (id, l) = val
774
+
775
+ if (self.in_def || self.in_single > 0) then
776
+ debug 8
777
+ yyerror "dynamic constant assignment"
778
+ end
779
+
780
+ result = s(:const, s(:colon3, id.to_sym).line(l)).line l
781
+ }
782
+ | backref
783
+ {
784
+ self.backref_assign_error val[0]
785
+ }
786
+
787
+ cname: tIDENTIFIER
788
+ {
789
+ yyerror "class/module name must be CONSTANT"
790
+ }
791
+ | tCONSTANT
792
+
793
+ cpath: tCOLON3 cname
794
+ {
795
+ result = wrap :colon3, val[1]
796
+ }
797
+ | cname
798
+ {
799
+ (id, line), = val
800
+ result = [id.to_sym, line] # TODO: sexp?
801
+ }
802
+ | primary_value tCOLON2 cname
803
+ {
804
+ pval, _, (name, _line) = val
805
+
806
+ result = s(:colon2, pval, name.to_sym)
807
+ result.line pval.line
808
+ }
809
+
810
+ fname: tIDENTIFIER | tCONSTANT | tFID
811
+ | op
812
+ {
813
+ lexer.lex_state = EXPR_END
814
+ }
815
+
816
+ | reswords
817
+
818
+ fitem: fname
819
+ {
820
+ result = wrap :lit, val[0]
821
+ }
822
+ | symbol
823
+
824
+ undef_list: fitem
825
+ {
826
+ result = new_undef val[0]
827
+ }
828
+ |
829
+ undef_list tCOMMA
830
+ {
831
+ lexer.lex_state = EXPR_FNAME
832
+ }
833
+ fitem
834
+ {
835
+ result = new_undef val[0], val[3]
836
+ }
837
+
838
+ op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
839
+ | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
840
+ | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
841
+ | tSTAR | tDIVIDE | tPERCENT | tPOW | tDSTAR | tBANG | tTILDE
842
+ | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
843
+
844
+ reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
845
+ | kALIAS | kAND | kBEGIN | kBREAK | kCASE
846
+ | kCLASS | kDEF | kDEFINED | kDO | kELSE
847
+ | kELSIF | kEND | kENSURE | kFALSE | kFOR
848
+ | kIN | kMODULE | kNEXT | kNIL | kNOT
849
+ | kOR | kREDO | kRESCUE | kRETRY | kRETURN
850
+ | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
851
+ | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
852
+ | kUNTIL
853
+
854
+ arg: lhs tEQL arg_rhs
855
+ {
856
+ result = new_assign val[0], val[2]
857
+ }
858
+ | var_lhs tOP_ASGN arg_rhs
859
+ {
860
+ result = new_op_asgn val
861
+ }
862
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg_rhs
863
+ {
864
+ result = new_op_asgn1 val
865
+ }
866
+ | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
867
+ {
868
+ result = new_op_asgn2 val
869
+ }
870
+ | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
871
+ {
872
+ result = new_op_asgn2 val
873
+ }
874
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
875
+ {
876
+ lhs, _, (id, _line), (op, _), rhs = val
877
+
878
+ result = s(:op_asgn, lhs, rhs, id.to_sym, op.to_sym).line lhs.line
879
+ }
880
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
881
+ {
882
+ lhs1, _, (lhs2, _line), op, rhs = val
883
+
884
+ lhs = s(:colon2, lhs1, lhs2.to_sym).line lhs1.line
885
+ result = new_const_op_asgn [lhs, op, rhs]
886
+ }
887
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
888
+ {
889
+ _, lhs, op, rhs = val
890
+
891
+ lhs = wrap :colon3, lhs
892
+ result = new_const_op_asgn [lhs, op, rhs]
893
+ }
894
+ | backref tOP_ASGN arg_rhs
895
+ {
896
+ # TODO: lhs = var_field val[0]
897
+ asgn = new_op_asgn val
898
+ result = self.backref_assign_error asgn
899
+ }
900
+ | arg tDOT2 arg
901
+ {
902
+ v1, v2 = val[0], val[2]
903
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
904
+ result = s(:lit, (v1.last)..(v2.last)).line v1.line
905
+ else
906
+ result = s(:dot2, v1, v2).line v1.line
907
+ end
908
+ }
909
+ | arg tDOT3 arg
910
+ {
911
+ v1, v2 = val[0], val[2]
912
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
913
+ result = s(:lit, (v1.last)...(v2.last)).line v1.line
914
+ else
915
+ result = s(:dot3, v1, v2).line v1.line
916
+ end
917
+ }
918
+ | arg tDOT2
919
+ {
920
+ v1, _ = val
921
+ v2 = nil
922
+
923
+ result = s(:dot2, v1, v2).line v1.line
924
+ }
925
+ | arg tDOT3
926
+ {
927
+ v1, _ = val
928
+ v2 = nil
929
+
930
+ result = s(:dot3, v1, v2).line v1.line
931
+ }
932
+
933
+ | tBDOT2 arg
934
+ {
935
+ _, v2, = val
936
+ v1 = nil
937
+
938
+ result = s(:dot2, v1, v2).line v2.line
939
+ }
940
+ | tBDOT3 arg
941
+ {
942
+ _, v2 = val
943
+ v1 = nil
944
+
945
+ result = s(:dot3, v1, v2).line v2.line
946
+ }
947
+
948
+ | arg tPLUS arg
949
+ {
950
+ result = new_call val[0], :+, argl(val[2])
951
+ }
952
+ | arg tMINUS arg
953
+ {
954
+ result = new_call val[0], :-, argl(val[2])
955
+ }
956
+ | arg tSTAR2 arg # TODO: rename
957
+ {
958
+ result = new_call val[0], :*, argl(val[2])
959
+ }
960
+ | arg tDIVIDE arg
961
+ {
962
+ result = new_call val[0], :"/", argl(val[2])
963
+ }
964
+ | arg tPERCENT arg
965
+ {
966
+ result = new_call val[0], :"%", argl(val[2])
967
+ }
968
+ | arg tPOW arg
969
+ {
970
+ result = new_call val[0], :**, argl(val[2])
971
+ }
972
+ | tUMINUS_NUM simple_numeric tPOW arg
973
+ {
974
+ _, num, _, arg = val
975
+ lit = wrap :lit, num
976
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
977
+
978
+ }
979
+ | tUPLUS arg
980
+ {
981
+ result = new_call val[1], :"+@"
982
+ }
983
+ | tUMINUS arg
984
+ {
985
+ result = new_call val[1], :"-@"
986
+ }
987
+ | arg tPIPE arg
988
+ {
989
+ result = new_call val[0], :"|", argl(val[2])
990
+ }
991
+ | arg tCARET arg
992
+ {
993
+ result = new_call val[0], :"^", argl(val[2])
994
+ }
995
+ | arg tAMPER2 arg
996
+ {
997
+ result = new_call val[0], :"&", argl(val[2])
998
+ }
999
+ | arg tCMP arg
1000
+ {
1001
+ result = new_call val[0], :"<=>", argl(val[2])
1002
+ }
1003
+ | rel_expr =tCMP
1004
+ | arg tEQ arg
1005
+ {
1006
+ result = new_call val[0], :"==", argl(val[2])
1007
+ }
1008
+ | arg tEQQ arg
1009
+ {
1010
+ result = new_call val[0], :"===", argl(val[2])
1011
+ }
1012
+ | arg tNEQ arg
1013
+ {
1014
+ result = new_call val[0], :"!=", argl(val[2])
1015
+ }
1016
+ | arg tMATCH arg
1017
+ {
1018
+ lhs, _, rhs = val
1019
+ result = new_match lhs, rhs
1020
+ }
1021
+ | arg tNMATCH arg
1022
+ {
1023
+ lhs, _, rhs = val
1024
+ result = s(:not, new_match(lhs, rhs)).line lhs.line
1025
+ }
1026
+ | tBANG arg
1027
+ {
1028
+ _, arg = val
1029
+ result = new_call arg, :"!"
1030
+ result.line arg.line
1031
+ }
1032
+ | tTILDE arg
1033
+ {
1034
+ result = new_call value_expr(val[1]), :"~"
1035
+ }
1036
+ | arg tLSHFT arg
1037
+ {
1038
+ val[0] = value_expr val[0]
1039
+ val[2] = value_expr val[2]
1040
+ result = new_call val[0], :"\<\<", argl(val[2])
1041
+ }
1042
+ | arg tRSHFT arg
1043
+ {
1044
+ val[0] = value_expr val[0]
1045
+ val[2] = value_expr val[2]
1046
+ result = new_call val[0], :">>", argl(val[2])
1047
+ }
1048
+ | arg tANDOP arg
1049
+ {
1050
+ result = logical_op :and, val[0], val[2]
1051
+ }
1052
+ | arg tOROP arg
1053
+ {
1054
+ result = logical_op :or, val[0], val[2]
1055
+ }
1056
+ | kDEFINED opt_nl arg
1057
+ {
1058
+ (_, line), _, arg = val
1059
+ result = s(:defined, arg).line line
1060
+ }
1061
+ | arg tEH arg opt_nl tCOLON arg
1062
+ {
1063
+ c, _, t, _, _, f = val
1064
+ result = s(:if, c, t, f).line c.line
1065
+ }
1066
+ | defn_head f_opt_paren_args tEQL arg
1067
+ {
1068
+ result = new_endless_defn val
1069
+ }
1070
+ | defn_head f_opt_paren_args tEQL arg kRESCUE_MOD arg
1071
+ {
1072
+ result = new_endless_defn val
1073
+ }
1074
+ | defs_head f_opt_paren_args tEQL arg
1075
+ {
1076
+ result = new_endless_defs val
1077
+ }
1078
+ | defs_head f_opt_paren_args tEQL arg kRESCUE_MOD arg
1079
+ {
1080
+ result = new_endless_defs val
1081
+ }
1082
+ | primary
1083
+
1084
+ relop: tGT
1085
+ | tLT
1086
+ | tGEQ
1087
+ | tLEQ
1088
+
1089
+ rel_expr: arg relop arg =tGT
1090
+ {
1091
+ lhs, (op, _), rhs = val
1092
+ result = new_call lhs, op.to_sym, argl(rhs)
1093
+ }
1094
+ | rel_expr relop arg =tGT
1095
+ {
1096
+ lhs, (op, _), rhs = val
1097
+ warn "comparison '%s' after comparison", op
1098
+ result = new_call lhs, op.to_sym, argl(rhs)
1099
+ }
1100
+
1101
+ arg_value: arg
1102
+ {
1103
+ result = value_expr(val[0])
1104
+ }
1105
+
1106
+ aref_args: none
1107
+ | args trailer
1108
+ {
1109
+ result = args [val[0]]
1110
+ }
1111
+ | args tCOMMA assocs trailer
1112
+ {
1113
+ result = args [val[0], array_to_hash(val[2])]
1114
+ }
1115
+ | assocs trailer
1116
+ {
1117
+ result = args [array_to_hash(val[0])]
1118
+ }
1119
+
1120
+ arg_rhs: arg =tOP_ASGN
1121
+ | arg kRESCUE_MOD arg
1122
+ {
1123
+ body, (_, line), resbody = val
1124
+ body = value_expr body
1125
+ resbody = remove_begin resbody
1126
+
1127
+ ary = s(:array).line line
1128
+ result = new_rescue(body, new_resbody(ary, resbody))
1129
+ }
1130
+
1131
+ paren_args: tLPAREN2 opt_call_args rparen
1132
+ {
1133
+ _, args, _ = val
1134
+ result = args
1135
+ }
1136
+ | tLPAREN2 args tCOMMA args_forward rparen
1137
+ {
1138
+ yyerror "Unexpected ..." unless
1139
+ self.lexer.is_local_id(:"*") &&
1140
+ self.lexer.is_local_id(:"**") &&
1141
+ self.lexer.is_local_id(:"&")
1142
+
1143
+ result = call_args val
1144
+ }
1145
+ | tLPAREN2 args_forward rparen
1146
+ {
1147
+ yyerror "Unexpected ..." unless
1148
+ self.lexer.is_local_id(:"*") &&
1149
+ self.lexer.is_local_id(:"**") &&
1150
+ self.lexer.is_local_id(:"&")
1151
+
1152
+ result = call_args val
1153
+ }
1154
+
1155
+ opt_paren_args: none
1156
+ | paren_args
1157
+
1158
+ opt_call_args: none
1159
+ | call_args
1160
+ | args tCOMMA
1161
+ {
1162
+ result = args val
1163
+ }
1164
+ | args tCOMMA assocs tCOMMA
1165
+ {
1166
+ result = args [val[0], array_to_hash(val[2])]
1167
+ }
1168
+ | assocs tCOMMA
1169
+ {
1170
+ result = args [array_to_hash(val[0])]
1171
+ }
1172
+
1173
+ call_args: command
1174
+ {
1175
+ warning "parenthesize argument(s) for future version"
1176
+ result = call_args val
1177
+ }
1178
+ | args opt_block_arg
1179
+ {
1180
+ result = call_args val
1181
+ }
1182
+ | assocs opt_block_arg
1183
+ {
1184
+ result = call_args [array_to_hash(val[0]), val[1]]
1185
+ }
1186
+ | args tCOMMA assocs opt_block_arg
1187
+ {
1188
+ result = call_args [val[0], array_to_hash(val[2]), val[3]]
1189
+ }
1190
+ | block_arg
1191
+ {
1192
+ result = call_args val
1193
+ }
1194
+
1195
+ command_args: {
1196
+ # parse26.y line 2200
1197
+
1198
+ # If call_args starts with a open paren '(' or
1199
+ # '[', look-ahead reading of the letters calls
1200
+ # CMDARG_PUSH(0), but the push must be done
1201
+ # after CMDARG_PUSH(1). So this code makes them
1202
+ # consistent by first cancelling the premature
1203
+ # CMDARG_PUSH(0), doing CMDARG_PUSH(1), and
1204
+ # finally redoing CMDARG_PUSH(0).
1205
+
1206
+ result = yychar = self.last_token_type.first
1207
+ lookahead = [:tLPAREN, :tLPAREN_ARG, :tLPAREN2, :tLBRACK, :tLBRACK2].include?(yychar)
1208
+ lexer.cmdarg.pop if lookahead
1209
+ lexer.cmdarg.push true
1210
+ lexer.cmdarg.push false if lookahead
1211
+ }
1212
+ call_args
1213
+ {
1214
+ yychar, args = val
1215
+
1216
+ # call_args can be followed by tLBRACE_ARG (that
1217
+ # does CMDARG_PUSH(0) in the lexer) but the push
1218
+ # must be done after CMDARG_POP() in the parser.
1219
+ # So this code does CMDARG_POP() to pop 0 pushed
1220
+ # by tLBRACE_ARG, CMDARG_POP() to pop 1 pushed
1221
+ # by command_args, and CMDARG_PUSH(0) to restore
1222
+ # back the flag set by tLBRACE_ARG.
1223
+
1224
+ lookahead = [:tLBRACE_ARG].include?(yychar)
1225
+ lexer.cmdarg.pop if lookahead
1226
+ lexer.cmdarg.pop
1227
+ lexer.cmdarg.push false if lookahead
1228
+ result = args
1229
+ }
1230
+
1231
+ block_arg: tAMPER arg_value
1232
+ {
1233
+ _, arg = val
1234
+ result = s(:block_pass, arg).line arg.line
1235
+ }
1236
+ | tAMPER
1237
+ {
1238
+ (_, line), = val
1239
+ result = s(:block_pass).line line
1240
+ }
1241
+
1242
+ opt_block_arg: tCOMMA block_arg
1243
+ {
1244
+ result = val[1]
1245
+ }
1246
+ | none
1247
+
1248
+ args: arg_value
1249
+ {
1250
+ arg, = val
1251
+ lineno = arg.line || lexer.lineno # HACK
1252
+
1253
+ result = s(:array, arg).line lineno
1254
+ }
1255
+ | tSTAR arg_value
1256
+ {
1257
+ _, arg = val
1258
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
1259
+ }
1260
+ | args tCOMMA arg_value
1261
+ {
1262
+ args, _, id = val
1263
+ result = self.list_append args, id
1264
+ }
1265
+ | args tCOMMA tSTAR arg_value
1266
+ {
1267
+ # TODO: the line number from tSTAR has been dropped
1268
+ args, _, _, id = val
1269
+ line = lexer.lineno
1270
+ result = self.list_append args, s(:splat, id).line(line)
1271
+ }
1272
+
1273
+ mrhs_arg: mrhs
1274
+ {
1275
+ result = new_masgn_arg val[0]
1276
+ }
1277
+ | arg_value
1278
+ {
1279
+ result = new_masgn_arg val[0], :wrap
1280
+ }
1281
+
1282
+ mrhs: args tCOMMA arg_value
1283
+ {
1284
+ result = val[0] << val[2]
1285
+ }
1286
+ | args tCOMMA tSTAR arg_value
1287
+ {
1288
+ # TODO: make all tXXXX terminals include lexer.lineno
1289
+ arg, _, _, splat = val
1290
+ result = self.arg_concat arg, splat
1291
+ }
1292
+ | tSTAR arg_value
1293
+ {
1294
+ _, arg = val
1295
+ result = s(:splat, arg).line arg.line
1296
+ }
1297
+
1298
+ primary: literal
1299
+ | strings
1300
+ | xstring
1301
+ | regexp
1302
+ | words
1303
+ | qwords
1304
+ | symbols
1305
+ | qsymbols
1306
+ | var_ref
1307
+ | backref
1308
+ | tFID
1309
+ {
1310
+ (msg, line), = val
1311
+ result = new_call nil, msg.to_sym
1312
+ result.line line
1313
+ }
1314
+ | k_begin
1315
+ {
1316
+ lexer.cmdarg.push false
1317
+ result = self.lexer.lineno
1318
+ }
1319
+ bodystmt k_end
1320
+ {
1321
+ lexer.cmdarg.pop
1322
+ result = new_begin val
1323
+ }
1324
+ | tLPAREN_ARG
1325
+ {
1326
+ lexer.lex_state = EXPR_ENDARG
1327
+ result = lexer.lineno
1328
+ }
1329
+ rparen
1330
+ {
1331
+ _, line, _ = val
1332
+ result = s(:begin).line line
1333
+ }
1334
+ | tLPAREN_ARG
1335
+ stmt
1336
+ {
1337
+ lexer.lex_state = EXPR_ENDARG
1338
+ }
1339
+ rparen
1340
+ {
1341
+ _, stmt, _, _, = val
1342
+ # warning "(...) interpreted as grouped expression"
1343
+ result = stmt
1344
+ }
1345
+ | tLPAREN compstmt tRPAREN
1346
+ {
1347
+ _, stmt, _ = val
1348
+ result = stmt
1349
+ result ||= s(:nil).line lexer.lineno
1350
+ result.paren = true
1351
+ }
1352
+ | primary_value tCOLON2 tCONSTANT
1353
+ {
1354
+ expr, _, (id, _line) = val
1355
+
1356
+ result = s(:colon2, expr, id.to_sym).line expr.line
1357
+ }
1358
+ | tCOLON3 tCONSTANT
1359
+ {
1360
+ result = wrap :colon3, val[1]
1361
+ }
1362
+ | tLBRACK { result = lexer.lineno } aref_args tRBRACK
1363
+ {
1364
+ _, line, args, _ = val
1365
+ result = args || s(:array)
1366
+ result.sexp_type = :array # aref_args is :args
1367
+ result.line line
1368
+ }
1369
+ | tLBRACE
1370
+ {
1371
+ result = self.lexer.lineno
1372
+ }
1373
+ assoc_list tRCURLY
1374
+ {
1375
+ result = new_hash val
1376
+ }
1377
+ | k_return
1378
+ {
1379
+ (_, line), = val
1380
+ result = s(:return).line line
1381
+ }
1382
+ | kYIELD tLPAREN2 call_args rparen
1383
+ {
1384
+ (_, line), _, args, _ = val
1385
+
1386
+ result = new_yield(args).line line
1387
+ }
1388
+ | kYIELD tLPAREN2 rparen
1389
+ {
1390
+ (_, line), _, _ = val
1391
+
1392
+ result = new_yield.line line
1393
+ }
1394
+ | kYIELD
1395
+ {
1396
+ (_, line), = val
1397
+
1398
+ result = new_yield.line line
1399
+ }
1400
+ | kDEFINED opt_nl tLPAREN2 expr rparen
1401
+ {
1402
+ (_, line), _, _, arg, _ = val
1403
+
1404
+ result = s(:defined, arg).line line
1405
+ }
1406
+ | kNOT tLPAREN2 expr rparen
1407
+ {
1408
+ _, _, lhs, _ = val
1409
+ result = new_call lhs, :"!"
1410
+ }
1411
+ | kNOT tLPAREN2 rparen
1412
+ {
1413
+ debug 9
1414
+ }
1415
+ | fcall brace_block
1416
+ {
1417
+ call, iter = val
1418
+
1419
+ iter.insert 1, call
1420
+ result = iter
1421
+ # FIX: probably not: call.line = iter.line
1422
+ }
1423
+ | method_call
1424
+ | method_call brace_block
1425
+ {
1426
+ call, iter = val[0], val[1]
1427
+ block_dup_check call, iter
1428
+ iter.insert 1, call # FIX
1429
+ result = iter
1430
+ }
1431
+ | lambda
1432
+ {
1433
+ expr, = val
1434
+ result = expr
1435
+ }
1436
+ | k_if expr_value then compstmt if_tail k_end
1437
+ {
1438
+ _, c, _, t, f, _ = val
1439
+ result = new_if c, t, f
1440
+ }
1441
+ | k_unless expr_value then compstmt opt_else k_end
1442
+ {
1443
+ _, c, _, t, f, _ = val
1444
+ result = new_if c, f, t
1445
+ }
1446
+ | k_while expr_value_do compstmt k_end
1447
+ {
1448
+ _, cond, body, _ = val
1449
+ result = new_while body, cond, true
1450
+ }
1451
+ | k_until expr_value_do compstmt k_end
1452
+ {
1453
+ _, cond, body, _ = val
1454
+ result = new_until body, cond, true
1455
+ }
1456
+ | k_case expr_value opt_terms case_body k_end
1457
+ {
1458
+ (_, line), expr, _, body, _ = val
1459
+ result = new_case expr, body, line
1460
+ }
1461
+ | k_case opt_terms case_body k_end
1462
+ {
1463
+ (_, line), _, body, _ = val
1464
+ result = new_case nil, body, line
1465
+ }
1466
+ | k_case expr_value opt_terms p_case_body k_end
1467
+ {
1468
+ (_, line), expr, _, body, _ = val
1469
+
1470
+ result = new_case expr, body, line
1471
+ }
1472
+ | k_for for_var kIN expr_value_do compstmt k_end
1473
+ {
1474
+ _, var, _, iter, body, _ = val
1475
+ result = new_for iter, var, body
1476
+ }
1477
+ | k_class
1478
+ {
1479
+ result = self.lexer.lineno
1480
+ }
1481
+ cpath superclass
1482
+ {
1483
+ if (self.in_def || self.in_single > 0) then
1484
+ yyerror "class definition in method body"
1485
+ end
1486
+ self.env.extend
1487
+ }
1488
+ bodystmt k_end
1489
+ {
1490
+ result = new_class val
1491
+ self.env.unextend
1492
+ self.lexer.ignore_body_comments
1493
+ }
1494
+ | k_class tLSHFT
1495
+ {
1496
+ result = self.lexer.lineno
1497
+ }
1498
+ expr
1499
+ {
1500
+ result = self.in_def
1501
+ self.in_def = false
1502
+ }
1503
+ term
1504
+ {
1505
+ result = self.in_single
1506
+ self.in_single = 0
1507
+ self.env.extend
1508
+ }
1509
+ bodystmt k_end
1510
+ {
1511
+ result = new_sclass val
1512
+ self.env.unextend
1513
+ self.lexer.ignore_body_comments
1514
+ }
1515
+ | k_module
1516
+ {
1517
+ result = self.lexer.lineno
1518
+ }
1519
+ cpath
1520
+ {
1521
+ yyerror "module definition in method body" if
1522
+ self.in_def or self.in_single > 0
1523
+
1524
+ self.env.extend
1525
+ }
1526
+ bodystmt k_end
1527
+ {
1528
+ result = new_module val
1529
+ self.env.unextend
1530
+ self.lexer.ignore_body_comments
1531
+ }
1532
+ | defn_head f_arglist bodystmt k_end
1533
+ {
1534
+ # [ [:f, 1, false], s(:args)...]
1535
+ # =>
1536
+ # [[:k_def, 666], [:f, 1], false, s(:args)...]
1537
+ val.insert 1, val.first.pop
1538
+ val.insert 0, [:k_def, 666]
1539
+
1540
+ result, in_def = new_defn val
1541
+
1542
+ lexer.cond.pop # group = local_pop
1543
+ lexer.cmdarg.pop
1544
+ self.env.unextend
1545
+ self.in_def = in_def
1546
+
1547
+ self.lexer.ignore_body_comments
1548
+ }
1549
+ | defs_head f_arglist bodystmt k_end
1550
+ {
1551
+ # [ [recv, [:name, 1, false]], s(:args...]
1552
+ # =>
1553
+ # [ recv, [:name, 1, false], s(:args...]
1554
+ # =>
1555
+ # [ recv, [:name, 1], false, s(:args...]
1556
+ # =>
1557
+ # [ :k_def, recv, [:name, 1], false, s(:args...]
1558
+
1559
+ val.prepend(*val.shift)
1560
+ val.insert 2, val[1].pop
1561
+ val.insert 0, [:k_def, 666]
1562
+
1563
+ result, in_def = new_defs val
1564
+
1565
+ lexer.cond.pop # group = local_pop
1566
+ lexer.cmdarg.pop
1567
+ self.env.unextend
1568
+ self.in_def = in_def
1569
+
1570
+ self.in_single -= 1
1571
+
1572
+ # TODO: restore cur_arg ? what's cur_arg?
1573
+
1574
+ self.lexer.ignore_body_comments
1575
+ }
1576
+ | kBREAK
1577
+ {
1578
+ (_, line), = val
1579
+ result = s(:break).line line
1580
+ }
1581
+ | kNEXT
1582
+ {
1583
+ (_, line), = val
1584
+ result = s(:next).line line
1585
+ }
1586
+ | kREDO
1587
+ {
1588
+ (_, line), = val
1589
+ result = s(:redo).line line
1590
+ }
1591
+ | kRETRY
1592
+ {
1593
+ (_, line), = val
1594
+ result = s(:retry).line line
1595
+ }
1596
+
1597
+ primary_value: primary
1598
+ {
1599
+ result = value_expr(val[0])
1600
+ }
1601
+
1602
+ # These are really stupid
1603
+ k_begin: kBEGIN
1604
+ k_if: kIF
1605
+ k_unless: kUNLESS
1606
+ k_while: kWHILE
1607
+ k_until: kUNTIL
1608
+ k_case: kCASE
1609
+ k_for: kFOR
1610
+ k_class: kCLASS
1611
+ {
1612
+ self.comments.push self.lexer.comments
1613
+ }
1614
+ k_module: kMODULE
1615
+ {
1616
+ self.comments.push self.lexer.comments
1617
+ }
1618
+ k_def: kDEF
1619
+ {
1620
+ self.comments.push self.lexer.comments
1621
+ }
1622
+ k_do: kDO
1623
+ k_do_block: kDO_BLOCK
1624
+ k_rescue: kRESCUE
1625
+ k_ensure: kENSURE
1626
+ k_when: kWHEN
1627
+ k_else: kELSE
1628
+ k_elsif: kELSIF
1629
+ k_end: kEND
1630
+ k_return: kRETURN
1631
+
1632
+ then: term
1633
+ | kTHEN
1634
+ | term kTHEN
1635
+
1636
+ do: term
1637
+ | kDO_COND
1638
+
1639
+ if_tail: opt_else
1640
+ | k_elsif expr_value then compstmt if_tail
1641
+ {
1642
+ (_, line), c, _, t, rest = val
1643
+
1644
+ result = s(:if, c, t, rest).line line
1645
+ }
1646
+
1647
+ opt_else: none
1648
+ | kELSE compstmt
1649
+ {
1650
+ result = val[1]
1651
+ }
1652
+
1653
+ for_var: lhs
1654
+ | mlhs
1655
+ {
1656
+ val[0].delete_at 1 if val[0][1].nil? # HACK
1657
+ }
1658
+
1659
+ f_marg: f_norm_arg
1660
+ | tLPAREN f_margs rparen
1661
+ {
1662
+ result = val[1]
1663
+ }
1664
+
1665
+ f_marg_list: f_marg
1666
+ {
1667
+ sym, = val
1668
+
1669
+ result = s(:array, sym).line lexer.lineno
1670
+ }
1671
+ | f_marg_list tCOMMA f_marg
1672
+ {
1673
+ result = list_append val[0], val[2]
1674
+ }
1675
+
1676
+ f_margs: f_marg_list
1677
+ {
1678
+ args, = val
1679
+
1680
+ result = block_var args
1681
+ }
1682
+ | f_marg_list tCOMMA f_rest_marg
1683
+ {
1684
+ args, _, rest = val
1685
+
1686
+ result = block_var args, rest
1687
+ }
1688
+ | f_marg_list tCOMMA f_rest_marg tCOMMA f_marg_list
1689
+ {
1690
+ lhs, _, splat, _, rhs = val
1691
+
1692
+ result = block_var lhs, splat, rhs
1693
+ }
1694
+ | f_rest_marg
1695
+ {
1696
+ rest, = val
1697
+
1698
+ result = block_var rest
1699
+ }
1700
+ | f_rest_marg tCOMMA f_marg_list
1701
+ {
1702
+ splat, _, rest = val
1703
+
1704
+ result = block_var splat, rest
1705
+ }
1706
+
1707
+ f_rest_marg: tSTAR f_norm_arg
1708
+ {
1709
+ _, (id, line) = val
1710
+
1711
+ result = args ["*#{id}".to_sym]
1712
+ result.line line
1713
+ }
1714
+ | tSTAR
1715
+ {
1716
+ result = args [:*]
1717
+ result.line lexer.lineno # FIX: tSTAR -> line
1718
+ }
1719
+
1720
+ f_any_kwrest: f_kwrest
1721
+ | f_no_kwarg
1722
+
1723
+ f_eq: tEQL # TODO: self.in_argdef = false
1724
+
1725
+ block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
1726
+ {
1727
+ result = call_args val
1728
+ }
1729
+ | f_block_kwarg opt_f_block_arg
1730
+ {
1731
+ result = call_args val
1732
+ }
1733
+ | f_any_kwrest opt_f_block_arg
1734
+ {
1735
+ result = call_args val
1736
+ }
1737
+ | f_block_arg
1738
+ {
1739
+ (id, line), = val
1740
+ result = call_args [id]
1741
+ result.line line
1742
+ }
1743
+
1744
+ opt_block_args_tail: tCOMMA block_args_tail
1745
+ {
1746
+ result = args val
1747
+ }
1748
+ | none
1749
+
1750
+ excessed_comma: tCOMMA
1751
+ {
1752
+ result = s(:WTF_COMMA!)
1753
+ }
1754
+
1755
+ block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1756
+ {
1757
+ result = args val
1758
+ }
1759
+ | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1760
+ {
1761
+ result = args val
1762
+ }
1763
+ | f_arg tCOMMA f_block_optarg opt_block_args_tail
1764
+ {
1765
+ result = args val
1766
+ }
1767
+ | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_block_args_tail
1768
+ {
1769
+ result = args val
1770
+ }
1771
+ | f_arg tCOMMA f_rest_arg opt_block_args_tail
1772
+ {
1773
+ result = args val
1774
+ }
1775
+ | f_arg excessed_comma
1776
+ {
1777
+ arg, _ = val
1778
+ result = arg << nil
1779
+ }
1780
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1781
+ {
1782
+ result = args val
1783
+ }
1784
+ | f_arg opt_block_args_tail
1785
+ {
1786
+ result = args val
1787
+ }
1788
+ | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1789
+ {
1790
+ result = args val
1791
+ }
1792
+ | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1793
+ {
1794
+ result = args val
1795
+ }
1796
+ | f_block_optarg opt_block_args_tail
1797
+ {
1798
+ result = args val
1799
+ }
1800
+ | f_block_optarg tCOMMA f_arg opt_block_args_tail
1801
+ {
1802
+ result = args val
1803
+ }
1804
+ | f_rest_arg opt_block_args_tail
1805
+ {
1806
+ result = args val
1807
+ }
1808
+ | f_rest_arg tCOMMA f_arg opt_block_args_tail
1809
+ {
1810
+ result = args val
1811
+ }
1812
+ | block_args_tail
1813
+ {
1814
+ result = args val
1815
+ }
1816
+
1817
+ opt_block_param: none { result = 0 }
1818
+ | block_param_def
1819
+ {
1820
+ self.lexer.command_start = true
1821
+ }
1822
+
1823
+ block_param_def: tPIPE opt_bv_decl tPIPE
1824
+ {
1825
+ # TODO: current_arg = 0
1826
+ result = args val
1827
+ }
1828
+ | tOROP
1829
+ {
1830
+ result = s(:args).line lexer.lineno
1831
+ }
1832
+ | tPIPE block_param opt_bv_decl tPIPE
1833
+ {
1834
+ # TODO: current_arg = 0
1835
+ result = args val
1836
+ }
1837
+
1838
+ opt_bv_decl: opt_nl
1839
+ | opt_nl tSEMI bv_decls opt_nl
1840
+ {
1841
+ result = args val
1842
+ }
1843
+
1844
+ bv_decls: bvar
1845
+ {
1846
+ result = args val
1847
+ }
1848
+ | bv_decls tCOMMA bvar
1849
+ {
1850
+ result = args val
1851
+ }
1852
+
1853
+ bvar: tIDENTIFIER
1854
+ {
1855
+ result = wrap :shadow, val[0]
1856
+ }
1857
+ | f_bad_arg
1858
+
1859
+ lambda: tLAMBDA
1860
+ {
1861
+ self.env.extend :dynamic
1862
+ result = [lexer.lineno, lexer.lpar_beg]
1863
+ lexer.paren_nest += 1
1864
+ lexer.lpar_beg = lexer.paren_nest
1865
+ }
1866
+ f_larglist
1867
+ {
1868
+ lexer.cmdarg.push false
1869
+ }
1870
+ lambda_body
1871
+ {
1872
+ _, (line, lpar), args, _cmdarg, body = val
1873
+ lexer.lpar_beg = lpar
1874
+
1875
+ lexer.cmdarg.pop
1876
+
1877
+ call = s(:lambda).line line
1878
+ result = new_iter call, args, body
1879
+ result.line line
1880
+ self.env.unextend # TODO: dynapush & dynapop
1881
+ }
1882
+
1883
+ f_larglist: tLPAREN2 f_args opt_bv_decl rparen
1884
+ {
1885
+ result = args val
1886
+ }
1887
+ | f_args
1888
+ {
1889
+ result = val[0]
1890
+ result = 0 if result == s(:args)
1891
+ }
1892
+
1893
+ lambda_body: tLAMBEG compstmt tRCURLY
1894
+ {
1895
+ result = val[1]
1896
+ }
1897
+ | kDO_LAMBDA bodystmt kEND
1898
+ {
1899
+ result = val[1]
1900
+ }
1901
+
1902
+ do_block: k_do_block do_body kEND
1903
+ {
1904
+ (_, line), iter, _ = val
1905
+ result = iter.line line
1906
+ }
1907
+
1908
+ block_call: command do_block
1909
+ {
1910
+ # TODO:
1911
+ ## if (nd_type($1) == NODE_YIELD) {
1912
+ ## compile_error(PARSER_ARG "block given to yield");
1913
+
1914
+ cmd, blk = val
1915
+
1916
+ syntax_error "Both block arg and actual block given." if
1917
+ cmd.block_pass?
1918
+
1919
+ if inverted? val then
1920
+ val = invert_block_call val
1921
+ cmd, blk = val
1922
+ end
1923
+
1924
+ result = blk
1925
+ result.insert 1, cmd
1926
+ }
1927
+ | block_call call_op2 operation2 opt_paren_args
1928
+ {
1929
+ lhs, _, (id, _line), args = val
1930
+
1931
+ result = new_call lhs, id.to_sym, args
1932
+ }
1933
+ | block_call call_op2 operation2 opt_paren_args brace_block
1934
+ {
1935
+ iter1, _, (name, _line), args, iter2 = val
1936
+
1937
+ call = new_call iter1, name.to_sym, args
1938
+ iter2.insert 1, call
1939
+
1940
+ result = iter2
1941
+ }
1942
+ | block_call call_op2 operation2 command_args do_block
1943
+ {
1944
+ iter1, _, (name, _line), args, iter2 = val
1945
+
1946
+ call = new_call iter1, name.to_sym, args
1947
+ iter2.insert 1, call
1948
+
1949
+ result = iter2
1950
+ }
1951
+
1952
+ method_call: fcall paren_args
1953
+ {
1954
+ call, args = val
1955
+
1956
+ result = call.concat args.sexp_body if args
1957
+ }
1958
+ | primary_value call_op operation2 opt_paren_args
1959
+ {
1960
+ recv, call_op, (op, _line), args = val
1961
+
1962
+ result = new_call recv, op.to_sym, args, call_op
1963
+ }
1964
+ | primary_value tCOLON2 operation2 paren_args
1965
+ {
1966
+ recv, _, (op, _line), args = val
1967
+
1968
+ result = new_call recv, op.to_sym, args
1969
+ }
1970
+ | primary_value tCOLON2 operation3
1971
+ {
1972
+ lhs, _, (id, _line) = val
1973
+
1974
+ result = new_call lhs, id.to_sym
1975
+ }
1976
+ | primary_value call_op paren_args
1977
+ {
1978
+ result = new_call val[0], :call, val[2], val[1]
1979
+ }
1980
+ | primary_value tCOLON2 paren_args
1981
+ {
1982
+ result = new_call val[0], :call, val[2]
1983
+ }
1984
+ | kSUPER paren_args
1985
+ {
1986
+ result = new_super val[1]
1987
+ }
1988
+ | kSUPER
1989
+ {
1990
+ result = s(:zsuper).line lexer.lineno
1991
+ }
1992
+ | primary_value tLBRACK2 opt_call_args rbracket
1993
+ {
1994
+ result = new_aref val
1995
+ }
1996
+
1997
+ brace_block: tLCURLY
1998
+ {
1999
+ self.env.extend :dynamic
2000
+ result = self.lexer.lineno
2001
+ }
2002
+ brace_body tRCURLY
2003
+ {
2004
+ _, line, body, _ = val
2005
+
2006
+ result = body
2007
+ result.line line
2008
+
2009
+ self.env.unextend
2010
+ }
2011
+ | k_do
2012
+ {
2013
+ self.env.extend :dynamic
2014
+ result = self.lexer.lineno
2015
+ }
2016
+ do_body kEND
2017
+ {
2018
+ _, line, body, _ = val
2019
+
2020
+ result = body
2021
+ result.line line
2022
+
2023
+ self.env.unextend
2024
+ }
2025
+
2026
+ brace_body: { self.env.extend :dynamic; result = self.lexer.lineno }
2027
+ { result = lexer.cmdarg.store(false) }
2028
+ opt_block_param compstmt
2029
+ {
2030
+ line, cmdarg, param, cmpstmt = val
2031
+
2032
+ result = new_brace_body param, cmpstmt, line
2033
+ self.env.unextend
2034
+ lexer.cmdarg.restore cmdarg
2035
+ lexer.cmdarg.pop # because of: cmdarg_stack >> 1 ?
2036
+ }
2037
+
2038
+ do_body: { self.env.extend :dynamic; result = self.lexer.lineno }
2039
+ { lexer.cmdarg.push false }
2040
+ opt_block_param
2041
+ bodystmt
2042
+ {
2043
+ line, _cmdarg, param, cmpstmt = val
2044
+
2045
+ result = new_do_body param, cmpstmt, line
2046
+ lexer.cmdarg.pop
2047
+ self.env.unextend
2048
+ }
2049
+
2050
+ case_args: arg_value
2051
+ {
2052
+ arg, = val
2053
+
2054
+ result = s(:array, arg).line arg.line
2055
+ }
2056
+ | tSTAR arg_value
2057
+ {
2058
+ _, arg = val
2059
+
2060
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
2061
+ }
2062
+ | case_args tCOMMA arg_value
2063
+ {
2064
+ args, _, id = val
2065
+
2066
+ result = self.list_append args, id
2067
+ }
2068
+ | case_args tCOMMA tSTAR arg_value
2069
+ {
2070
+ args, _, _, id = val
2071
+
2072
+ result = self.list_append args, s(:splat, id).line(id.line)
2073
+ }
2074
+
2075
+ case_body: k_when
2076
+ {
2077
+ result = self.lexer.lineno
2078
+ }
2079
+ case_args then compstmt cases
2080
+ {
2081
+ result = new_when(val[2], val[4])
2082
+ result.line val[1]
2083
+ result << val[5] if val[5]
2084
+ }
2085
+
2086
+ cases: opt_else | case_body
2087
+ ######################################################################
2088
+
2089
+ p_case_body: kIN
2090
+ {
2091
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
2092
+ self.lexer.command_start = false
2093
+ result = self.in_kwarg
2094
+ self.in_kwarg = true
2095
+ push_pvtbl
2096
+ push_pktbl
2097
+ }
2098
+ p_top_expr then
2099
+ {
2100
+ pop_pktbl
2101
+ pop_pvtbl
2102
+ old_kwargs = _values[-3]
2103
+ self.in_kwarg = old_kwargs
2104
+ }
2105
+ compstmt
2106
+ p_cases
2107
+ {
2108
+ (_, line), _, pat, _, _, body, cases = val
2109
+
2110
+ result = new_in pat, body, cases, line
2111
+ }
2112
+
2113
+ p_cases: opt_else
2114
+ | p_case_body
2115
+
2116
+ p_top_expr: p_top_expr_body
2117
+ | p_top_expr_body kIF_MOD expr_value
2118
+ {
2119
+ body, _, cond = val
2120
+ body = remove_begin body
2121
+
2122
+ result = s(:if, cond, body, nil).line body.line
2123
+ }
2124
+ | p_top_expr_body kUNLESS_MOD expr_value
2125
+ {
2126
+ body, _, cond = val
2127
+ body = remove_begin body
2128
+
2129
+ result = s(:if, cond, nil, body).line body.line
2130
+ }
2131
+
2132
+ p_top_expr_body: p_expr
2133
+ | p_expr tCOMMA
2134
+ {
2135
+ expr, _ = val
2136
+
2137
+ tail = new_array_pattern_tail nil, true, nil, nil
2138
+ result = new_array_pattern nil, expr, tail, expr.line
2139
+ }
2140
+ | p_expr tCOMMA p_args
2141
+ {
2142
+ expr, _, args = val
2143
+
2144
+ result = new_array_pattern nil, expr, args, expr.line
2145
+ }
2146
+ | p_find
2147
+ {
2148
+ find, = val
2149
+
2150
+ result = new_find_pattern nil, find
2151
+ }
2152
+ | p_args_tail
2153
+ {
2154
+ args, = val
2155
+ result = new_array_pattern nil, nil, args, args.line
2156
+ }
2157
+ | p_kwargs
2158
+ {
2159
+ kwargs, = val
2160
+ result = new_hash_pattern nil, kwargs, kwargs.line
2161
+ }
2162
+
2163
+ p_expr: p_as
2164
+
2165
+ p_as: p_expr tASSOC p_variable
2166
+ {
2167
+ # NODE *n = NEW_LIST($1, &@$);
2168
+ # n = list_append(p, n, $3);
2169
+ # $$ = new_hash(p, n, &@$);
2170
+
2171
+ expr, _, var = val
2172
+
2173
+ id = var.last
2174
+
2175
+ self.env[id] = :lvar # HACK: need to extend env
2176
+ lhs = s(:lasgn, id).line var.line
2177
+
2178
+ result = new_assign lhs, expr
2179
+ }
2180
+ | p_alt
2181
+
2182
+ p_alt: p_alt tPIPE p_expr_basic
2183
+ {
2184
+ lhs, _, rhs = val
2185
+
2186
+ result = s(:or, lhs, rhs).line lhs.line
2187
+ }
2188
+ | p_expr_basic
2189
+
2190
+ p_lparen: tLPAREN2 { push_pktbl }
2191
+ p_lbracket: tLBRACK2 { push_pktbl }
2192
+
2193
+ p_expr_basic: p_value
2194
+ | p_variable
2195
+ | p_const p_lparen p_args tRPAREN
2196
+ {
2197
+ lhs, _, args, _ = val
2198
+
2199
+ pop_pktbl
2200
+ result = new_array_pattern(lhs, nil, args, lhs.line)
2201
+ }
2202
+ | p_const p_lparen p_find tRPAREN
2203
+ {
2204
+ const, _, find, _ = val
2205
+
2206
+ pop_pktbl
2207
+ result = new_find_pattern(const, find).line const.line
2208
+ }
2209
+ | p_const p_lparen p_kwargs tRPAREN
2210
+ {
2211
+ lhs, _, kwargs, _ = val
2212
+
2213
+ pop_pktbl
2214
+ result = new_hash_pattern(lhs, kwargs, lhs.line)
2215
+ }
2216
+ | p_const tLPAREN2 tRPAREN
2217
+ {
2218
+ const, _, _ = val
2219
+
2220
+ tail = new_array_pattern_tail nil, nil, nil, nil
2221
+ result = new_array_pattern const, nil, tail, const.line
2222
+ }
2223
+ | p_const p_lbracket p_args rbracket
2224
+ {
2225
+ const, _, pre_arg, _ = val
2226
+
2227
+ pop_pktbl
2228
+ result = new_array_pattern const, nil, pre_arg, const.line
2229
+ }
2230
+ | p_const p_lbracket p_find rbracket
2231
+ {
2232
+ const, _, find, _ = val
2233
+
2234
+ pop_pktbl
2235
+ result = new_find_pattern(const, find).line const.line
2236
+ }
2237
+ | p_const p_lbracket p_kwargs rbracket
2238
+ {
2239
+ const, _, kwargs, _ = val
2240
+
2241
+ result = new_hash_pattern const, kwargs, const.line
2242
+ }
2243
+ | p_const tLBRACK2 rbracket
2244
+ {
2245
+ const, _, _ = val
2246
+
2247
+ tail = new_array_pattern_tail nil, nil, nil, nil
2248
+ result = new_array_pattern const, nil, tail, const.line
2249
+ }
2250
+ | tLBRACK p_args rbracket
2251
+ {
2252
+ _, pat, _ = val
2253
+
2254
+ result = new_array_pattern nil, nil, pat, pat.line
2255
+ }
2256
+ | tLBRACK p_find rbracket
2257
+ {
2258
+ _, find, _ = val
2259
+
2260
+ result = new_find_pattern nil, find
2261
+ }
2262
+ | tLBRACK rbracket
2263
+ {
2264
+ (_, line), _ = val
2265
+
2266
+ result = s(:array_pat).line line
2267
+ }
2268
+ | tLBRACE
2269
+ {
2270
+ push_pktbl
2271
+ result = self.in_kwarg
2272
+ self.in_kwarg = false
2273
+ }
2274
+ p_kwargs rbrace
2275
+ {
2276
+ _, in_kwarg, kwargs, _ = val
2277
+
2278
+ pop_pktbl
2279
+ self.in_kwarg = in_kwarg
2280
+
2281
+ result = new_hash_pattern(nil, kwargs, kwargs.line)
2282
+ }
2283
+ | tLBRACE rbrace
2284
+ {
2285
+ (_, line), _ = val
2286
+
2287
+ tail = new_hash_pattern_tail nil, nil, line
2288
+ result = new_hash_pattern nil, tail, line
2289
+ }
2290
+ | tLPAREN { push_pktbl } p_expr tRPAREN
2291
+ {
2292
+ _, _, expr, _ = val
2293
+
2294
+ pop_pktbl
2295
+ result = expr
2296
+ }
2297
+
2298
+ p_args: p_expr
2299
+ {
2300
+ expr, = val
2301
+
2302
+ ary = s(:array_TAIL, expr).line expr.line
2303
+ result = new_array_pattern_tail(ary, nil, nil, nil).line expr.line
2304
+ }
2305
+ | p_args_head
2306
+ {
2307
+ head, = val
2308
+
2309
+ result = new_array_pattern_tail head, true, nil, nil
2310
+ }
2311
+ | p_args_head p_arg
2312
+ {
2313
+ head, tail = val
2314
+
2315
+ both = array_pat_concat head, tail
2316
+
2317
+ result = new_array_pattern_tail both, nil, nil, nil
2318
+ result.line head.line
2319
+ }
2320
+ | p_args_head tSTAR tIDENTIFIER
2321
+ {
2322
+ head, _, (id, _line) = val
2323
+
2324
+ result = new_array_pattern_tail head, true, id.to_sym, nil
2325
+ result.line head.line
2326
+ }
2327
+ | p_args_head tSTAR tIDENTIFIER tCOMMA p_args_post
2328
+ {
2329
+ head, _, (id, _line), _, post = val
2330
+
2331
+ result = new_array_pattern_tail head, true, id.to_sym, post
2332
+ result.line head.line
2333
+ }
2334
+ | p_args_head tSTAR
2335
+ {
2336
+ expr, _ = val
2337
+
2338
+ result = new_array_pattern_tail(expr, true, nil, nil).line expr.line
2339
+ }
2340
+ | p_args_head tSTAR tCOMMA p_args_post
2341
+ {
2342
+ head, _, _, post = val
2343
+
2344
+ result = new_array_pattern_tail(head, true, nil, post).line head.line
2345
+ }
2346
+ | p_args_tail
2347
+
2348
+ p_args_head: p_arg tCOMMA
2349
+ {
2350
+ arg, _ = val
2351
+ result = arg
2352
+ }
2353
+ | p_args_head p_arg tCOMMA
2354
+ {
2355
+ head, tail, _ = val
2356
+
2357
+ result = s(:PATTERN, *head.sexp_body, *tail.sexp_body)
2358
+ result.line head.line
2359
+ }
2360
+
2361
+ p_args_tail: p_rest
2362
+ {
2363
+ (id, line), = val
2364
+
2365
+ result = new_array_pattern_tail nil, true, id, nil
2366
+ result.line line
2367
+ }
2368
+ | p_rest tCOMMA p_args_post
2369
+ {
2370
+ (id, line), _, rhs = val
2371
+
2372
+ result = new_array_pattern_tail nil, true, id, rhs
2373
+ result.line line
2374
+ }
2375
+
2376
+ p_find: p_rest tCOMMA p_args_post tCOMMA p_rest
2377
+ {
2378
+ lhs, _, mid, _, rhs = val
2379
+
2380
+ result = new_find_pattern_tail lhs, mid, rhs
2381
+ }
2382
+
2383
+ p_rest: tSTAR tIDENTIFIER
2384
+ {
2385
+ _, (id, line) = val
2386
+
2387
+ result = [id.to_sym, line]
2388
+ }
2389
+ | tSTAR
2390
+ {
2391
+ (_id, line), = val
2392
+
2393
+ result = [nil, line]
2394
+ }
2395
+
2396
+ p_args_post: p_arg
2397
+ | p_args_post tCOMMA p_arg
2398
+ {
2399
+ lhs, _, rhs = val
2400
+
2401
+ result = array_pat_concat lhs, rhs
2402
+ }
2403
+
2404
+ p_arg: p_expr
2405
+ {
2406
+ expr, = val
2407
+ expr = s(:array_TAIL, expr).line expr.line unless
2408
+ expr.sexp_type == :array_TAIL
2409
+ result = expr
2410
+ }
2411
+
2412
+ p_kwargs: p_kwarg tCOMMA p_any_kwrest
2413
+ {
2414
+ kw_arg, _, rest = val
2415
+ # TODO? new_unique_key_hash(p, $1, &@$)
2416
+ result = new_hash_pattern_tail kw_arg, rest, kw_arg.line
2417
+ }
2418
+ | p_kwarg
2419
+ {
2420
+ kwarg, = val
2421
+ # TODO? new_unique_key_hash(p, $1, &@$)
2422
+ result = new_hash_pattern_tail kwarg, nil, kwarg.line
2423
+ }
2424
+ | p_kwarg tCOMMA
2425
+ {
2426
+ kwarg, _ = val
2427
+ # TODO? new_unique_key_hash(p, $1, &@$)
2428
+ result = new_hash_pattern_tail kwarg, nil, kwarg.line
2429
+ }
2430
+ | p_any_kwrest
2431
+ {
2432
+ rest, = val
2433
+
2434
+ result = new_hash_pattern_tail nil, rest, rest.line
2435
+ }
2436
+
2437
+ p_kwarg: p_kw # TODO? rb_ary_new_from_args(1, $1)
2438
+ | p_kwarg tCOMMA p_kw
2439
+ {
2440
+ kwarg, _, kw = val
2441
+ kwarg.concat kw.sexp_body
2442
+ result = kwarg
2443
+ }
2444
+
2445
+ p_kw: p_kw_label p_expr
2446
+ {
2447
+ # TODO: error_duplicate_pattern_key(p, get_id($1), &@1);
2448
+ lhs, rhs = val
2449
+
2450
+ result = s(:PAIR, lhs, rhs).line lhs.line
2451
+ }
2452
+ | p_kw_label
2453
+ {
2454
+ lhs, = val
2455
+
2456
+ # TODO: error_duplicate_pattern_variable(p, get_id($1), &@1);
2457
+
2458
+ # TODO: if ($1 && !is_local_id(get_id($1))) {
2459
+ # yyerror1(&@1, "key must be valid as local variables");
2460
+ # }
2461
+
2462
+ # $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@$), &@$),
2463
+ # assignable(p, $1, 0, &@$));
2464
+
2465
+ case lhs.sexp_type
2466
+ when :lit then
2467
+ assignable [lhs.value, lhs.line]
2468
+ else
2469
+ # TODO or done?
2470
+ debug 10
2471
+ end
2472
+
2473
+ # TODO PAIR -> LIST ?
2474
+ result = s(:PAIR, lhs, nil).line lhs.line
2475
+ }
2476
+
2477
+ p_kw_label: tLABEL
2478
+ {
2479
+ result = wrap :lit, val[0]
2480
+ }
2481
+ | tSTRING_BEG string_contents tLABEL_END
2482
+ {
2483
+ # you can't actually get here the way I lex labels
2484
+ debug 11
2485
+ }
2486
+
2487
+ p_kwrest: kwrest_mark tIDENTIFIER
2488
+ {
2489
+ _, (id, line) = val
2490
+
2491
+ name = id.to_sym
2492
+ self.assignable [name, line]
2493
+ result = s(:kwrest, :"**#{name}").line line
2494
+ }
2495
+ | kwrest_mark
2496
+ {
2497
+ (_, line), = val
2498
+
2499
+ result = s(:kwrest, :"**").line line
2500
+ }
2501
+
2502
+ p_kwnorest: kwrest_mark kNIL
2503
+ {
2504
+ (_, line), _ = val
2505
+
2506
+ # TODO: or s(:norest)? s(:**nil)?
2507
+ result = s(:kwrest, :"**nil").line line
2508
+ }
2509
+
2510
+ p_any_kwrest: p_kwrest
2511
+ | p_kwnorest
2512
+
2513
+ p_value: p_primitive
2514
+ | p_primitive tDOT2 p_primitive
2515
+ {
2516
+ lhs, _, rhs = val
2517
+
2518
+ lhs = value_expr lhs
2519
+ rhs = value_expr rhs
2520
+
2521
+ result = s(:dot2, lhs, rhs).line lhs.line
2522
+ }
2523
+ | p_primitive tDOT3 p_primitive
2524
+ {
2525
+ lhs, _, rhs = val
2526
+
2527
+ lhs = value_expr lhs
2528
+ rhs = value_expr rhs
2529
+
2530
+ result = s(:dot3, lhs, rhs).line lhs.line
2531
+ }
2532
+ | p_primitive tDOT2
2533
+ {
2534
+ v1, _ = val
2535
+
2536
+ result = s(:dot2, v1, nil).line v1.line
2537
+ }
2538
+ | p_primitive tDOT3
2539
+ {
2540
+ v1, _ = val
2541
+
2542
+ result = s(:dot3, v1, nil).line v1.line
2543
+ }
2544
+ | p_var_ref
2545
+ | p_expr_ref
2546
+ | p_const
2547
+ | tBDOT2 p_primitive
2548
+ {
2549
+ _, v1 = val
2550
+
2551
+ result = s(:dot2, nil, v1).line v1.line
2552
+ }
2553
+ | tBDOT3 p_primitive
2554
+ {
2555
+ _, v1 = val
2556
+
2557
+ result = s(:dot3, nil, v1).line v1.line
2558
+ }
2559
+
2560
+ p_primitive: literal
2561
+ | strings
2562
+ | xstring
2563
+ | regexp
2564
+ | words
2565
+ | qwords
2566
+ | symbols
2567
+ | qsymbols
2568
+ | keyword_variable
2569
+ {
2570
+ # TODO? if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$);
2571
+ var, = val
2572
+
2573
+ result = var
2574
+ }
2575
+ | lambda
2576
+
2577
+ p_variable: tIDENTIFIER
2578
+ {
2579
+ # TODO: error_duplicate_pattern_variable(p, $1, &@1);
2580
+ # TODO: assignable(p, $1, 0, &@$);
2581
+ result = wrap :lvar, val[0]
2582
+ }
2583
+
2584
+ p_var_ref: tCARET tIDENTIFIER
2585
+ {
2586
+ # TODO: check id against env for lvar or dvar
2587
+ result = wrap :lvar, val[1]
2588
+ }
2589
+ | tCARET nonlocal_var
2590
+ {
2591
+ _, var = val
2592
+ result = var
2593
+ }
2594
+
2595
+ p_expr_ref: tCARET tLPAREN expr_value rparen
2596
+ {
2597
+ _, _, expr, _ = val
2598
+ result = expr # TODO? s(:begin, expr).line expr.line
2599
+ }
2600
+
2601
+ p_const: tCOLON3 cname
2602
+ {
2603
+ result = wrap :colon3, val[1]
2604
+ }
2605
+ | p_const tCOLON2 cname
2606
+ {
2607
+ lhs, _, (id, _line) = val
2608
+
2609
+ l = lhs.line
2610
+ result = s(:const, s(:colon2, lhs, id.to_sym).line(l)).line l
2611
+ }
2612
+ | tCONSTANT
2613
+ {
2614
+ # TODO $$ = gettable(p, $1, &@$);
2615
+ result = wrap :const, val[0]
2616
+ }
2617
+ ######################################################################
2618
+
2619
+ opt_rescue: k_rescue exc_list exc_var then compstmt opt_rescue
2620
+ {
2621
+ (_, line), klasses, var, _, body, rest = val
2622
+
2623
+ klasses ||= s(:array)
2624
+ klasses << new_assign(var, s(:gvar, :"$!").line(var.line)) if var
2625
+ klasses.line line
2626
+
2627
+ result = new_resbody(klasses, body)
2628
+ result << rest if rest # UGH, rewritten above
2629
+ }
2630
+ |
2631
+ {
2632
+ result = nil
2633
+ }
2634
+
2635
+ exc_list: arg_value
2636
+ {
2637
+ arg, = val
2638
+ result = s(:array, arg).line arg.line
2639
+ }
2640
+ | mrhs
2641
+ | none
2642
+
2643
+ exc_var: tASSOC lhs
2644
+ {
2645
+ result = val[1]
2646
+ }
2647
+ | none
2648
+
2649
+ opt_ensure: k_ensure compstmt
2650
+ {
2651
+ (_, line), body = val
2652
+
2653
+ result = body || s(:nil).line(line)
2654
+ }
2655
+ | none
2656
+
2657
+ literal: numeric
2658
+ {
2659
+ (lit, line), = val
2660
+ result = s(:lit, lit).line line
2661
+ }
2662
+ | symbol
2663
+
2664
+ strings: string
2665
+ {
2666
+ str, = val
2667
+ str = s(:dstr, str.value) if str.sexp_type == :evstr
2668
+ result = str
2669
+ }
2670
+
2671
+ string: tCHAR
2672
+ {
2673
+ debug 12
2674
+ }
2675
+ | string1
2676
+ | string string1
2677
+ {
2678
+ result = self.literal_concat val[0], val[1]
2679
+ }
2680
+
2681
+ string1: tSTRING_BEG string_contents tSTRING_END
2682
+ {
2683
+ (_, line), str, (_, func) = val
2684
+
2685
+ str = dedent str if func =~ RubyLexer::STR_FUNC_DEDENT
2686
+
2687
+ result = str.line line
2688
+ }
2689
+ | tSTRING
2690
+ {
2691
+ result = new_string val
2692
+ }
2693
+
2694
+ xstring: tXSTRING_BEG xstring_contents tSTRING_END
2695
+ {
2696
+ result = new_xstring val
2697
+ # TODO: dedent?!?! SERIOUSLY?!?
2698
+ }
2699
+
2700
+ regexp: tREGEXP_BEG regexp_contents tREGEXP_END
2701
+ {
2702
+ result = new_regexp val
2703
+ }
2704
+
2705
+ words: tWORDS_BEG tSPACE tSTRING_END
2706
+ {
2707
+ (_, line), _, _ = val
2708
+
2709
+ result = s(:array).line line
2710
+ }
2711
+ | tWORDS_BEG word_list tSTRING_END
2712
+ {
2713
+ (_, line), list, _ = val
2714
+
2715
+ result = list.line line
2716
+ }
2717
+
2718
+ word_list: none
2719
+ {
2720
+ result = new_word_list
2721
+ }
2722
+ | word_list word tSPACE
2723
+ {
2724
+ result = val[0].dup << new_word_list_entry(val)
2725
+ }
2726
+
2727
+ word: string_content
2728
+ | word string_content
2729
+ {
2730
+ result = self.literal_concat val[0], val[1]
2731
+ }
2732
+
2733
+ symbols: tSYMBOLS_BEG tSPACE tSTRING_END
2734
+ {
2735
+ (_, line), _, _ = val
2736
+
2737
+ result = s(:array).line line
2738
+ }
2739
+ | tSYMBOLS_BEG symbol_list tSTRING_END
2740
+ {
2741
+ (_, line), list, _, = val
2742
+ list.line line
2743
+ result = list
2744
+ }
2745
+
2746
+ symbol_list: none
2747
+ {
2748
+ result = new_symbol_list
2749
+ }
2750
+ | symbol_list word tSPACE
2751
+ {
2752
+ list, * = val
2753
+ result = list.dup << new_symbol_list_entry(val)
2754
+ }
2755
+
2756
+ qwords: tQWORDS_BEG tSPACE tSTRING_END
2757
+ {
2758
+ (_, line), _, _ = val
2759
+
2760
+ result = s(:array).line line
2761
+ }
2762
+ | tQWORDS_BEG qword_list tSTRING_END
2763
+ {
2764
+ (_, line), list, _ = val
2765
+
2766
+ result = list.line line
2767
+ }
2768
+
2769
+ qsymbols: tQSYMBOLS_BEG tSPACE tSTRING_END
2770
+ {
2771
+ (_, line), _, _ = val
2772
+
2773
+ result = s(:array).line line
2774
+ }
2775
+ | tQSYMBOLS_BEG qsym_list tSTRING_END
2776
+ {
2777
+ (_, line), list, _ = val
2778
+
2779
+ result = list.line line
2780
+ }
2781
+
2782
+ qword_list: none
2783
+ {
2784
+ result = new_qword_list
2785
+ }
2786
+ | qword_list tSTRING_CONTENT tSPACE
2787
+ {
2788
+ result = val[0].dup << new_qword_list_entry(val)
2789
+ }
2790
+
2791
+ qsym_list: none
2792
+ {
2793
+ result = new_qsym_list
2794
+ }
2795
+ | qsym_list tSTRING_CONTENT tSPACE
2796
+ {
2797
+ result = val[0].dup << new_qsym_list_entry(val)
2798
+ }
2799
+
2800
+ string_contents: none
2801
+ {
2802
+ line = prev_value_to_lineno _values.last
2803
+ result = s(:str, +"").line line
2804
+ }
2805
+ | string_contents string_content
2806
+ {
2807
+ v1, v2 = val
2808
+ result = literal_concat v1, v2
2809
+ }
2810
+
2811
+ xstring_contents: none
2812
+ {
2813
+ result = nil
2814
+ }
2815
+ | xstring_contents string_content
2816
+ {
2817
+ v1, v2 = val
2818
+ result = literal_concat v1, v2
2819
+ }
2820
+
2821
+ regexp_contents: none
2822
+ {
2823
+ result = nil
2824
+ }
2825
+ | regexp_contents string_content
2826
+ {
2827
+ v1, v2 = val
2828
+ result = literal_concat v1, v2
2829
+ }
2830
+
2831
+ string_content: tSTRING_CONTENT
2832
+ {
2833
+ result = new_string val
2834
+ }
2835
+ | tSTRING_DVAR
2836
+ {
2837
+ result = lexer.lex_strterm
2838
+
2839
+ lexer.lex_strterm = nil
2840
+ lexer.lex_state = EXPR_BEG
2841
+ }
2842
+ string_dvar
2843
+ {
2844
+ _, strterm, str = val
2845
+ lexer.lex_strterm = strterm
2846
+ result = s(:evstr, str).line str.line
2847
+ }
2848
+ | tSTRING_DBEG
2849
+ {
2850
+ result = [lexer.lex_strterm,
2851
+ lexer.brace_nest,
2852
+ lexer.string_nest, # TODO: remove
2853
+ lexer.lex_state,
2854
+ lexer.lineno,
2855
+ ]
2856
+
2857
+ lexer.cmdarg.push false
2858
+ lexer.cond.push false
2859
+
2860
+ lexer.lex_strterm = nil
2861
+ lexer.brace_nest = 0
2862
+ lexer.string_nest = 0
2863
+
2864
+ lexer.lex_state = EXPR_BEG
2865
+ }
2866
+ compstmt
2867
+ tSTRING_DEND
2868
+ {
2869
+ _, memo, stmt, _ = val
2870
+
2871
+ lex_strterm, brace_nest, string_nest, oldlex_state, line = memo
2872
+ # TODO: heredoc_indent
2873
+
2874
+ lexer.lex_strterm = lex_strterm
2875
+ lexer.brace_nest = brace_nest
2876
+ lexer.string_nest = string_nest
2877
+
2878
+ lexer.cond.pop
2879
+ lexer.cmdarg.pop
2880
+
2881
+ lexer.lex_state = oldlex_state
2882
+
2883
+ case stmt
2884
+ when Sexp then
2885
+ case stmt.sexp_type
2886
+ when :str, :dstr, :evstr then
2887
+ result = stmt
2888
+ else
2889
+ result = s(:evstr, stmt).line line
2890
+ end
2891
+ when nil then
2892
+ result = s(:evstr).line line
2893
+ else
2894
+ debug 13
2895
+ raise "unknown string body: #{stmt.inspect}"
2896
+ end
2897
+ }
2898
+
2899
+ string_dvar: tGVAR
2900
+ {
2901
+ result = wrap :gvar, val[0]
2902
+ }
2903
+ | tIVAR
2904
+ {
2905
+ result = wrap :ivar, val[0]
2906
+ }
2907
+ | tCVAR
2908
+ {
2909
+ result = wrap :cvar, val[0]
2910
+ }
2911
+ | backref
2912
+
2913
+ symbol: ssym
2914
+ | dsym
2915
+
2916
+ ssym: tSYMBEG sym
2917
+ {
2918
+ lexer.lex_state = EXPR_END
2919
+ result = wrap :lit, val[1]
2920
+ }
2921
+ | tSYMBOL
2922
+ {
2923
+ lexer.lex_state = EXPR_END
2924
+ result = wrap :lit, val[0]
2925
+ }
2926
+
2927
+ sym: fname | tIVAR | tGVAR | tCVAR
2928
+
2929
+ dsym: tSYMBEG string_contents tSTRING_END
2930
+ {
2931
+ _, result, _ = val
2932
+
2933
+ lexer.lex_state = EXPR_END
2934
+
2935
+ result ||= s(:str, "").line lexer.lineno
2936
+
2937
+ case result.sexp_type
2938
+ when :dstr then
2939
+ result.sexp_type = :dsym
2940
+ when :str then
2941
+ result = s(:lit, result.last.to_sym).line result.line
2942
+ when :evstr then
2943
+ result = s(:dsym, "", result).line result.line
2944
+ else
2945
+ debug 14
2946
+ end
2947
+ }
2948
+
2949
+ numeric: simple_numeric
2950
+ | tUMINUS_NUM simple_numeric =tLOWEST
2951
+ {
2952
+ _, (num, line) = val
2953
+ result = [-num, line]
2954
+ }
2955
+
2956
+ simple_numeric: tINTEGER
2957
+ | tFLOAT
2958
+ | tRATIONAL
2959
+ | tIMAGINARY
2960
+
2961
+ nonlocal_var: tIVAR { result = wrap :ivar, val[0] }
2962
+ | tGVAR { result = wrap :gvar, val[0] }
2963
+ | tCVAR { result = wrap :cvar, val[0] }
2964
+
2965
+ user_variable: tIDENTIFIER
2966
+ | tIVAR
2967
+ | tGVAR
2968
+ | tCONSTANT
2969
+ | tCVAR
2970
+
2971
+ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2972
+ | kSELF { result = s(:self).line lexer.lineno }
2973
+ | kTRUE { result = s(:true).line lexer.lineno }
2974
+ | kFALSE { result = s(:false).line lexer.lineno }
2975
+ | k__FILE__ { result = s(:str, self.file).line lexer.lineno }
2976
+ | k__LINE__ { result = s(:lit, lexer.lineno).line lexer.lineno }
2977
+ | k__ENCODING__
2978
+ {
2979
+ l = lexer.lineno
2980
+ result =
2981
+ if defined? Encoding then
2982
+ s(:colon2, s(:const, :Encoding).line(l), :UTF_8).line l
2983
+ else
2984
+ s(:str, "Unsupported!").line l
2985
+ end
2986
+ }
2987
+
2988
+ var_ref: user_variable
2989
+ {
2990
+ raise "NO: #{val.inspect}" if Sexp === val.first
2991
+ (var, line), = val
2992
+ result = Sexp === var ? var : self.gettable(var)
2993
+
2994
+ result.line line
2995
+ }
2996
+ | keyword_variable
2997
+ {
2998
+ var = val[0]
2999
+ result = Sexp === var ? var : self.gettable(var)
3000
+ }
3001
+
3002
+ var_lhs: user_variable
3003
+ {
3004
+ result = self.assignable val[0]
3005
+ }
3006
+ | keyword_variable
3007
+ {
3008
+ result = self.assignable val[0]
3009
+ debug 15
3010
+ }
3011
+
3012
+ backref: tNTH_REF
3013
+ {
3014
+ (ref, line), = val
3015
+ result = s(:nth_ref, ref).line line
3016
+ }
3017
+ | tBACK_REF
3018
+ {
3019
+ (ref, line), = val
3020
+ result = s(:back_ref, ref).line line
3021
+ }
3022
+
3023
+ superclass: tLT
3024
+ {
3025
+ lexer.lex_state = EXPR_BEG
3026
+ lexer.command_start = true
3027
+ }
3028
+ expr_value term
3029
+ {
3030
+ result = val[2]
3031
+ }
3032
+ | none
3033
+ {
3034
+ result = nil
3035
+ }
3036
+
3037
+ f_opt_paren_args: f_paren_args
3038
+ | none
3039
+ {
3040
+ result = end_args val
3041
+ }
3042
+
3043
+ f_paren_args: tLPAREN2 f_args rparen
3044
+ {
3045
+ result = end_args val
3046
+ }
3047
+
3048
+ f_arglist: f_paren_args
3049
+ | {
3050
+ result = self.in_kwarg
3051
+ self.in_kwarg = true
3052
+ self.lexer.lex_state |= EXPR_LABEL
3053
+ }
3054
+ f_args term
3055
+ {
3056
+ result = end_args val
3057
+ }
3058
+
3059
+ args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
3060
+ {
3061
+ result = args val
3062
+ }
3063
+ | f_kwarg opt_f_block_arg
3064
+ {
3065
+ result = args val
3066
+ }
3067
+ | f_any_kwrest opt_f_block_arg
3068
+ {
3069
+ result = args val
3070
+ }
3071
+ | f_block_arg
3072
+ | args_forward
3073
+
3074
+ opt_args_tail: tCOMMA args_tail
3075
+ {
3076
+ result = val[1]
3077
+ }
3078
+ |
3079
+ {
3080
+ result = nil
3081
+ }
3082
+
3083
+ f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
3084
+ {
3085
+ result = args val
3086
+ }
3087
+ | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
3088
+ {
3089
+ result = args val
3090
+ }
3091
+ | f_arg tCOMMA f_optarg opt_args_tail
3092
+ {
3093
+ result = args val
3094
+ }
3095
+ | f_arg tCOMMA f_optarg tCOMMA f_arg opt_args_tail
3096
+ {
3097
+ result = args val
3098
+ }
3099
+ | f_arg tCOMMA f_rest_arg opt_args_tail
3100
+ {
3101
+ result = args val
3102
+ }
3103
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
3104
+ {
3105
+ result = args val
3106
+ }
3107
+ | f_arg opt_args_tail
3108
+ {
3109
+ result = args val
3110
+ }
3111
+ | f_optarg tCOMMA f_rest_arg opt_args_tail
3112
+ {
3113
+ result = args val
3114
+ }
3115
+ | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
3116
+ {
3117
+ result = args val
3118
+ }
3119
+ | f_optarg opt_args_tail
3120
+ {
3121
+ result = args val
3122
+ }
3123
+ | f_optarg tCOMMA f_arg opt_args_tail
3124
+ {
3125
+ result = args val
3126
+ }
3127
+ | f_rest_arg opt_args_tail
3128
+ {
3129
+ result = args val
3130
+ }
3131
+ | f_rest_arg tCOMMA f_arg opt_args_tail
3132
+ {
3133
+ result = args val
3134
+ }
3135
+ | args_tail
3136
+ {
3137
+ result = args val
3138
+ }
3139
+ |
3140
+ {
3141
+ result = args val
3142
+ # result.line lexer.lineno
3143
+ }
3144
+
3145
+ args_forward: tBDOT3
3146
+ {
3147
+ result = s(:forward_args).line lexer.lineno
3148
+ }
3149
+
3150
+ f_bad_arg: tCONSTANT
3151
+ {
3152
+ yyerror "formal argument cannot be a constant"
3153
+ }
3154
+ | tIVAR
3155
+ {
3156
+ yyerror "formal argument cannot be an instance variable"
3157
+ }
3158
+ | tGVAR
3159
+ {
3160
+ yyerror "formal argument cannot be a global variable"
3161
+ }
3162
+ | tCVAR
3163
+ {
3164
+ yyerror "formal argument cannot be a class variable"
3165
+ }
3166
+
3167
+ f_norm_arg: f_bad_arg
3168
+ | tIDENTIFIER
3169
+ {
3170
+ (id, line), = val
3171
+ identifier = id.to_sym
3172
+ self.env[identifier] = :lvar
3173
+
3174
+ result = [identifier, line]
3175
+ }
3176
+
3177
+ f_arg_asgn: f_norm_arg
3178
+
3179
+ f_arg_item: f_arg_asgn
3180
+ | tLPAREN f_margs rparen
3181
+ {
3182
+ _, margs, _ = val
3183
+
3184
+ result = margs
3185
+ }
3186
+
3187
+ f_arg: f_arg_item
3188
+ {
3189
+ result = new_arg val
3190
+ }
3191
+ | f_arg tCOMMA f_arg_item
3192
+ {
3193
+ list, _, item = val
3194
+
3195
+ if list.sexp_type == :args then
3196
+ result = list
3197
+ else
3198
+ result = s(:args, list).line list.line
3199
+ end
3200
+
3201
+ result << (Sexp === item ? item : item.first)
3202
+ }
3203
+
3204
+ f_label: tLABEL
3205
+
3206
+ f_kw: f_label arg_value
3207
+ {
3208
+ # TODO: new_kw_arg
3209
+ (label, line), arg = val
3210
+
3211
+ identifier = label.to_sym
3212
+ self.env[identifier] = :lvar
3213
+
3214
+ kwarg = s(:kwarg, identifier, arg).line line
3215
+ result = s(:array, kwarg).line line
3216
+ }
3217
+ | f_label
3218
+ {
3219
+ (label, line), = val
3220
+
3221
+ id = label.to_sym
3222
+ self.env[id] = :lvar
3223
+
3224
+ result = s(:array, s(:kwarg, id).line(line)).line line
3225
+ }
3226
+
3227
+ f_block_kw: f_label primary_value
3228
+ {
3229
+ # TODO: new_kw_arg
3230
+ (label, line), expr = val
3231
+ id = label.to_sym
3232
+ self.env[id] = :lvar
3233
+
3234
+ result = s(:array, s(:kwarg, id, expr).line(line)).line line
3235
+ }
3236
+ | f_label
3237
+ {
3238
+ # TODO: new_kw_arg
3239
+ (label, line), = val
3240
+ id = label.to_sym
3241
+ self.env[id] = :lvar
3242
+
3243
+ result = s(:array, s(:kwarg, id).line(line)).line line
3244
+ }
3245
+
3246
+ f_block_kwarg: f_block_kw
3247
+ | f_block_kwarg tCOMMA f_block_kw
3248
+ {
3249
+ list, _, item = val
3250
+ result = list << item.last
3251
+ }
3252
+
3253
+ f_kwarg: f_kw
3254
+ | f_kwarg tCOMMA f_kw
3255
+ {
3256
+ result = args val
3257
+ }
3258
+
3259
+ kwrest_mark: tPOW
3260
+ | tDSTAR
3261
+
3262
+ f_no_kwarg: kwrest_mark kNIL
3263
+ {
3264
+ (_, line), _ = val
3265
+ result = [:"**nil", line]
3266
+ }
3267
+
3268
+ f_kwrest: kwrest_mark tIDENTIFIER
3269
+ {
3270
+ _, (id, line) = val
3271
+
3272
+ name = id.to_sym
3273
+ self.assignable [name, line]
3274
+ result = [:"**#{name}", line]
3275
+ }
3276
+ | kwrest_mark
3277
+ {
3278
+ id = :"**"
3279
+ self.env[id] = :lvar # TODO: needed?!?
3280
+ result = [id, lexer.lineno] # TODO: tPOW/tDSTAR include lineno
3281
+ }
3282
+
3283
+ f_opt: f_arg_asgn
3284
+ f_eq
3285
+ arg_value
3286
+ {
3287
+ lhs, _, rhs = val
3288
+ result = self.assignable lhs, rhs
3289
+ # TODO: detect duplicate names
3290
+ # TODO? p->cur_arg = 0;
3291
+ # TODO? p->ctxt.in_argdef = 1;
3292
+ }
3293
+
3294
+ f_block_opt: f_arg_asgn
3295
+ f_eq
3296
+ primary_value
3297
+ {
3298
+ lhs, _, rhs = val
3299
+ result = self.assignable lhs, rhs
3300
+ # TODO? p->cur_arg = 0;
3301
+ # TODO? p->ctxt.in_argdef = 1;
3302
+ }
3303
+
3304
+ f_block_optarg: f_block_opt
3305
+ {
3306
+ optblk, = val
3307
+ result = s(:block, optblk).line optblk.line
3308
+ }
3309
+ | f_block_optarg tCOMMA f_block_opt
3310
+ {
3311
+ optarg, _, optblk = val
3312
+ result = optarg
3313
+ result << optblk
3314
+ }
3315
+
3316
+ f_optarg: f_opt
3317
+ {
3318
+ opt, = val
3319
+ result = s(:block, opt).line opt.line
3320
+ }
3321
+ | f_optarg tCOMMA f_opt
3322
+ {
3323
+ result = self.block_append val[0], val[2]
3324
+ }
3325
+
3326
+ restarg_mark: tSTAR2 | tSTAR
3327
+
3328
+ f_rest_arg: restarg_mark tIDENTIFIER
3329
+ {
3330
+ # TODO: differs from parse.y - needs tests
3331
+ _, (id, line) = val
3332
+ name = id.to_sym
3333
+ self.assignable [name, line]
3334
+ result = [:"*#{name}", line]
3335
+ }
3336
+ | restarg_mark
3337
+ {
3338
+ name = :"*"
3339
+ self.env[name] = :lvar
3340
+ result = [name, lexer.lineno] # FIX: tSTAR to include lineno
3341
+ }
3342
+
3343
+ blkarg_mark: tAMPER2 | tAMPER
3344
+
3345
+ f_block_arg: blkarg_mark tIDENTIFIER
3346
+ {
3347
+ _, (id, line) = val
3348
+ identifier = id.to_sym
3349
+
3350
+ self.env[identifier] = :lvar
3351
+ result = ["&#{identifier}".to_sym, line]
3352
+ }
3353
+ | blkarg_mark
3354
+ {
3355
+ (_, line), = val
3356
+
3357
+ result = [:&, line]
3358
+ }
3359
+
3360
+ opt_f_block_arg: tCOMMA f_block_arg
3361
+ {
3362
+ _, arg = val
3363
+ result = arg
3364
+ }
3365
+ |
3366
+ {
3367
+ result = nil
3368
+ }
3369
+
3370
+ singleton: var_ref
3371
+ | tLPAREN2
3372
+ {
3373
+ lexer.lex_state = EXPR_BEG
3374
+ }
3375
+ expr rparen
3376
+ {
3377
+ result = val[2]
3378
+ yyerror "Can't define single method for literals." if
3379
+ result.sexp_type == :lit
3380
+ }
3381
+
3382
+ assoc_list: none
3383
+ {
3384
+ result = s(:array).line lexer.lineno
3385
+ }
3386
+ | assocs trailer
3387
+
3388
+ assocs: assoc
3389
+ | assocs tCOMMA assoc
3390
+ {
3391
+ list = val[0].dup
3392
+ more = val[2].sexp_body
3393
+ list.push(*more) unless more.empty?
3394
+ result = list
3395
+ result.sexp_type = :hash
3396
+ }
3397
+
3398
+ assoc: arg_value tASSOC arg_value
3399
+ {
3400
+ v1, _, v2 = val
3401
+ result = s(:array, v1, v2).line v1.line
3402
+ }
3403
+ | tLABEL arg_value
3404
+ {
3405
+ label, arg = val
3406
+
3407
+ lit = wrap :lit, label
3408
+ result = s(:array, lit, arg).line lit.line
3409
+ }
3410
+ | tLABEL
3411
+ {
3412
+ lit = wrap :lit, val[0]
3413
+ arg = nil
3414
+
3415
+ result = s(:array, lit, arg).line lit.line
3416
+ }
3417
+ | tSTRING_BEG string_contents tLABEL_END arg_value
3418
+ {
3419
+ (_, line), sym, _, value = val
3420
+
3421
+ sym.sexp_type = :dsym
3422
+
3423
+ result = s(:array, sym, value).line line
3424
+ }
3425
+ | tDSTAR arg_value
3426
+ {
3427
+ _, arg = val
3428
+ line = arg.line
3429
+ result = s(:array, s(:kwsplat, arg).line(line)).line line
3430
+ }
3431
+
3432
+ operation: tIDENTIFIER | tCONSTANT | tFID
3433
+ operation2: tIDENTIFIER | tCONSTANT | tFID | op
3434
+ operation3: tIDENTIFIER | tFID | op
3435
+ dot_or_colon: tDOT | tCOLON2
3436
+ call_op: tDOT
3437
+ | tLONELY # TODO: rename tANDDOT?
3438
+
3439
+ call_op2: call_op
3440
+ | tCOLON2
3441
+
3442
+ opt_terms: | terms
3443
+ opt_nl: | tNL
3444
+ rparen: opt_nl tRPAREN
3445
+ # TODO:
3446
+ # {
3447
+ # _, close = val
3448
+ # result = [close, lexer.lineno]
3449
+ # }
3450
+ rbracket: opt_nl tRBRACK
3451
+ {
3452
+ _, close = val
3453
+ result = [close, lexer.lineno]
3454
+ }
3455
+ rbrace: opt_nl tRCURLY
3456
+ {
3457
+ _, close = val
3458
+ result = [close, lexer.lineno]
3459
+ }
3460
+ trailer: | tNL | tCOMMA
3461
+
3462
+ term: tSEMI { yyerrok }
3463
+ | tNL
3464
+
3465
+ terms: term
3466
+ | terms tSEMI { yyerrok }
3467
+
3468
+ none: { result = nil; }
3469
+ end
3470
+
3471
+ ---- inner
3472
+
3473
+ require "ruby_lexer"
3474
+ require "ruby_parser_extras"
3475
+ include RubyLexer::State::Values
3476
+
3477
+ # :stopdoc:
3478
+
3479
+ # Local Variables: **
3480
+ # racc-token-length-max:14 **
3481
+ # End: **