ruby_parser 3.15.0 → 3.19.2

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 (47) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/History.rdoc +151 -0
  4. data/Manifest.txt +7 -0
  5. data/README.rdoc +9 -6
  6. data/Rakefile +141 -31
  7. data/bin/ruby_parse_extract_error +1 -1
  8. data/compare/normalize.rb +8 -3
  9. data/debugging.md +133 -0
  10. data/gauntlet.md +107 -0
  11. data/lib/rp_extensions.rb +15 -36
  12. data/lib/rp_stringscanner.rb +20 -51
  13. data/lib/ruby20_parser.rb +7544 -3633
  14. data/lib/ruby20_parser.y +335 -257
  15. data/lib/ruby21_parser.rb +7518 -3678
  16. data/lib/ruby21_parser.y +330 -254
  17. data/lib/ruby22_parser.rb +7652 -3689
  18. data/lib/ruby22_parser.y +334 -256
  19. data/lib/ruby23_parser.rb +7659 -3702
  20. data/lib/ruby23_parser.y +334 -256
  21. data/lib/ruby24_parser.rb +7748 -3721
  22. data/lib/ruby24_parser.y +334 -256
  23. data/lib/ruby25_parser.rb +7748 -3721
  24. data/lib/ruby25_parser.y +334 -256
  25. data/lib/ruby26_parser.rb +7755 -3726
  26. data/lib/ruby26_parser.y +334 -255
  27. data/lib/ruby27_parser.rb +10290 -4518
  28. data/lib/ruby27_parser.y +933 -254
  29. data/lib/ruby30_parser.rb +13258 -0
  30. data/lib/ruby30_parser.y +3459 -0
  31. data/lib/ruby31_parser.rb +13638 -0
  32. data/lib/ruby31_parser.y +3493 -0
  33. data/lib/ruby3_parser.yy +3548 -0
  34. data/lib/ruby_lexer.rb +277 -599
  35. data/lib/ruby_lexer.rex +28 -21
  36. data/lib/ruby_lexer.rex.rb +60 -24
  37. data/lib/ruby_lexer_strings.rb +638 -0
  38. data/lib/ruby_parser.rb +4 -0
  39. data/lib/ruby_parser.yy +974 -261
  40. data/lib/ruby_parser_extras.rb +355 -114
  41. data/test/test_ruby_lexer.rb +226 -129
  42. data/test/test_ruby_parser.rb +1653 -267
  43. data/tools/munge.rb +36 -8
  44. data/tools/ripper.rb +15 -10
  45. data.tar.gz.sig +0 -0
  46. metadata +55 -37
  47. metadata.gz.sig +0 -0
data/lib/ruby_parser.yy CHANGED
@@ -36,7 +36,7 @@ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
36
36
  tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
37
37
  tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
38
38
  tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA
39
- tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND tUBANG
39
+ tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND
40
40
  #if V >= 21
41
41
  tRATIONAL tIMAGINARY
42
42
  #endif
@@ -46,6 +46,9 @@ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
46
46
  #if V >= 23
47
47
  tLONELY
48
48
  #endif
49
+ #if V >= 26
50
+ tBDOT2 tBDOT3
51
+ #endif
49
52
 
50
53
  preclow
51
54
  nonassoc tLOWEST
@@ -57,7 +60,7 @@ preclow
57
60
  right tEQL tOP_ASGN
58
61
  left kRESCUE_MOD
59
62
  right tEH tCOLON
60
- nonassoc tDOT2 tDOT3
63
+ nonassoc tDOT2 tDOT3 tBDOT2 tBDOT3
61
64
  left tOROP
62
65
  left tANDOP
63
66
  nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
@@ -80,6 +83,9 @@ rule
80
83
  top_compstmt
81
84
  {
82
85
  result = new_compstmt val
86
+
87
+ lexer.cond.pop # local_pop
88
+ lexer.cmdarg.pop
83
89
  }
84
90
 
85
91
  top_compstmt: top_stmts opt_terms
@@ -100,7 +106,7 @@ rule
100
106
  | klBEGIN
101
107
  {
102
108
  if (self.in_def || self.in_single > 0) then
103
- debug20 1
109
+ debug 11
104
110
  yyerror "BEGIN in method"
105
111
  end
106
112
  self.env.extend
@@ -125,7 +131,13 @@ rule
125
131
  bodystmt: compstmt opt_rescue k_else
126
132
  {
127
133
  res = _values[-2]
134
+ # TODO: move down to main match so I can just use val
135
+
136
+ #if V >= 26
128
137
  yyerror "else without rescue is useless" unless res
138
+ #else
139
+ warn "else without rescue is useless" unless res
140
+ #endif
129
141
  }
130
142
  compstmt
131
143
  opt_ensure
@@ -155,7 +167,7 @@ rule
155
167
  | error stmt
156
168
  {
157
169
  result = val[1]
158
- debug20 2, val, result
170
+ debug 12
159
171
  }
160
172
 
161
173
  stmt_or_begin: stmt
@@ -163,6 +175,10 @@ rule
163
175
  {
164
176
  yyerror "BEGIN is permitted only at toplevel"
165
177
  }
178
+ begin_block
179
+ {
180
+ result = val[2] # wtf?
181
+ }
166
182
 
167
183
  stmt: kALIAS fitem
168
184
  {
@@ -175,12 +191,12 @@ rule
175
191
  }
176
192
  | kALIAS tGVAR tGVAR
177
193
  {
178
- (_, line), lhs, rhs = val
194
+ (_, line), (lhs, _), (rhs, _) = val
179
195
  result = s(:valias, lhs.to_sym, rhs.to_sym).line line
180
196
  }
181
197
  | kALIAS tGVAR tBACK_REF
182
198
  {
183
- (_, line), lhs, rhs = val
199
+ (_, line), (lhs, _), (rhs, _) = val
184
200
  result = s(:valias, lhs.to_sym, :"$#{rhs}").line line
185
201
  }
186
202
  | kALIAS tGVAR tNTH_REF
@@ -223,7 +239,7 @@ rule
223
239
  (_, line), _, stmt, _ = val
224
240
 
225
241
  if (self.in_def || self.in_single > 0) then
226
- debug20 3
242
+ debug 13
227
243
  yyerror "END in method; use at_exit"
228
244
  end
229
245
 
@@ -244,6 +260,19 @@ rule
244
260
  {
245
261
  result = new_masgn val[0], val[2], :wrap
246
262
  }
263
+ #endif
264
+ #if V >= 27
265
+ | mlhs tEQL mrhs_arg kRESCUE_MOD stmt
266
+ {
267
+ # unwraps s(:to_ary, rhs)
268
+ lhs, _, (_, rhs), _, resbody = val
269
+
270
+ resbody = new_resbody s(:array).line(resbody.line), resbody
271
+
272
+ result = new_masgn lhs, new_rescue(rhs, resbody), :wrap
273
+ }
274
+ #endif
275
+ #if V == 20
247
276
  | mlhs tEQL mrhs
248
277
  #else
249
278
  | mlhs tEQL mrhs_arg
@@ -271,32 +300,31 @@ rule
271
300
  }
272
301
  | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
273
302
  {
274
- prim, _, id, opasgn, rhs = val
275
- result = s(:op_asgn, prim, rhs, id.to_sym, opasgn.to_sym)
276
- if val[1] == '&.'
277
- result.sexp_type = :safe_op_asgn
278
- end
279
- result.line = val[0].line
303
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
304
+
305
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
306
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
307
+ result.line prim.line
280
308
  }
281
309
  | primary_value call_op tCONSTANT tOP_ASGN command_rhs
282
310
  {
283
- result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
284
- if val[1] == '&.'
285
- result.sexp_type = :safe_op_asgn
286
- end
287
- result.line = val[0].line
311
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
312
+
313
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
314
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
315
+ result.line prim.line
288
316
  }
289
317
  | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
290
318
  {
291
- lhs1, _, lhs2, op, rhs = val
319
+ lhs1, _, (lhs2, line), (id, _), rhs = val
292
320
 
293
- result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
321
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
294
322
  }
295
323
  | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
296
324
  {
297
- lhs1, _, lhs2, op, rhs = val
325
+ lhs1, _, (lhs2, line), (id, _), rhs = val
298
326
 
299
- result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
327
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
300
328
  }
301
329
  | backref tOP_ASGN command_rhs
302
330
  {
@@ -344,7 +372,31 @@ rule
344
372
  # TODO: fix line number to tBANG... but causes BAD shift/reduce conflict
345
373
  # REFACTOR: call_uni_op -- see parse26.y
346
374
  }
375
+ #if V >= 27
347
376
  | arg
377
+ kIN
378
+ {
379
+ # TODO? value_expr($1);
380
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
381
+ self.lexer.command_start = false
382
+ result = self.in_kwarg
383
+ self.in_kwarg = true
384
+ self.env.extend
385
+ }
386
+ p_expr
387
+ {
388
+ self.env.unextend
389
+
390
+ expr, _, old_kwarg, pat = val
391
+
392
+ expr = value_expr expr
393
+
394
+ self.in_kwarg = old_kwarg
395
+ pat_in = new_in pat, nil, nil, expr.line
396
+ result = new_case expr, pat_in, expr.line
397
+ }
398
+ #endif
399
+ | arg =tLBRACE_ARG
348
400
 
349
401
  expr_value: expr
350
402
  {
@@ -369,7 +421,7 @@ rule
369
421
  block_command: block_call
370
422
  | block_call call_op2 operation2 command_args
371
423
  {
372
- blk, _, msg, args = val
424
+ blk, _, (msg, _line), args = val
373
425
  result = new_call(blk, msg.to_sym, args).line blk.line
374
426
  }
375
427
 
@@ -383,15 +435,15 @@ rule
383
435
  _, line, body, _ = val
384
436
 
385
437
  result = body
386
- result.line = line
438
+ result.line line
387
439
 
388
440
  # self.env.unextend
389
441
  }
