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