390
442
 
391
443
  fcall: operation
392
444
  {
393
- msg, = val
394
- result = new_call(nil, msg.to_sym).line lexer.lineno
445
+ (msg, line), = val
446
+ result = new_call(nil, msg.to_sym).line line
395
447
  }
396
448
 
397
449
  command: fcall command_args =tLOWEST
@@ -414,12 +466,14 @@ rule
414
466
  }
415
467
  | primary_value call_op operation2 command_args =tLOWEST
416
468
  {
417
- lhs, callop, op, args = val
469
+ lhs, callop, (op, _), args = val
470
+
418
471
  result = new_call lhs, op.to_sym, args, callop
472
+ result.line lhs.line
419
473
  }
420
474
  | primary_value call_op operation2 command_args cmd_brace_block
421
475
  {
422
- recv, _, msg, args, block = val
476
+ recv, _, (msg, _line), args, block = val
423
477
  call = new_call recv, msg.to_sym, args, val[1]
424
478
 
425
479
  block_dup_check call, block
@@ -429,11 +483,14 @@ rule
429
483
  }
430
484
  | primary_value tCOLON2 operation2 command_args =tLOWEST
431
485
  {
432
- result = new_call val[0], val[2].to_sym, val[3]
486
+ lhs, _, (id, line), args = val
487
+
488
+ result = new_call lhs, id.to_sym, args
489
+ result.line line
433
490
  }
434
491
  | primary_value tCOLON2 operation2 command_args cmd_brace_block
435
492
  {
436
- recv, _, msg, args, block = val
493
+ recv, _, (msg, _line), args, block = val
437
494
  call = new_call recv, msg.to_sym, args
438
495
 
439
496
  block_dup_check call, block
@@ -591,25 +648,29 @@ rule
591
648
  }
592
649
  | primary_value call_op tIDENTIFIER
593
650
  {
594
- result = new_attrasgn val[0], val[2], val[1]
651
+ lhs, call_op, (id, _line) = val
652
+
653
+ result = new_attrasgn lhs, id, call_op
595
654
  }
596
655
  | primary_value tCOLON2 tIDENTIFIER
597
656
  {
598
- recv, _, id = val
657
+ recv, _, (id, _line) = val
599
658
  result = new_attrasgn recv, id
600
659
  }
601
660
  | primary_value call_op tCONSTANT
602
661
  {
603
- result = new_attrasgn val[0], val[2], val[1]
662
+ lhs, call_op, (id, _line) = val
663
+
664
+ result = new_attrasgn lhs, id, call_op
604
665
  }
605
666
  | primary_value tCOLON2 tCONSTANT
606
667
  {
607
668
  if (self.in_def || self.in_single > 0) then
608
- debug20 7
669
+ debug 14
609
670
  yyerror "dynamic constant assignment"
610
671
  end
611
672
 
612
- expr, _, id = val
673
+ expr, _, (id, _line) = val
613
674
  l = expr.line
614
675
 
615
676
  result = s(:const, s(:colon2, expr, id.to_sym).line(l), nil).line l
@@ -617,58 +678,65 @@ rule
617
678
  | tCOLON3 tCONSTANT
618
679
  {
619
680
  if (self.in_def || self.in_single > 0) then
620
- debug20 8
681
+ debug 15
621
682
  yyerror "dynamic constant assignment"
622
683
  end
623
684
 
624
- _, id = val
625
- l = lexer.lineno
685
+ _, (id, l) = val
626
686
 
627
687
  result = s(:const, nil, s(:colon3, id.to_sym).line(l)).line l
628
688
  }
629
689
  | backref
630
690
  {
631
- self.backref_assign_error val[0]
691
+ ref, = val
692
+
693
+ self.backref_assign_error ref
632
694
  }
633
695
 
634
696
  lhs: user_variable
635
697
  {
636
- line = lexer.lineno
637
- result = self.assignable val[0]
638
- result.line = line
698
+ var, = val
699
+
700
+ result = self.assignable var
639
701
  }
640
702
  | keyword_variable
641
703
  {
642
- line = lexer.lineno
643
- result = self.assignable val[0]
644
- result.line = line
645
- debug20 9, val, result
704
+ var, = val
705
+
706
+ result = self.assignable var
707
+
708
+ debug 16
646
709
  }
647
710
  | primary_value tLBRACK2 opt_call_args rbracket
648
711
  {
649
712
  lhs, _, args, _ = val
713
+
650
714
  result = self.aryset lhs, args
651
715
  }
652
716
  | primary_value call_op tIDENTIFIER # REFACTOR
653
717
  {
654
- lhs, op, id = val
718
+ lhs, op, (id, _line) = val
719
+
655
720
  result = new_attrasgn lhs, id, op
656
721
  }
657
722
  | primary_value tCOLON2 tIDENTIFIER
658
723
  {
659
- lhs, _, id = val
724
+ lhs, _, (id, _line) = val
725
+
660
726
  result = new_attrasgn lhs, id
661
727
  }
662
728
  | primary_value call_op tCONSTANT # REFACTOR?
663
729
  {
664
- result = new_attrasgn val[0], val[2], val[1]
730
+ lhs, call_op, (id, _line) = val
731
+
732
+ result = new_attrasgn lhs, id, call_op
665
733
  }
666
734
  | primary_value tCOLON2 tCONSTANT
667
735
  {
668
- expr, _, id = val
736
+ expr, _, (id, _line) = val
669
737
 
670
738
  if (self.in_def || self.in_single > 0) then
671
- debug20 10
739
+ debug 17
672
740
  yyerror "dynamic constant assignment"
673
741
  end
674
742
 
@@ -677,14 +745,13 @@ rule
677
745
  }
678
746
  | tCOLON3 tCONSTANT
679
747
  {
680
- _, id = val
748
+ _, (id, l) = val
681
749
 
682
750
  if (self.in_def || self.in_single > 0) then
683
- debug20 11
751
+ debug 18
684
752
  yyerror "dynamic constant assignment"
685
753
  end
686
754
 
687
- l = lexer.lineno
688
755
  result = s(:const, s(:colon3, id.to_sym).line(l)).line l
689
756
  }
690
757
  | backref
@@ -700,16 +767,16 @@ rule
700
767
 
701
768
  cpath: tCOLON3 cname
702
769
  {
703
- _, name = val
704
- result = s(:colon3, name.to_sym).line lexer.lineno
770
+ result = wrap :colon3, val[1]
705
771
  }
706
772
  | cname
707
773
  {
708
- result = val[0].to_sym
774
+ (id, line), = val
775
+ result = [id.to_sym, line] # TODO: sexp?
709
776
  }
710
777
  | primary_value tCOLON2 cname
711
778
  {
712
- pval, _, name = val
779
+ pval, _, (name, _line) = val
713
780
 
714
781
  result = s(:colon2, pval, name.to_sym)
715
782
  result.line pval.line
@@ -719,24 +786,15 @@ rule
719
786
  | op
720
787
  {
721
788
  lexer.lex_state = EXPR_END
722
- result = val[0]
723
789
  }
724
790
 
725
791
  | reswords
726
- {
727
- (sym, _line), = val
728
- lexer.lex_state = EXPR_END
729
- result = sym
730
- }
731
792
 
732
- fsym: fname | symbol
733
-
734
- fitem: fsym
793
+ fitem: fname
735
794
  {
736
- id, = val
737
- result = s(:lit, id.to_sym).line lexer.lineno
795
+ result = wrap :lit, val[0]
738
796
  }
739
- | dsym
797
+ | symbol
740
798
 
741
799
  undef_list: fitem
742
800
  {
@@ -757,10 +815,6 @@ rule
757
815
  | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
758
816
  | tSTAR | tDIVIDE | tPERCENT | tPOW | tDSTAR | tBANG | tTILDE
759
817
  | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
760
- #if V >= 20
761
- # TODO: tUBANG dead?
762
- | tUBANG
763
- #endif
764
818
 
765
819
  reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
766
820
  | kALIAS | kAND | kBEGIN | kBREAK | kCASE
@@ -794,26 +848,22 @@ rule
794
848
  }
795
849
  | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
796
850
  {
797
- lhs, _, id, op, rhs = val
851
+ lhs, _, (id, _line), (op, _), rhs = val
798
852
 
799
853
  result = s(:op_asgn, lhs, rhs, id.to_sym, op.to_sym).line lhs.line
800
854
  }
801
855
  | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
802
856
  {
803
- lhs1, _, lhs2, op, rhs = val
857
+ lhs1, _, (lhs2, _line), op, rhs = val
804
858
 
805
859
  lhs = s(:colon2, lhs1, lhs2.to_sym).line lhs1.line
806
860
  result = new_const_op_asgn [lhs, op, rhs]
807
861
  }
808
- | tCOLON3 tCONSTANT
809
- {
810
- result = self.lexer.lineno
811
- }
812
- tOP_ASGN arg_rhs
862
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
813
863
  {
814
- _, lhs, line, op, rhs = val
864
+ _, lhs, op, rhs = val
815
865
 
816
- lhs = s(:colon3, lhs.to_sym).line line
866
+ lhs = wrap :colon3, lhs
817
867
  result = new_const_op_asgn [lhs, op, rhs]
818
868
  }
819
869
  | backref tOP_ASGN arg_rhs
@@ -825,7 +875,7 @@ rule
825
875
  | arg tDOT2 arg
826
876
  {
827
877
  v1, v2 = val[0], val[2]
828
- if v1.node_type == :lit and v2.node_type == :lit and Integer === v1.last and Integer === v2.last then
878
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
829
879
  result = s(:lit, (v1.last)..(v2.last)).line v1.line
830
880
  else
831
881
  result = s(:dot2, v1, v2).line v1.line
@@ -834,7 +884,7 @@ rule
834
884
  | arg tDOT3 arg
835
885
  {
836
886
  v1, v2 = val[0], val[2]
837
- if v1.node_type == :lit and v2.node_type == :lit and Integer === v1.last and Integer === v2.last then
887
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
838
888
  result = s(:lit, (v1.last)...(v2.last)).line v1.line
839
889
  else
840
890
  result = s(:dot3, v1, v2).line v1.line
@@ -856,6 +906,24 @@ rule
856
906
  result = s(:dot3, v1, v2).line v1.line
857
907
  }
858
908
  #endif
909
+
910
+ #if V >= 27
911
+ | tBDOT2 arg
912
+ {
913
+ _, v2, = val
914
+ v1 = nil
915
+
916
+ result = s(:dot2, v1, v2).line v2.line
917
+ }
918
+ | tBDOT3 arg
919
+ {
920
+ _, v2 = val
921
+ v1 = nil
922
+
923
+ result = s(:dot3, v1, v2).line v2.line
924
+ }
925
+ #endif
926
+
859
927
  | arg tPLUS arg
860
928
  {
861
929
  result = new_call val[0], :+, argl(val[2])
@@ -883,20 +951,22 @@ rule
883
951
  #if V == 20
884
952
  | tUMINUS_NUM tINTEGER tPOW arg
885
953
  {
886
- lit = s(:lit, val[1]).line lexer.lineno
887
- result = new_call(new_call(lit, :"**", argl(val[3])), :"-@")
954
+ _, (num, line), _, arg = val
955
+ lit = s(:lit, num).line line
956
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
888
957
  }
889
958
  | tUMINUS_NUM tFLOAT tPOW arg
890
959
  #else
891
960
  | tUMINUS_NUM simple_numeric tPOW arg
892
961
  #endif
893
962
  {
894
- lit = s(:lit, val[1]).line lexer.lineno
895
- result = new_call(new_call(lit, :"**", argl(val[3])), :"-@")
963
+ _, (num, line), _, arg = val
964
+ lit = s(:lit, num).line line
965
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
896
966
 
897
967
  #if V == 20
898
968
  ## TODO: why is this 2.0 only?
899
- debug20 12, val, result
969
+ debug 19
900
970
  #endif
901
971
  }
902
972
  | tUPLUS arg
@@ -995,12 +1065,12 @@ rule
995
1065
 
996
1066
  rel_expr: arg relop arg =tGT
997
1067
  {
998
- lhs, op, rhs = val
1068
+ lhs, (op, _), rhs = val
999
1069
  result = new_call lhs, op.to_sym, argl(rhs)
1000
1070
  }
1001
1071
  | rel_expr relop arg =tGT
1002
1072
  {
1003
- lhs, op, rhs = val
1073
+ lhs, (op, _), rhs = val
1004
1074
  warn "comparison '%s' after comparison", op
1005
1075
  result = new_call lhs, op.to_sym, argl(rhs)
1006
1076
  }
@@ -1040,6 +1110,26 @@ rule
1040
1110
  _, args, _ = val
1041
1111
  result = args
1042
1112
  }
1113
+ #if V >= 27
1114
+ | tLPAREN2 args tCOMMA args_forward rparen
1115
+ {
1116
+ yyerror "Unexpected ..." unless
1117
+ self.lexer.is_local_id(:"*") &&
1118
+ self.lexer.is_local_id(:"**") &&
1119
+ self.lexer.is_local_id(:"&")
1120
+
1121
+ result = call_args val
1122
+ }
1123
+ | tLPAREN2 args_forward rparen
1124
+ {
1125
+ yyerror "Unexpected ..." unless
1126
+ self.lexer.is_local_id(:"*") &&
1127
+ self.lexer.is_local_id(:"**") &&
1128
+ self.lexer.is_local_id(:"&")
1129
+
1130
+ result = call_args val
1131
+ }
1132
+ #endif
1043
1133
 
1044
1134
  opt_paren_args: none
1045
1135
  | paren_args
@@ -1193,8 +1283,9 @@ rule
1193
1283
  | backref
1194
1284
  | tFID
1195
1285
  {
1196
- msg, = val
1286
+ (msg, line), = val
1197
1287
  result = new_call nil, msg.to_sym
1288
+ result.line line
1198
1289
  }
1199
1290
  | k_begin
1200
1291
  {
@@ -1236,15 +1327,13 @@ rule
1236
1327
  }
1237
1328
  | primary_value tCOLON2 tCONSTANT
1238
1329
  {
1239
- expr, _, id = val
1330
+ expr, _, (id, _line) = val
1240
1331
 
1241
1332
  result = s(:colon2, expr, id.to_sym).line expr.line
1242
1333
  }
1243
1334
  | tCOLON3 tCONSTANT
1244
1335
  {
1245
- _, id = val
1246
-
1247
- result = s(:colon3, id.to_sym).line lexer.lineno
1336
+ result = wrap :colon3, val[1]
1248
1337
  }
1249
1338
  | tLBRACK { result = lexer.lineno } aref_args tRBRACK
1250
1339
  {
@@ -1268,15 +1357,21 @@ rule
1268
1357
  }
1269
1358
  | kYIELD tLPAREN2 call_args rparen
1270
1359
  {
1271
- result = new_yield val[2]
1360
+ (_, line), _, args, _ = val
1361
+
1362
+ result = new_yield(args).line line
1272
1363
  }
1273
1364
  | kYIELD tLPAREN2 rparen
1274
1365
  {
1275
- result = new_yield
1366
+ (_, line), _, _ = val
1367
+
1368
+ result = new_yield.line line
1276
1369
  }
1277
1370
  | kYIELD
1278
1371
  {
1279
- result = new_yield
1372
+ (_, line), = val
1373
+
1374
+ result = new_yield.line line
1280
1375
  }
1281
1376
  | kDEFINED opt_nl tLPAREN2 expr rparen
1282
1377
  {
@@ -1291,7 +1386,7 @@ rule
1291
1386
  }
1292
1387
  | kNOT tLPAREN2 rparen
1293
1388
  {
1294
- debug20 14, val, result
1389
+ debug 20
1295
1390
  }
1296
1391
  | fcall brace_block
1297
1392
  {
@@ -1309,9 +1404,10 @@ rule
1309
1404
  iter.insert 1, call # FIX
1310
1405
  result = iter
1311
1406
  }
1312
- | tLAMBDA lambda
1407
+ | lambda
1313
1408
  {
1314
- result = val[1] # TODO: fix lineno
1409
+ expr, = val
1410
+ result = expr
1315
1411
  }
1316
1412
  | k_if expr_value then compstmt if_tail k_end
1317
1413
  {
@@ -1343,6 +1439,14 @@ rule
1343
1439
  (_, line), _, body, _ = val
1344
1440
  result = new_case nil, body, line
1345
1441
  }
1442
+ #if V >= 27
1443
+ | k_case expr_value opt_terms p_case_body k_end
1444
+ {
1445
+ (_, line), expr, _, body, _ = val
1446
+
1447
+ result = new_case expr, body, line
1448
+ }
1449
+ #endif
1346
1450
  | k_for for_var kIN expr_value_do compstmt k_end
1347
1451
  {
1348
1452
  _, var, _, iter, body, _ = val
@@ -1354,7 +1458,6 @@ rule
1354
1458
  }
1355
1459
  cpath superclass
1356
1460
  {
1357
- self.comments.push self.lexer.comments
1358
1461
  if (self.in_def || self.in_single > 0) then
1359
1462
  yyerror "class definition in method body"
1360
1463
  end
@@ -1364,7 +1467,7 @@ rule
1364
1467
  {
1365
1468
  result = new_class val
1366
1469
  self.env.unextend
1367
- self.lexer.comments # we don't care about comments in the body
1470
+ self.lexer.ignore_body_comments
1368
1471
  }
1369
1472
  | k_class tLSHFT
1370
1473
  {
@@ -1385,7 +1488,7 @@ rule
1385
1488
  {
1386
1489
  result = new_sclass val
1387
1490
  self.env.unextend
1388
- self.lexer.comments # we don't care about comments in the body
1491
+ self.lexer.ignore_body_comments
1389
1492
  }
1390
1493
  | k_module
1391
1494
  {
@@ -1393,7 +1496,6 @@ rule
1393
1496
  }
1394
1497
  cpath
1395
1498
  {
1396
- self.comments.push self.lexer.comments
1397
1499
  yyerror "module definition in method body" if
1398
1500
  self.in_def or self.in_single > 0
1399
1501
 
@@ -1403,7 +1505,7 @@ rule
1403
1505
  {
1404
1506
  result = new_module val
1405
1507
  self.env.unextend
1406
- self.lexer.comments # we don't care about comments in the body
1508
+ self.lexer.ignore_body_comments
1407
1509
  }
1408
1510
  | k_def fname
1409
1511
  {
@@ -1413,21 +1515,17 @@ rule
1413
1515
  self.env.extend
1414
1516
  lexer.cmdarg.push false
1415
1517
  lexer.cond.push false
1416
-
1417
- self.comments.push self.lexer.comments
1418
1518
  }
1419
- f_arglist bodystmt { result = lexer.lineno } k_end
1519
+ f_arglist bodystmt k_end
1420
1520
  {
1421
- in_def = val[2]
1422
-
1423
- result = new_defn val
1521
+ result, in_def = new_defn val
1424
1522
 
1425
1523
  lexer.cond.pop # group = local_pop
1426
1524
  lexer.cmdarg.pop
1427
1525
  self.env.unextend
1428
1526
  self.in_def = in_def
1429
1527
 
1430
- self.lexer.comments # we don't care about comments in the body
1528
+ self.lexer.ignore_body_comments
1431
1529
  }
1432
1530
  | k_def singleton dot_or_colon
1433
1531
  {
@@ -1435,7 +1533,7 @@ rule
1435
1533
  }
1436
1534
  fname
1437
1535
  {
1438
- result = [self.in_def, lexer.lineno]
1536
+ result = self.in_def
1439
1537
 
1440
1538
  self.in_single += 1 # TODO: remove?
1441
1539
 
@@ -1445,13 +1543,18 @@ rule
1445
1543
  lexer.cond.push false
1446
1544
 
1447
1545
  lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
1448
- self.comments.push self.lexer.comments
1449
1546
  }
1450
1547
  f_arglist bodystmt k_end
1451
1548
  {
1452
- _, _recv, _, _, _name, (in_def, _lineno), _args, _body, _ = val
1453
1549
 
1454
- result = new_defs val
1550
+ # [kdef, recv, _, _, (name, line), in_def, args, body, kend]
1551
+ # =>
1552
+ # [kdef, recv, (name, line), in_def, args, body, kend]
1553
+
1554
+ val.delete_at 3
1555
+ val.delete_at 2
1556
+
1557
+ result, in_def = new_defs val
1455
1558
 
1456
1559
  lexer.cond.pop # group = local_pop
1457
1560
  lexer.cmdarg.pop
@@ -1462,7 +1565,7 @@ rule
1462
1565
 
1463
1566
  # TODO: restore cur_arg ? what's cur_arg?
1464
1567
 
1465
- self.lexer.comments # we don't care about comments in the body
1568
+ self.lexer.ignore_body_comments
1466
1569
  }
1467
1570
  | kBREAK
1468
1571
  {
@@ -1499,8 +1602,17 @@ rule
1499
1602
  k_case: kCASE
1500
1603
  k_for: kFOR
1501
1604
  k_class: kCLASS
1605
+ {
1606
+ self.comments.push self.lexer.comments
1607
+ }
1502
1608
  k_module: kMODULE
1609
+ {
1610
+ self.comments.push self.lexer.comments
1611
+ }
1503
1612
  k_def: kDEF
1613
+ {
1614
+ self.comments.push self.lexer.comments
1615
+ }
1504
1616
  k_do: kDO
1505
1617
  k_do_block: kDO_BLOCK
1506
1618
  k_rescue: kRESCUE
@@ -1561,51 +1673,42 @@ rule
1561
1673
 
1562
1674
  result = block_var args
1563
1675
  }
1564
- | f_marg_list tCOMMA tSTAR f_norm_arg
1676
+ | f_marg_list tCOMMA f_rest_marg
1565
1677
  {
1566
- args, _, _, splat = val
1678
+ args, _, rest = val
1567
1679
 
1568
- result = block_var args, "*#{splat}".to_sym
1680
+ result = block_var args, rest
1569
1681
  }
1570
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
1682
+ | f_marg_list tCOMMA f_rest_marg tCOMMA f_marg_list
1571
1683
  {
1572
- args, _, _, splat, _, args2 = val
1684
+ lhs, _, splat, _, rhs = val
1573
1685
 
1574
- result = block_var args, "*#{splat}".to_sym, args2
1686
+ result = block_var lhs, splat, rhs
1575
1687
  }
1576
- | f_marg_list tCOMMA tSTAR
1688
+ | f_rest_marg
1577
1689
  {
1578
- args, _, _ = val
1690
+ rest, = val
1579
1691
 
1580
- result = block_var args, :*
1692
+ result = block_var rest
1581
1693
  }
1582
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
1694
+ | f_rest_marg tCOMMA f_marg_list
1583
1695
  {
1584
- args, _, _, _, args2 = val
1696
+ splat, _, rest = val
1585
1697
 
1586
- result = block_var args, :*, args2
1698
+ result = block_var splat, rest
1587
1699
  }
1588
- | tSTAR f_norm_arg
1589
- {
1590
- _, splat = val
1591
1700
 
1592
- result = block_var :"*#{splat}"
1593
- }
1594
- | tSTAR f_norm_arg tCOMMA f_marg_list
1701
+ f_rest_marg: tSTAR f_norm_arg
1595
1702
  {
1596
- _, splat, _, args = val
1703
+ _, (id, line) = val
1597
1704
 
1598
- result = block_var :"*#{splat}", args
1705
+ result = args ["*#{id}".to_sym]
1706
+ result.line line
1599
1707
  }
1600
1708
  | tSTAR
1601
1709
  {
1602
- result = block_var :*
1603
- }
1604
- | tSTAR tCOMMA f_marg_list
1605
- {
1606
- _, _, args = val
1607
-
1608
- result = block_var :*, args
1710
+ result = args [:*]
1711
+ result.line lexer.lineno # FIX: tSTAR -> line
1609
1712
  }
1610
1713
 
1611
1714
  block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
@@ -1620,10 +1723,16 @@ rule
1620
1723
  {
1621
1724
  result = call_args val
1622
1725
  }
1726
+ #if V >= 27
1727
+ | f_no_kwarg opt_f_block_arg
1728
+ {
1729
+ result = args val
1730
+ }
1731
+ #endif
1623
1732
  | f_block_arg
1624
1733
  {
1625
- line = lexer.lineno
1626
- result = call_args val # TODO: push line down
1734
+ (id, line), = val
1735
+ result = call_args [id]
1627
1736
  result.line line
1628
1737
  }
1629
1738
 
@@ -1732,13 +1841,12 @@ opt_block_args_tail: tCOMMA block_args_tail
1732
1841
 
1733
1842
  bvar: tIDENTIFIER
1734
1843
  {
1735
- id, = val
1736
- line = lexer.lineno
1737
- result = s(:shadow, id.to_sym).line line
1844
+ result = wrap :shadow, val[0]
1738
1845
  }
1739
1846
  | f_bad_arg
1740
1847
 
1741
- lambda: {
1848
+ lambda: tLAMBDA
1849
+ {
1742
1850
  self.env.extend :dynamic
1743
1851
  result = [lexer.lineno, lexer.lpar_beg]
1744
1852
  lexer.paren_nest += 1
@@ -1750,14 +1858,14 @@ opt_block_args_tail: tCOMMA block_args_tail
1750
1858
  }
1751
1859
  lambda_body
1752
1860
  {
1753
- (line, lpar), args, _cmdarg, body = val
1861
+ _, (line, lpar), args, _cmdarg, body = val
1754
1862
  lexer.lpar_beg = lpar
1755
1863
 
1756
1864
  lexer.cmdarg.pop
1757
1865
 
1758
1866
  call = s(:lambda).line line
1759
1867
  result = new_iter call, args, body
1760
- result.line = line
1868
+ result.line line
1761
1869
  self.env.unextend # TODO: dynapush & dynapop
1762
1870
  }
1763
1871
 
@@ -1792,23 +1900,28 @@ opt_block_args_tail: tCOMMA block_args_tail
1792
1900
  ## if (nd_type($1) == NODE_YIELD) {
1793
1901
  ## compile_error(PARSER_ARG "block given to yield");
1794
1902
 
1795
- syntax_error "Both block arg and actual block given." if
1796
- val[0].block_pass?
1903
+ cmd, blk = val
1797
1904
 
1798
- val = invert_block_call val if inverted? val
1905
+ syntax_error "Both block arg and actual block given." if
1906
+ cmd.block_pass?
1799
1907
 
1800
- cmd, blk = val
1908
+ if inverted? val then
1909
+ val = invert_block_call val
1910
+ cmd, blk = val
1911
+ end
1801
1912
 
1802
1913
  result = blk
1803
1914
  result.insert 1, cmd
1804
1915
  }
1805
1916
  | block_call call_op2 operation2 opt_paren_args
1806
1917
  {
1807
- result = new_call val[0], val[2].to_sym, val[3]
1918
+ lhs, _, (id, _line), args = val
1919
+
1920
+ result = new_call lhs, id.to_sym, args
1808
1921
  }
1809
1922
  | block_call call_op2 operation2 opt_paren_args brace_block
1810
1923
  {
1811
- iter1, _, name, args, iter2 = val
1924
+ iter1, _, (name, _line), args, iter2 = val
1812
1925
 
1813
1926
  call = new_call iter1, name.to_sym, args
1814
1927
  iter2.insert 1, call
@@ -1817,7 +1930,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1817
1930
  }
1818
1931
  | block_call call_op2 operation2 command_args do_block
1819
1932
  {
1820
- iter1, _, name, args, iter2 = val
1933
+ iter1, _, (name, _line), args, iter2 = val
1821
1934
 
1822
1935
  call = new_call iter1, name.to_sym, args
1823
1936
  iter2.insert 1, call
@@ -1825,28 +1938,29 @@ opt_block_args_tail: tCOMMA block_args_tail
1825
1938
  result = iter2
1826
1939
  }
1827
1940
 
1828
- method_call: fcall
1941
+ method_call: fcall paren_args
1829
1942
  {
1830
- result = self.lexer.lineno
1831
- }
1832
- paren_args
1833
- {
1834
- call, lineno, args = val
1943
+ call, args = val
1835
1944
 
1836
1945
  result = call.concat args.sexp_body if args
1837
- result.line lineno
1838
1946
  }
1839
1947
  | primary_value call_op operation2 opt_paren_args
1840
1948
  {
1841
- result = new_call val[0], val[2].to_sym, val[3], val[1]
1949
+ recv, call_op, (op, _line), args = val
1950
+
1951
+ result = new_call recv, op.to_sym, args, call_op
1842
1952
  }
1843
1953
  | primary_value tCOLON2 operation2 paren_args
1844
1954
  {
1845
- result = new_call val[0], val[2].to_sym, val[3]
1955
+ recv, _, (op, _line), args = val
1956
+
1957
+ result = new_call recv, op.to_sym, args
1846
1958
  }
1847
1959
  | primary_value tCOLON2 operation3
1848
1960
  {
1849
- result = new_call val[0], val[2].to_sym
1961
+ lhs, _, (id, _line) = val
1962
+
1963
+ result = new_call lhs, id.to_sym
1850
1964
  }
1851
1965
  | primary_value call_op paren_args
1852
1966
  {
@@ -1879,7 +1993,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1879
1993
  _, line, body, _ = val
1880
1994
 
1881
1995
  result = body
1882
- result.line = line
1996
+ result.line line
1883
1997
 
1884
1998
  self.env.unextend
1885
1999
  }
@@ -1893,7 +2007,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1893
2007
  _, line, body, _ = val
1894
2008
 
1895
2009
  result = body
1896
- result.line = line
2010
+ result.line line
1897
2011
 
1898
2012
  self.env.unextend
1899
2013
  }
@@ -1926,18 +2040,551 @@ opt_block_args_tail: tCOMMA block_args_tail
1926
2040
  self.env.unextend
1927
2041
  }
1928
2042
 
2043
+ case_args: arg_value
2044
+ {
2045
+ arg, = val
2046
+
2047
+ result = s(:array, arg).line arg.line
2048
+ }
2049
+ | tSTAR arg_value
2050
+ {
2051
+ _, arg = val
2052
+
2053
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
2054
+ }
2055
+ | case_args tCOMMA arg_value
2056
+ {
2057
+ args, _, id = val
2058
+
2059
+ result = self.list_append args, id
2060
+ }
2061
+ | case_args tCOMMA tSTAR arg_value
2062
+ {
2063
+ args, _, _, id = val
2064
+
2065
+ result = self.list_append args, s(:splat, id).line(id.line)
2066
+ }
2067
+
1929
2068
  case_body: k_when
1930
2069
  {
1931
2070
  result = self.lexer.lineno
1932
2071
  }
1933
- args then compstmt cases
2072
+ case_args then compstmt cases
1934
2073
  {
1935
2074
  result = new_when(val[2], val[4])
1936
- result.line = val[1]
2075
+ result.line val[1]
1937
2076
  result << val[5] if val[5]
1938
2077
  }
1939
2078
 
1940
2079
  cases: opt_else | case_body
2080
+ #if V >= 27
2081
+ ######################################################################
2082
+
2083
+ p_case_body: kIN
2084
+ {
2085
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
2086
+ self.lexer.command_start = false
2087
+ result = self.in_kwarg
2088
+ self.in_kwarg = true
2089
+ push_pvtbl
2090
+ push_pktbl
2091
+ }
2092
+ p_top_expr then
2093
+ {
2094
+ pop_pktbl
2095
+ pop_pvtbl
2096
+ old_kwargs = _values[-3]
2097
+ self.in_kwarg = old_kwargs
2098
+ }
2099
+ compstmt
2100
+ p_cases
2101
+ {
2102
+ (_, line), _, pat, _, _, body, cases = val
2103
+
2104
+ result = new_in pat, body, cases, line
2105
+ }
2106
+
2107
+ p_cases: opt_else
2108
+ | p_case_body
2109
+
2110
+ p_top_expr: p_top_expr_body
2111
+ | p_top_expr_body kIF_MOD expr_value
2112
+ {
2113
+ body, _, cond = val
2114
+ body = remove_begin body
2115
+
2116
+ result = s(:if, cond, body, nil).line body.line
2117
+ }
2118
+ | p_top_expr_body kUNLESS_MOD expr_value
2119
+ {
2120
+ body, _, cond = val
2121
+ body = remove_begin body
2122
+
2123
+ result = s(:if, cond, nil, body).line body.line
2124
+ }
2125
+
2126
+ p_top_expr_body: p_expr
2127
+ | p_expr tCOMMA
2128
+ {
2129
+ expr, _ = val
2130
+
2131
+ tail = new_array_pattern_tail nil, true, nil, nil
2132
+ result = new_array_pattern nil, expr, tail, expr.line
2133
+ }
2134
+ | p_expr tCOMMA p_args
2135
+ {
2136
+ expr, _, args = val
2137
+
2138
+ result = new_array_pattern nil, expr, args, expr.line
2139
+ }
2140
+ | p_args_tail
2141
+ {
2142
+ args, = val
2143
+ result = new_array_pattern nil, nil, args, args.line
2144
+ }
2145
+ | p_kwargs
2146
+ {
2147
+ kwargs, = val
2148
+ result = new_hash_pattern nil, kwargs, kwargs.line
2149
+ }
2150
+
2151
+ p_expr: p_as
2152
+
2153
+ p_as: p_expr tASSOC p_variable
2154
+ {
2155
+ # NODE *n = NEW_LIST($1, &@$);
2156
+ # n = list_append(p, n, $3);
2157
+ # $$ = new_hash(p, n, &@$);
2158
+
2159
+ expr, _, var = val
2160
+
2161
+ id = var.last
2162
+
2163
+ self.env[id] = :lvar # HACK: need to extend env
2164
+ lhs = s(:lasgn, id).line var.line
2165
+
2166
+ result = new_assign lhs, expr
2167
+ }
2168
+ | p_alt
2169
+
2170
+ p_alt: p_alt tPIPE p_expr_basic
2171
+ {
2172
+ lhs, _, rhs = val
2173
+
2174
+ result = s(:or, lhs, rhs).line lhs.line
2175
+ }
2176
+ | p_expr_basic
2177
+
2178
+ p_lparen: tLPAREN2 { push_pktbl }
2179
+ p_lbracket: tLBRACK2 { push_pktbl }
2180
+
2181
+ p_expr_basic: p_value
2182
+ | p_const p_lparen p_args tRPAREN
2183
+ {
2184
+ lhs, _, args, _ = val
2185
+
2186
+ pop_pktbl
2187
+ result = new_array_pattern(lhs, nil, args, lhs.line)
2188
+ }
2189
+ | p_const p_lparen p_kwargs tRPAREN
2190
+ {
2191
+ lhs, _, kwargs, _ = val
2192
+
2193
+ pop_pktbl
2194
+ result = new_hash_pattern(lhs, kwargs, lhs.line)
2195
+ }
2196
+ | p_const tLPAREN2 tRPAREN
2197
+ {
2198
+ const, _, _ = val
2199
+
2200
+ tail = new_array_pattern_tail nil, nil, nil, nil
2201
+ result = new_array_pattern const, nil, tail, const.line
2202
+ }
2203
+ | p_const p_lbracket p_args rbracket
2204
+ {
2205
+ const, _, pre_arg, _ = val
2206
+
2207
+ pop_pktbl
2208
+ result = new_array_pattern const, nil, pre_arg, const.line
2209
+ }
2210
+ | p_const p_lbracket p_kwargs rbracket
2211
+ {
2212
+ const, _, kwargs, _ = val
2213
+
2214
+ result = new_hash_pattern const, kwargs, const.line
2215
+ }
2216
+ | p_const tLBRACK2 rbracket
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
+ | tLBRACK { push_pktbl } p_args rbracket
2224
+ {
2225
+ _, _, pat, _ = val
2226
+
2227
+ pop_pktbl
2228
+ result = new_array_pattern nil, nil, pat, pat.line
2229
+ }
2230
+ | tLBRACK rbracket
2231
+ {
2232
+ (_, line), _ = val
2233
+
2234
+ result = s(:array_pat).line line
2235
+ }
2236
+ | tLBRACE
2237
+ {
2238
+ push_pktbl
2239
+ result = self.in_kwarg
2240
+ self.in_kwarg = false
2241
+ }
2242
+ p_kwargs rbrace
2243
+ {
2244
+ _, in_kwarg, kwargs, _ = val
2245
+
2246
+ pop_pktbl
2247
+ self.in_kwarg = in_kwarg
2248
+
2249
+ result = new_hash_pattern(nil, kwargs, kwargs.line)
2250
+ }
2251
+ | tLBRACE rbrace
2252
+ {
2253
+ (_, line), _ = val
2254
+
2255
+ tail = new_hash_pattern_tail nil, nil, line
2256
+ result = new_hash_pattern nil, tail, line
2257
+ }
2258
+ | tLPAREN { push_pktbl } p_expr tRPAREN
2259
+ {
2260
+ _, _, expr, _ = val
2261
+
2262
+ pop_pktbl
2263
+ result = expr
2264
+ }
2265
+
2266
+ p_args: p_expr
2267
+ {
2268
+ expr, = val
2269
+
2270
+ ary = s(:array_TAIL, expr).line expr.line
2271
+ result = new_array_pattern_tail(ary, nil, nil, nil).line expr.line
2272
+ }
2273
+ | p_args_head
2274
+ {
2275
+ head, = val
2276
+
2277
+ result = new_array_pattern_tail head, true, nil, nil
2278
+ }
2279
+ | p_args_head p_arg
2280
+ {
2281
+ head, tail = val
2282
+
2283
+ both = array_pat_concat head, tail
2284
+
2285
+ result = new_array_pattern_tail both, nil, nil, nil
2286
+ result.line head.line
2287
+ }
2288
+ | p_args_head tSTAR tIDENTIFIER
2289
+ {
2290
+ head, _, (id, _line) = val
2291
+
2292
+ result = new_array_pattern_tail head, true, id.to_sym, nil
2293
+ result.line head.line
2294
+ }
2295
+ | p_args_head tSTAR tIDENTIFIER tCOMMA p_args_post
2296
+ {
2297
+ head, _, (id, _line), _, post = val
2298
+
2299
+ result = new_array_pattern_tail head, true, id.to_sym, post
2300
+ result.line head.line
2301
+ }
2302
+ | p_args_head tSTAR
2303
+ {
2304
+ expr, _ = val
2305
+
2306
+ result = new_array_pattern_tail(expr, true, nil, nil).line expr.line
2307
+ }
2308
+ | p_args_head tSTAR tCOMMA p_args_post
2309
+ {
2310
+ head, _, _, post = val
2311
+
2312
+ result = new_array_pattern_tail(head, true, nil, post).line head.line
2313
+ }
2314
+ | p_args_tail
2315
+
2316
+ p_args_head: p_arg tCOMMA
2317
+ {
2318
+ arg, _ = val
2319
+ result = arg
2320
+ }
2321
+ | p_args_head p_arg tCOMMA
2322
+ {
2323
+ head, tail, _ = val
2324
+
2325
+ result = s(:PATTERN, *head.sexp_body, *tail.sexp_body)
2326
+ result.line head.line
2327
+ }
2328
+
2329
+ p_args_tail: tSTAR tIDENTIFIER
2330
+ {
2331
+ _, (id, line) = val
2332
+
2333
+ result = new_array_pattern_tail nil, true, id.to_sym, nil
2334
+ result.line line
2335
+ }
2336
+ | tSTAR tIDENTIFIER tCOMMA p_args_post
2337
+ {
2338
+ _, (id, line), _, rhs = val
2339
+
2340
+ result = new_array_pattern_tail nil, true, id.to_sym, rhs
2341
+ result.line line
2342
+ }
2343
+ | tSTAR
2344
+ {
2345
+ (_, line), = val
2346
+
2347
+ result = new_array_pattern_tail nil, true, nil, nil
2348
+ result.line line
2349
+ }
2350
+ | tSTAR tCOMMA p_args_post
2351
+ {
2352
+ (_, line), _, args = val
2353
+
2354
+ result = new_array_pattern_tail nil, true, nil, args
2355
+ result.line line
2356
+ }
2357
+
2358
+ p_args_post: p_arg
2359
+ | p_args_post tCOMMA p_arg
2360
+ {
2361
+ lhs, _, rhs = val
2362
+
2363
+ result = array_pat_concat lhs, rhs
2364
+ }
2365
+
2366
+ p_arg: p_expr
2367
+ {
2368
+ expr, = val
2369
+ expr = s(:array_TAIL, expr).line expr.line unless
2370
+ expr.sexp_type == :array_TAIL
2371
+ result = expr
2372
+ }
2373
+
2374
+ p_kwargs: p_kwarg tCOMMA p_kwrest
2375
+ {
2376
+ kw_arg, _, rest = val
2377
+ # TODO? new_unique_key_hash(p, $1, &@$)
2378
+ result = new_hash_pattern_tail kw_arg, rest, kw_arg.line
2379
+ }
2380
+ | p_kwarg
2381
+ {
2382
+ kwarg, = val
2383
+ # TODO? new_unique_key_hash(p, $1, &@$)
2384
+ result = new_hash_pattern_tail kwarg, nil, kwarg.line
2385
+ }
2386
+ | p_kwarg tCOMMA
2387
+ {
2388
+ kwarg, _ = val
2389
+ # TODO? new_unique_key_hash(p, $1, &@$)
2390
+ result = new_hash_pattern_tail kwarg, nil, kwarg.line
2391
+ }
2392
+ | p_kwrest
2393
+ {
2394
+ rest, = val
2395
+
2396
+ result = new_hash_pattern_tail nil, rest, rest.line
2397
+ }
2398
+ | p_kwarg tCOMMA p_kwnorest
2399
+ {
2400
+ kwarg, _, norest = val
2401
+
2402
+ # TODO? new_unique_key_hash(p, $1, &@$)
2403
+ result = new_hash_pattern_tail kwarg, norest, kwarg.line
2404
+ }
2405
+ | p_kwnorest
2406
+ {
2407
+ norest, = val
2408
+
2409
+ result = new_hash_pattern_tail nil, norest, norest.line
2410
+ }
2411
+
2412
+ p_kwarg: p_kw # TODO? rb_ary_new_from_args(1, $1)
2413
+ | p_kwarg tCOMMA p_kw
2414
+ {
2415
+ kwarg, _, kw = val
2416
+ kwarg.concat kw.sexp_body
2417
+ result = kwarg
2418
+ }
2419
+
2420
+ p_kw: p_kw_label p_expr
2421
+ {
2422
+ # TODO: error_duplicate_pattern_key(p, get_id($1), &@1);
2423
+ lhs, rhs = val
2424
+
2425
+ result = s(:PAIR, lhs, rhs).line lhs.line
2426
+ }
2427
+ | p_kw_label
2428
+ {
2429
+ lhs, = val
2430
+
2431
+ # TODO: error_duplicate_pattern_variable(p, get_id($1), &@1);
2432
+
2433
+ # TODO: if ($1 && !is_local_id(get_id($1))) {
2434
+ # yyerror1(&@1, "key must be valid as local variables");
2435
+ # }
2436
+
2437
+ # $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@$), &@$),
2438
+ # assignable(p, $1, 0, &@$));
2439
+
2440
+
2441
+ case lhs.sexp_type
2442
+ when :lit then
2443
+ assignable [lhs.value, lhs.line]
2444
+ else
2445
+ # TODO or done?
2446
+ debug 666
2447
+ end
2448
+
2449
+ # TODO PAIR -> LIST ?
2450
+ result = s(:PAIR, lhs, nil).line lhs.line
2451
+ }
2452
+
2453
+ p_kw_label: tLABEL
2454
+ {
2455
+ result = wrap :lit, val[0]
2456
+ }
2457
+
2458
+ p_kwrest: kwrest_mark tIDENTIFIER
2459
+ {
2460
+ _, (id, line) = val
2461
+
2462
+ name = id.to_sym
2463
+ self.assignable [name, line]
2464
+ result = s(:kwrest, :"**#{name}").line line
2465
+ }
2466
+ | kwrest_mark
2467
+ {
2468
+ (_, line), = val
2469
+
2470
+ result = s(:kwrest, :"**").line line
2471
+ }
2472
+
2473
+ p_kwnorest: kwrest_mark kNIL
2474
+ {
2475
+ (_, line), _ = val
2476
+
2477
+ # TODO: or s(:norest)? s(:**nil)?
2478
+ result = s(:kwrest, :"**nil").line line
2479
+ }
2480
+
2481
+ p_value: p_primitive
2482
+ | p_primitive tDOT2 p_primitive
2483
+ {
2484
+ lhs, _, rhs = val
2485
+
2486
+ lhs = value_expr lhs
2487
+ rhs = value_expr rhs
2488
+
2489
+ result = s(:dot2, lhs, rhs).line lhs.line
2490
+ }
2491
+ | p_primitive tDOT3 p_primitive
2492
+ {
2493
+ lhs, _, rhs = val
2494
+
2495
+ lhs = value_expr lhs
2496
+ rhs = value_expr rhs
2497
+
2498
+ result = s(:dot3, lhs, rhs).line lhs.line
2499
+ }
2500
+ | p_primitive tDOT2
2501
+ {
2502
+ v1, _ = val
2503
+
2504
+ result = s(:dot2, v1, nil).line v1.line
2505
+ }
2506
+ | p_primitive tDOT3
2507
+ {
2508
+ v1, _ = val
2509
+
2510
+ result = s(:dot3, v1, nil).line v1.line
2511
+ }
2512
+ | p_variable
2513
+ | p_var_ref
2514
+ | p_const
2515
+ | tBDOT2 p_primitive
2516
+ {
2517
+ _, v1 = val
2518
+
2519
+ result = s(:dot2, nil, v1).line v1.line
2520
+ }
2521
+ | tBDOT3 p_primitive
2522
+ {
2523
+ _, v1 = val
2524
+
2525
+ result = s(:dot3, nil, v1).line v1.line
2526
+ }
2527
+
2528
+ p_primitive: literal
2529
+ | strings
2530
+ | xstring
2531
+ | regexp
2532
+ | words
2533
+ {
2534
+ result = ary_to_pat val[0]
2535
+ }
2536
+ | qwords
2537
+ {
2538
+ result = ary_to_pat val[0]
2539
+ }
2540
+ | symbols
2541
+ {
2542
+ result = ary_to_pat val[0]
2543
+ }
2544
+ | qsymbols
2545
+ {
2546
+ result = ary_to_pat val[0]
2547
+ }
2548
+ | keyword_variable
2549
+ {
2550
+ # TODO? if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$);
2551
+ var, = val
2552
+
2553
+ result = var
2554
+ }
2555
+ | lambda
2556
+
2557
+ p_variable: tIDENTIFIER
2558
+ {
2559
+ # TODO: error_duplicate_pattern_variable(p, $1, &@1);
2560
+ # TODO: assignable(p, $1, 0, &@$);
2561
+ result = wrap :lasgn, val[0]
2562
+ }
2563
+
2564
+ p_var_ref: tCARET tIDENTIFIER
2565
+ {
2566
+ # TODO: check id against env for lvar or dvar
2567
+ result = wrap :lvar, val[1]
2568
+ }
2569
+
2570
+ p_const: tCOLON3 cname
2571
+ {
2572
+ result = wrap :colon3, val[1]
2573
+ }
2574
+ | p_const tCOLON2 cname
2575
+ {
2576
+ lhs, _, (id, _line) = val
2577
+
2578
+ l = lhs.line
2579
+ result = s(:const, s(:colon2, lhs, id.to_sym).line(l)).line l
2580
+ }
2581
+ | tCONSTANT
2582
+ {
2583
+ # TODO $$ = gettable(p, $1, &@$);
2584
+ result = wrap :const, val[0]
2585
+ }
2586
+ ######################################################################
2587
+ #endif
1941
2588
 
1942
2589
  opt_rescue: k_rescue exc_list exc_var then compstmt opt_rescue
1943
2590
  {
@@ -1979,17 +2626,10 @@ opt_block_args_tail: tCOMMA block_args_tail
1979
2626
 
1980
2627
  literal: numeric
1981
2628
  {
1982
- line = lexer.lineno
1983
- result = s(:lit, val[0])
1984
- result.line = line
2629
+ (lit, line), = val
2630
+ result = s(:lit, lit).line line
1985
2631
  }
1986
2632
  | symbol
1987
- {
1988
- line = lexer.lineno
1989
- result = s(:lit, val[0])
1990
- result.line = line
1991
- }
1992
- | dsym
1993
2633
 
1994
2634
  strings: string
1995
2635
  {
@@ -2000,7 +2640,7 @@ opt_block_args_tail: tCOMMA block_args_tail
2000
2640
 
2001
2641
  string: tCHAR
2002
2642
  {
2003
- debug20 23, val, result
2643
+ debug 37
2004
2644
  }
2005
2645
  | string1
2006
2646
  | string string1
@@ -2010,11 +2650,11 @@ opt_block_args_tail: tCOMMA block_args_tail
2010
2650
 
2011
2651
  string1: tSTRING_BEG string_contents tSTRING_END
2012
2652
  {
2013
- _, str, (_, func) = val
2653
+ (_, line), str, (_, func) = val
2014
2654
 
2015
- str = dedent str if func =~ RubyLexer::STR_FUNC_ICNTNT
2655
+ str = dedent str if func =~ RubyLexer::STR_FUNC_DEDENT
2016
2656
 
2017
- result = str
2657
+ result = str.line line
2018
2658
  }
2019
2659
  | tSTRING
2020
2660
  {
@@ -2034,11 +2674,15 @@ opt_block_args_tail: tCOMMA block_args_tail
2034
2674
 
2035
2675
  words: tWORDS_BEG tSPACE tSTRING_END
2036
2676
  {
2037
- result = s(:array).line lexer.lineno
2677
+ (_, line), _, _ = val
2678
+
2679
+ result = s(:array).line line
2038
2680
  }
2039
2681
  | tWORDS_BEG word_list tSTRING_END
2040
2682
  {
2041
- result = val[1]
2683
+ (_, line), list, _ = val
2684
+
2685
+ result = list.line line
2042
2686
  }
2043
2687
 
2044
2688
  word_list: none
@@ -2058,18 +2702,20 @@ opt_block_args_tail: tCOMMA block_args_tail
2058
2702
 
2059
2703
  symbols: tSYMBOLS_BEG tSPACE tSTRING_END
2060
2704
  {
2061
- result = s(:array).line lexer.lineno
2705
+ (_, line), _, _ = val
2706
+
2707
+ result = s(:array).line line
2062
2708
  }
2063
- | tSYMBOLS_BEG { result = lexer.lineno } symbol_list tSTRING_END
2709
+ | tSYMBOLS_BEG symbol_list tSTRING_END
2064
2710
  {
2065
- _, line, list, _, = val
2066
- list.line = line
2711
+ (_, line), list, _, = val
2712
+ list.line line
2067
2713
  result = list
2068
2714
  }
2069
2715
 
2070
2716
  symbol_list: none
2071
2717
  {
2072
- result = new_symbol_list.line lexer.lineno
2718
+ result = new_symbol_list
2073
2719
  }
2074
2720
  | symbol_list word tSPACE
2075
2721
  {
@@ -2079,20 +2725,28 @@ opt_block_args_tail: tCOMMA block_args_tail
2079
2725
 
2080
2726
  qwords: tQWORDS_BEG tSPACE tSTRING_END
2081
2727
  {
2082
- result = s(:array).line lexer.lineno
2728
+ (_, line), _, _ = val
2729
+
2730
+ result = s(:array).line line
2083
2731
  }
2084
2732
  | tQWORDS_BEG qword_list tSTRING_END
2085
2733
  {
2086
- result = val[1]
2734
+ (_, line), list, _ = val
2735
+
2736
+ result = list.line line
2087
2737
  }
2088
2738
 
2089
2739
  qsymbols: tQSYMBOLS_BEG tSPACE tSTRING_END
2090
2740
  {
2091
- result = s(:array).line lexer.lineno # FIX
2741
+ (_, line), _, _ = val
2742
+
2743
+ result = s(:array).line line
2092
2744
  }
2093
2745
  | tQSYMBOLS_BEG qsym_list tSTRING_END
2094
2746
  {
2095
- result = val[1]
2747
+ (_, line), list, _ = val
2748
+
2749
+ result = list.line line
2096
2750
  }
2097
2751
 
2098
2752
  qword_list: none
@@ -2115,7 +2769,8 @@ opt_block_args_tail: tCOMMA block_args_tail
2115
2769
 
2116
2770
  string_contents: none
2117
2771
  {
2118
- result = s(:str, "").line lexer.lineno
2772
+ line = prev_value_to_lineno _values.last
2773
+ result = s(:str, +"").line line
2119
2774
  }
2120
2775
  | string_contents string_content
2121
2776
  {
@@ -2190,8 +2845,8 @@ regexp_contents: none
2190
2845
  lexer.brace_nest = brace_nest
2191
2846
  lexer.string_nest = string_nest
2192
2847
 
2193
- lexer.cmdarg.pop
2194
2848
  lexer.cond.pop
2849
+ lexer.cmdarg.pop
2195
2850
 
2196
2851
  lexer.lex_state = oldlex_state
2197
2852
 
@@ -2206,29 +2861,42 @@ regexp_contents: none
2206
2861
  when nil then
2207
2862
  result = s(:evstr).line line
2208
2863
  else
2209
- debug20 25
2864
+ debug 38
2210
2865
  raise "unknown string body: #{stmt.inspect}"
2211
2866
  end
2212
2867
  }
2213
2868
 
2214
- string_dvar: tGVAR { result = s(:gvar, val[0].to_sym).line lexer.lineno }
2215
- | tIVAR { result = s(:ivar, val[0].to_sym).line lexer.lineno }
2216
- | tCVAR { result = s(:cvar, val[0].to_sym).line lexer.lineno }
2869
+ string_dvar: tGVAR
2870
+ {
2871
+ result = wrap :gvar, val[0]
2872
+ }
2873
+ | tIVAR
2874
+ {
2875
+ result = wrap :ivar, val[0]
2876
+ }
2877
+ | tCVAR
2878
+ {
2879
+ result = wrap :cvar, val[0]
2880
+ }
2217
2881
  | backref
2218
2882
 
2219
- symbol: tSYMBEG sym
2883
+ symbol: ssym
2884
+ | dsym
2885
+
2886
+ ssym: tSYMBEG sym
2220
2887
  {
2221
2888
  lexer.lex_state = EXPR_END
2222
- result = val[1].to_sym
2889
+ result = wrap :lit, val[1]
2223
2890
  }
2224
2891
  | tSYMBOL
2225
2892
  {
2226
- result = val[0].to_sym
2893
+ lexer.lex_state = EXPR_END
2894
+ result = wrap :lit, val[0]
2227
2895
  }
2228
2896
 
2229
2897
  sym: fname | tIVAR | tGVAR | tCVAR
2230
2898
 
2231
- dsym: tSYMBEG xstring_contents tSTRING_END
2899
+ dsym: tSYMBEG string_contents tSTRING_END
2232
2900
  {
2233
2901
  _, result, _ = val
2234
2902
 
@@ -2244,7 +2912,7 @@ regexp_contents: none
2244
2912
  when :evstr then
2245
2913
  result = s(:dsym, "", result).line result.line
2246
2914
  else
2247
- debug20 26, val, result
2915
+ debug 39
2248
2916
  end
2249
2917
  }
2250
2918
 
@@ -2254,15 +2922,17 @@ regexp_contents: none
2254
2922
  | tUMINUS_NUM tINTEGER =tLOWEST
2255
2923
  #else
2256
2924
  numeric: simple_numeric
2257
- | tUMINUS_NUM simple_numeric
2925
+ | tUMINUS_NUM simple_numeric =tLOWEST
2258
2926
  #endif
2259
2927
  {
2260
- result = -val[1] # TODO: pt_testcase
2928
+ _, (num, line) = val
2929
+ result = [-num, line]
2261
2930
  #if V == 20
2262
2931
  }
2263
2932
  | tUMINUS_NUM tFLOAT =tLOWEST
2264
2933
  {
2265
- result = -val[1] # TODO: pt_testcase
2934
+ _, (num, line) = val
2935
+ result = [-num, line]
2266
2936
  #endif
2267
2937
  }
2268
2938
 
@@ -2298,8 +2968,10 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2298
2968
 
2299
2969
  var_ref: user_variable
2300
2970
  {
2301
- var = val[0]
2971
+ raise "NO: #{val.inspect}" if Sexp === val.first
2972
+ (var, line), = val
2302
2973
  result = Sexp === var ? var : self.gettable(var)
2974
+ result.line line
2303
2975
  }
2304
2976
  | keyword_variable
2305
2977
  {
@@ -2314,11 +2986,19 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2314
2986
  | keyword_variable
2315
2987
  {
2316
2988
  result = self.assignable val[0]
2317
- debug20 29, val, result
2989
+ debug 40
2318
2990
  }
2319
2991
 
2320
- backref: tNTH_REF { result = s(:nth_ref, val[0]).line lexer.lineno }
2321
- | tBACK_REF { result = s(:back_ref, val[0]).line lexer.lineno }
2992
+ backref: tNTH_REF
2993
+ {
2994
+ (ref, line), = val
2995
+ result = s(:nth_ref, ref).line line
2996
+ }
2997
+ | tBACK_REF
2998
+ {
2999
+ (ref, line), = val
3000
+ result = s(:back_ref, ref).line line
3001
+ }
2322
3002
 
2323
3003
  superclass: tLT
2324
3004
  {
@@ -2336,10 +3016,18 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2336
3016
 
2337
3017
  f_arglist: tLPAREN2 f_args rparen
2338
3018
  {
2339
- result = val[1]
2340
- self.lexer.lex_state = EXPR_BEG
2341
- self.lexer.command_start = true
3019
+ result = end_args val
3020
+ }
3021
+ #if V == 27
3022
+ | tLPAREN2 f_arg tCOMMA args_forward rparen
3023
+ {
3024
+ result = end_args val
3025
+ }
3026
+ | tLPAREN2 args_forward rparen
3027
+ {
3028
+ result = end_args val
2342
3029
  }
3030
+ #endif
2343
3031
  | {
2344
3032
  result = self.in_kwarg
2345
3033
  self.in_kwarg = true
@@ -2347,12 +3035,7 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2347
3035
  }
2348
3036
  f_args term
2349
3037
  {
2350
- kwarg, args, _ = val
2351
-
2352
- self.in_kwarg = kwarg
2353
- result = args
2354
- lexer.lex_state = EXPR_BEG
2355
- lexer.command_start = true
3038
+ result = end_args val
2356
3039
  }
2357
3040
 
2358
3041
  args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
@@ -2367,6 +3050,12 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2367
3050
  {
2368
3051
  result = args val
2369
3052
  }
3053
+ #if V >= 27
3054
+ | f_no_kwarg opt_f_block_arg
3055
+ {
3056
+ result = args val
3057
+ }
3058
+ #endif
2370
3059
  | f_block_arg
2371
3060
 
2372
3061
  opt_args_tail: tCOMMA args_tail
@@ -2437,7 +3126,15 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2437
3126
  |
2438
3127
  {
2439
3128
  result = args val
3129
+ # result.line lexer.lineno
3130
+ }
3131
+
3132
+ #if V >= 27
3133
+ args_forward: tBDOT3
3134
+ {
3135
+ result = s(:forward_args).line lexer.lineno
2440
3136
  }
3137
+ #endif
2441
3138
 
2442
3139
  f_bad_arg: tCONSTANT
2443
3140
  {
@@ -2459,10 +3156,11 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2459
3156
  f_norm_arg: f_bad_arg
2460
3157
  | tIDENTIFIER
2461
3158
  {
2462
- identifier = val[0].to_sym
3159
+ (id, line), = val
3160
+ identifier = id.to_sym
2463
3161
  self.env[identifier] = :lvar
2464
3162
 
2465
- result = identifier
3163
+ result = [identifier, line]
2466
3164
  }
2467
3165
 
2468
3166
  #if V >= 22
@@ -2471,29 +3169,23 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2471
3169
  f_arg_item: f_arg_asgn
2472
3170
  | tLPAREN f_margs rparen
2473
3171
  {
2474
- result = val[1]
3172
+ _, margs, _ = val
3173
+
3174
+ result = margs
2475
3175
  }
2476
3176
  #else
2477
3177
  f_arg_item: f_norm_arg
2478
3178
  | tLPAREN f_margs rparen
2479
3179
  {
2480
- result = val[1]
3180
+ _, margs, _ = val
3181
+
3182
+ result = margs
2481
3183
  }
2482
3184
  #endif
2483
3185
 
2484
3186
  f_arg: f_arg_item
2485
3187
  {
2486
- arg, = val
2487
-
2488
- case arg
2489
- when Symbol then
2490
- result = s(:args, arg).line lexer.lineno
2491
- when Sexp then
2492
- result = arg
2493
- else
2494
- debug20 32
2495
- raise "Unknown f_arg type: #{val.inspect}"
2496
- end
3188
+ result = new_arg val
2497
3189
  }
2498
3190
  | f_arg tCOMMA f_arg_item
2499
3191
  {
@@ -2505,7 +3197,7 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2505
3197
  result = s(:args, list).line list.line
2506
3198
  end
2507
3199
 
2508
- result << item
3200
+ result << (Sexp === item ? item : item.first)
2509
3201
  }
2510
3202
 
2511
3203
  #if V == 20
@@ -2578,15 +3270,26 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2578
3270
  kwrest_mark: tPOW
2579
3271
  | tDSTAR
2580
3272
 
3273
+ #if V >= 27
3274
+ f_no_kwarg: kwrest_mark kNIL
3275
+ {
3276
+ result = :"**nil"
3277
+ }
3278
+ #endif
3279
+
2581
3280
  f_kwrest: kwrest_mark tIDENTIFIER
2582
3281
  {
2583
- name = val[1].to_sym
2584
- self.assignable name
2585
- result = :"**#{name}"
3282
+ _, (id, line) = val
3283
+
3284
+ name = id.to_sym
3285
+ self.assignable [name, line]
3286
+ result = [:"**#{name}", line]
2586
3287
  }
2587
3288
  | kwrest_mark
2588
3289
  {
2589
- result = :"**"
3290
+ id = :"**"
3291
+ self.env[id] = :lvar # TODO: needed?!?
3292
+ result = [id, lexer.lineno] # TODO: tPOW/tDSTAR include lineno
2590
3293
  }
2591
3294
 
2592
3295
  #if V == 20
@@ -2597,7 +3300,8 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2597
3300
  f_opt: f_arg_asgn tEQL arg_value
2598
3301
  #endif
2599
3302
  {
2600
- result = self.assignable val[0], val[2]
3303
+ lhs, _, rhs = val
3304
+ result = self.assignable lhs, rhs
2601
3305
  # TODO: detect duplicate names
2602
3306
  }
2603
3307
 
@@ -2609,7 +3313,8 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2609
3313
  f_block_opt: f_arg_asgn tEQL primary_value
2610
3314
  #endif
2611
3315
  {
2612
- result = self.assignable val[0], val[2]
3316
+ lhs, _, rhs = val
3317
+ result = self.assignable lhs, rhs
2613
3318
  }
2614
3319
 
2615
3320
  f_block_optarg: f_block_opt
@@ -2639,30 +3344,33 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2639
3344
  f_rest_arg: restarg_mark tIDENTIFIER
2640
3345
  {
2641
3346
  # TODO: differs from parse.y - needs tests
2642
- name = val[1].to_sym
2643
- self.assignable name
2644
- result = :"*#{name}"
3347
+ _, (id, line) = val
3348
+ name = id.to_sym
3349
+ self.assignable [name, line]
3350
+ result = [:"*#{name}", line]
2645
3351
  }
2646
3352
  | restarg_mark
2647
3353
  {
2648
3354
  name = :"*"
2649
3355
  self.env[name] = :lvar
2650
- result = name
3356
+ result = [name, lexer.lineno] # FIX: tSTAR to include lineno
2651
3357
  }
2652
3358
 
2653
3359
  blkarg_mark: tAMPER2 | tAMPER
2654
3360
 
2655
3361
  f_block_arg: blkarg_mark tIDENTIFIER
2656
3362
  {
2657
- identifier = val[1].to_sym
3363
+ _, (id, line) = val
3364
+ identifier = id.to_sym
2658
3365
 
2659
3366
  self.env[identifier] = :lvar
2660
- result = "&#{identifier}".to_sym
3367
+ result = ["&#{identifier}".to_sym, line]
2661
3368
  }
2662
3369
 
2663
3370
  opt_f_block_arg: tCOMMA f_block_arg
2664
3371
  {
2665
- result = val[1]
3372
+ _, arg = val
3373
+ result = arg
2666
3374
  }
2667
3375
  |
2668
3376
  {
@@ -2704,17 +3412,19 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2704
3412
  }
2705
3413
  | tLABEL arg_value
2706
3414
  {
2707
- (label, line), arg = val
3415
+ label, arg = val
2708
3416
 
2709
- lit = s(:lit, label.to_sym).line line
2710
- result = s(:array, lit, arg).line line
3417
+ lit = wrap :lit, label
3418
+ result = s(:array, lit, arg).line lit.line
2711
3419
  }
2712
3420
  #if V >= 22
2713
3421
  | tSTRING_BEG string_contents tLABEL_END arg_value
2714
3422
  {
2715
- _, sym, _, value = val
3423
+ (_, line), sym, _, value = val
3424
+
2716
3425
  sym.sexp_type = :dsym
2717
- result = s(:array, sym, value).line sym.line
3426
+
3427
+ result = s(:array, sym, value).line line
2718
3428
  }
2719
3429
  #endif
2720
3430
  | tDSTAR arg_value
@@ -2740,6 +3450,9 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2740
3450
  opt_nl: | tNL
2741
3451
  rparen: opt_nl tRPAREN
2742
3452
  rbracket: opt_nl tRBRACK
3453
+ #if V >= 27
3454
+ rbrace: opt_nl tRCURLY
3455
+ #endif
2743
3456
  trailer: | tNL | tCOMMA
2744
3457
 
2745
3458
  term: tSEMI { yyerrok }