ruby_parser 3.17.0 → 3.19.0

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 (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/History.rdoc +109 -0
  4. data/Manifest.txt +5 -0
  5. data/README.rdoc +9 -6
  6. data/Rakefile +85 -24
  7. data/bin/ruby_parse_extract_error +1 -1
  8. data/compare/normalize.rb +6 -1
  9. data/gauntlet.md +108 -0
  10. data/lib/rp_extensions.rb +15 -36
  11. data/lib/rp_stringscanner.rb +20 -51
  12. data/lib/ruby20_parser.rb +7430 -3528
  13. data/lib/ruby20_parser.y +328 -257
  14. data/lib/ruby21_parser.rb +7408 -3572
  15. data/lib/ruby21_parser.y +323 -254
  16. data/lib/ruby22_parser.rb +7543 -3601
  17. data/lib/ruby22_parser.y +327 -256
  18. data/lib/ruby23_parser.rb +7549 -3612
  19. data/lib/ruby23_parser.y +327 -256
  20. data/lib/ruby24_parser.rb +7640 -3624
  21. data/lib/ruby24_parser.y +327 -256
  22. data/lib/ruby25_parser.rb +7640 -3623
  23. data/lib/ruby25_parser.y +327 -256
  24. data/lib/ruby26_parser.rb +7649 -3632
  25. data/lib/ruby26_parser.y +326 -255
  26. data/lib/ruby27_parser.rb +10132 -4545
  27. data/lib/ruby27_parser.y +871 -262
  28. data/lib/ruby30_parser.rb +10504 -4655
  29. data/lib/ruby30_parser.y +1065 -333
  30. data/lib/ruby31_parser.rb +13622 -0
  31. data/lib/ruby31_parser.y +3481 -0
  32. data/lib/ruby3_parser.yy +3536 -0
  33. data/lib/ruby_lexer.rb +261 -609
  34. data/lib/ruby_lexer.rex +27 -20
  35. data/lib/ruby_lexer.rex.rb +59 -23
  36. data/lib/ruby_lexer_strings.rb +638 -0
  37. data/lib/ruby_parser.rb +2 -0
  38. data/lib/ruby_parser.yy +903 -272
  39. data/lib/ruby_parser_extras.rb +333 -113
  40. data/test/test_ruby_lexer.rb +181 -129
  41. data/test/test_ruby_parser.rb +1529 -288
  42. data/tools/munge.rb +34 -6
  43. data/tools/ripper.rb +15 -10
  44. data.tar.gz.sig +0 -0
  45. metadata +27 -23
  46. metadata.gz.sig +0 -0
data/lib/ruby20_parser.y CHANGED
@@ -18,7 +18,7 @@ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
18
18
  tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
19
19
  tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
20
20
  tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA
21
- tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND tUBANG
21
+ tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND
22
22
 
23
23
  preclow
24
24
  nonassoc tLOWEST
@@ -76,7 +76,7 @@ rule
76
76
  | klBEGIN
77
77
  {
78
78
  if (self.in_def || self.in_single > 0) then
79
- debug20 1
79
+ debug 11
80
80
  yyerror "BEGIN in method"
81
81
  end
82
82
  self.env.extend
@@ -101,7 +101,9 @@ rule
101
101
  bodystmt: compstmt opt_rescue k_else
102
102
  {
103
103
  res = _values[-2]
104
- yyerror "else without rescue is useless" unless res
104
+ # TODO: move down to main match so I can just use val
105
+
106
+ warn "else without rescue is useless" unless res
105
107
  }
106
108
  compstmt
107
109
  opt_ensure
@@ -131,7 +133,7 @@ rule
131
133
  | error stmt
132
134
  {
133
135
  result = val[1]
134
- debug20 2, val, result
136
+ debug 12
135
137
  }
136
138
 
137
139
  stmt_or_begin: stmt
@@ -139,6 +141,10 @@ rule
139
141
  {
140
142
  yyerror "BEGIN is permitted only at toplevel"
141
143
  }
144
+ begin_block
145
+ {
146
+ result = val[2] # wtf?
147
+ }
142
148
 
143
149
  stmt: kALIAS fitem
144
150
  {
@@ -151,12 +157,12 @@ rule
151
157
  }
152
158
  | kALIAS tGVAR tGVAR
153
159
  {
154
- (_, line), lhs, rhs = val
160
+ (_, line), (lhs, _), (rhs, _) = val
155
161
  result = s(:valias, lhs.to_sym, rhs.to_sym).line line
156
162
  }
157
163
  | kALIAS tGVAR tBACK_REF
158
164
  {
159
- (_, line), lhs, rhs = val
165
+ (_, line), (lhs, _), (rhs, _) = val
160
166
  result = s(:valias, lhs.to_sym, :"$#{rhs}").line line
161
167
  }
162
168
  | kALIAS tGVAR tNTH_REF
@@ -199,7 +205,7 @@ rule
199
205
  (_, line), _, stmt, _ = val
200
206
 
201
207
  if (self.in_def || self.in_single > 0) then
202
- debug20 3
208
+ debug 13
203
209
  yyerror "END in method; use at_exit"
204
210
  end
205
211
 
@@ -243,32 +249,31 @@ rule
243
249
  }
244
250
  | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
245
251
  {
246
- prim, _, id, opasgn, rhs = val
247
- result = s(:op_asgn, prim, rhs, id.to_sym, opasgn.to_sym)
248
- if val[1] == '&.'
249
- result.sexp_type = :safe_op_asgn
250
- end
251
- result.line = val[0].line
252
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
253
+
254
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
255
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
256
+ result.line prim.line
252
257
  }
253
258
  | primary_value call_op tCONSTANT tOP_ASGN command_rhs
254
259
  {
255
- result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
256
- if val[1] == '&.'
257
- result.sexp_type = :safe_op_asgn
258
- end
259
- result.line = val[0].line
260
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
261
+
262
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
263
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
264
+ result.line prim.line
260
265
  }
261
266
  | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
262
267
  {
263
- lhs1, _, lhs2, op, rhs = val
268
+ lhs1, _, (lhs2, line), (id, _), rhs = val
264
269
 
265
- result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
270
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
266
271
  }
267
272
  | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
268
273
  {
269
- lhs1, _, lhs2, op, rhs = val
274
+ lhs1, _, (lhs2, line), (id, _), rhs = val
270
275
 
271
- result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, op.to_sym)
276
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
272
277
  }
273
278
  | backref tOP_ASGN command_rhs
274
279
  {
@@ -306,7 +311,7 @@ rule
306
311
  # TODO: fix line number to tBANG... but causes BAD shift/reduce conflict
307
312
  # REFACTOR: call_uni_op -- see parse26.y
308
313
  }
309
- | arg
314
+ | arg =tLBRACE_ARG
310
315
 
311
316
  expr_value: expr
312
317
  {
@@ -331,7 +336,7 @@ rule
331
336
  block_command: block_call
332
337
  | block_call call_op2 operation2 command_args
333
338
  {
334
- blk, _, msg, args = val
339
+ blk, _, (msg, _line), args = val
335
340
  result = new_call(blk, msg.to_sym, args).line blk.line
336
341
  }
337
342
 
@@ -345,15 +350,15 @@ rule
345
350
  _, line, body, _ = val
346
351
 
347
352
  result = body
348
- result.line = line
353
+ result.line line
349
354
 
350
355
  # self.env.unextend
351
356
  }
352
357
 
353
358
  fcall: operation
354
359
  {
355
- msg, = val
356
- result = new_call(nil, msg.to_sym).line lexer.lineno
360
+ (msg, line), = val
361
+ result = new_call(nil, msg.to_sym).line line
357
362
  }
358
363
 
359
364
  command: fcall command_args =tLOWEST
@@ -376,12 +381,14 @@ rule
376
381
  }
377
382
  | primary_value call_op operation2 command_args =tLOWEST
378
383
  {
379
- lhs, callop, op, args = val
384
+ lhs, callop, (op, _), args = val
385
+
380
386
  result = new_call lhs, op.to_sym, args, callop
387
+ result.line lhs.line
381
388
  }
382
389
  | primary_value call_op operation2 command_args cmd_brace_block
383
390
  {
384
- recv, _, msg, args, block = val
391
+ recv, _, (msg, _line), args, block = val
385
392
  call = new_call recv, msg.to_sym, args, val[1]
386
393
 
387
394
  block_dup_check call, block
@@ -391,11 +398,14 @@ rule
391
398
  }
392
399
  | primary_value tCOLON2 operation2 command_args =tLOWEST
393
400
  {
394
- result = new_call val[0], val[2].to_sym, val[3]
401
+ lhs, _, (id, line), args = val
402
+
403
+ result = new_call lhs, id.to_sym, args
404
+ result.line line
395
405
  }
396
406
  | primary_value tCOLON2 operation2 command_args cmd_brace_block
397
407
  {
398
- recv, _, msg, args, block = val
408
+ recv, _, (msg, _line), args, block = val
399
409
  call = new_call recv, msg.to_sym, args
400
410
 
401
411
  block_dup_check call, block
@@ -553,25 +563,29 @@ rule
553
563
  }
554
564
  | primary_value call_op tIDENTIFIER
555
565
  {
556
- result = new_attrasgn val[0], val[2], val[1]
566
+ lhs, call_op, (id, _line) = val
567
+
568
+ result = new_attrasgn lhs, id, call_op
557
569
  }
558
570
  | primary_value tCOLON2 tIDENTIFIER
559
571
  {
560
- recv, _, id = val
572
+ recv, _, (id, _line) = val
561
573
  result = new_attrasgn recv, id
562
574
  }
563
575
  | primary_value call_op tCONSTANT
564
576
  {
565
- result = new_attrasgn val[0], val[2], val[1]
577
+ lhs, call_op, (id, _line) = val
578
+
579
+ result = new_attrasgn lhs, id, call_op
566
580
  }
567
581
  | primary_value tCOLON2 tCONSTANT
568
582
  {
569
583
  if (self.in_def || self.in_single > 0) then
570
- debug20 7
584
+ debug 14
571
585
  yyerror "dynamic constant assignment"
572
586
  end
573
587
 
574
- expr, _, id = val
588
+ expr, _, (id, _line) = val
575
589
  l = expr.line
576
590
 
577
591
  result = s(:const, s(:colon2, expr, id.to_sym).line(l), nil).line l
@@ -579,58 +593,65 @@ rule
579
593
  | tCOLON3 tCONSTANT
580
594
  {
581
595
  if (self.in_def || self.in_single > 0) then
582
- debug20 8
596
+ debug 15
583
597
  yyerror "dynamic constant assignment"
584
598
  end
585
599
 
586
- _, id = val
587
- l = lexer.lineno
600
+ _, (id, l) = val
588
601
 
589
602
  result = s(:const, nil, s(:colon3, id.to_sym).line(l)).line l
590
603
  }
591
604
  | backref
592
605
  {
593
- self.backref_assign_error val[0]
606
+ ref, = val
607
+
608
+ self.backref_assign_error ref
594
609
  }
595
610
 
596
611
  lhs: user_variable
597
612
  {
598
- line = lexer.lineno
599
- result = self.assignable val[0]
600
- result.line = line
613
+ var, = val
614
+
615
+ result = self.assignable var
601
616
  }
602
617
  | keyword_variable
603
618
  {
604
- line = lexer.lineno
605
- result = self.assignable val[0]
606
- result.line = line
607
- debug20 9, val, result
619
+ var, = val
620
+
621
+ result = self.assignable var
622
+
623
+ debug 16
608
624
  }
609
625
  | primary_value tLBRACK2 opt_call_args rbracket
610
626
  {
611
627
  lhs, _, args, _ = val
628
+
612
629
  result = self.aryset lhs, args
613
630
  }
614
631
  | primary_value call_op tIDENTIFIER # REFACTOR
615
632
  {
616
- lhs, op, id = val
633
+ lhs, op, (id, _line) = val
634
+
617
635
  result = new_attrasgn lhs, id, op
618
636
  }
619
637
  | primary_value tCOLON2 tIDENTIFIER
620
638
  {
621
- lhs, _, id = val
639
+ lhs, _, (id, _line) = val
640
+
622
641
  result = new_attrasgn lhs, id
623
642
  }
624
643
  | primary_value call_op tCONSTANT # REFACTOR?
625
644
  {
626
- result = new_attrasgn val[0], val[2], val[1]
645
+ lhs, call_op, (id, _line) = val
646
+
647
+ result = new_attrasgn lhs, id, call_op
627
648
  }
628
649
  | primary_value tCOLON2 tCONSTANT
629
650
  {
630
- expr, _, id = val
651
+ expr, _, (id, _line) = val
631
652
 
632
653
  if (self.in_def || self.in_single > 0) then
633
- debug20 10
654
+ debug 17
634
655
  yyerror "dynamic constant assignment"
635
656
  end
636
657
 
@@ -639,14 +660,13 @@ rule
639
660
  }
640
661
  | tCOLON3 tCONSTANT
641
662
  {
642
- _, id = val
663
+ _, (id, l) = val
643
664
 
644
665
  if (self.in_def || self.in_single > 0) then
645
- debug20 11
666
+ debug 18
646
667
  yyerror "dynamic constant assignment"
647
668
  end
648
669
 
649
- l = lexer.lineno
650
670
  result = s(:const, s(:colon3, id.to_sym).line(l)).line l
651
671
  }
652
672
  | backref
@@ -662,16 +682,16 @@ rule
662
682
 
663
683
  cpath: tCOLON3 cname
664
684
  {
665
- _, name = val
666
- result = s(:colon3, name.to_sym).line lexer.lineno
685
+ result = wrap :colon3, val[1]
667
686
  }
668
687
  | cname
669
688
  {
670
- result = val[0].to_sym
689
+ (id, line), = val
690
+ result = [id.to_sym, line] # TODO: sexp?
671
691
  }
672
692
  | primary_value tCOLON2 cname
673
693
  {
674
- pval, _, name = val
694
+ pval, _, (name, _line) = val
675
695
 
676
696
  result = s(:colon2, pval, name.to_sym)
677
697
  result.line pval.line
@@ -681,24 +701,15 @@ rule
681
701
  | op
682
702
  {
683
703
  lexer.lex_state = EXPR_END
684
- result = val[0]
685
704
  }
686
705
 
687
706
  | reswords
688
- {
689
- (sym, _line), = val
690
- lexer.lex_state = EXPR_END
691
- result = sym
692
- }
693
-
694
- fsym: fname | symbol
695
707
 
696
- fitem: fsym
708
+ fitem: fname
697
709
  {
698
- id, = val
699
- result = s(:lit, id.to_sym).line lexer.lineno
710
+ result = wrap :lit, val[0]
700
711
  }
701
- | dsym
712
+ | symbol
702
713
 
703
714
  undef_list: fitem
704
715
  {
@@ -719,8 +730,6 @@ rule
719
730
  | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
720
731
  | tSTAR | tDIVIDE | tPERCENT | tPOW | tDSTAR | tBANG | tTILDE
721
732
  | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
722
- # TODO: tUBANG dead?
723
- | tUBANG
724
733
 
725
734
  reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
726
735
  | kALIAS | kAND | kBEGIN | kBREAK | kCASE
@@ -754,26 +763,22 @@ rule
754
763
  }
755
764
  | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
756
765
  {
757
- lhs, _, id, op, rhs = val
766
+ lhs, _, (id, _line), (op, _), rhs = val
758
767
 
759
768
  result = s(:op_asgn, lhs, rhs, id.to_sym, op.to_sym).line lhs.line
760
769
  }
761
770
  | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
762
771
  {
763
- lhs1, _, lhs2, op, rhs = val
772
+ lhs1, _, (lhs2, _line), op, rhs = val
764
773
 
765
774
  lhs = s(:colon2, lhs1, lhs2.to_sym).line lhs1.line
766
775
  result = new_const_op_asgn [lhs, op, rhs]
767
776
  }
768
- | tCOLON3 tCONSTANT
769
- {
770
- result = self.lexer.lineno
771
- }
772
- tOP_ASGN arg_rhs
777
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
773
778
  {
774
- _, lhs, line, op, rhs = val
779
+ _, lhs, op, rhs = val
775
780
 
776
- lhs = s(:colon3, lhs.to_sym).line line
781
+ lhs = wrap :colon3, lhs
777
782
  result = new_const_op_asgn [lhs, op, rhs]
778
783
  }
779
784
  | backref tOP_ASGN arg_rhs
@@ -785,7 +790,7 @@ rule
785
790
  | arg tDOT2 arg
786
791
  {
787
792
  v1, v2 = val[0], val[2]
788
- if v1.node_type == :lit and v2.node_type == :lit and Integer === v1.last and Integer === v2.last then
793
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
789
794
  result = s(:lit, (v1.last)..(v2.last)).line v1.line
790
795
  else
791
796
  result = s(:dot2, v1, v2).line v1.line
@@ -794,7 +799,7 @@ rule
794
799
  | arg tDOT3 arg
795
800
  {
796
801
  v1, v2 = val[0], val[2]
797
- if v1.node_type == :lit and v2.node_type == :lit and Integer === v1.last and Integer === v2.last then
802
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
798
803
  result = s(:lit, (v1.last)...(v2.last)).line v1.line
799
804
  else
800
805
  result = s(:dot3, v1, v2).line v1.line
@@ -828,16 +833,18 @@ rule
828
833
  }
829
834
  | tUMINUS_NUM tINTEGER tPOW arg
830
835
  {
831
- lit = s(:lit, val[1]).line lexer.lineno
832
- result = new_call(new_call(lit, :"**", argl(val[3])), :"-@")
836
+ _, (num, line), _, arg = val
837
+ lit = s(:lit, num).line line
838
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
833
839
  }
834
840
  | tUMINUS_NUM tFLOAT tPOW arg
835
841
  {
836
- lit = s(:lit, val[1]).line lexer.lineno
837
- result = new_call(new_call(lit, :"**", argl(val[3])), :"-@")
842
+ _, (num, line), _, arg = val
843
+ lit = s(:lit, num).line line
844
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
838
845
 
839
846
  ## TODO: why is this 2.0 only?
840
- debug20 12, val, result
847
+ debug 19
841
848
  }
842
849
  | tUPLUS arg
843
850
  {
@@ -935,12 +942,12 @@ rule
935
942
 
936
943
  rel_expr: arg relop arg =tGT
937
944
  {
938
- lhs, op, rhs = val
945
+ lhs, (op, _), rhs = val
939
946
  result = new_call lhs, op.to_sym, argl(rhs)
940
947
  }
941
948
  | rel_expr relop arg =tGT
942
949
  {
943
- lhs, op, rhs = val
950
+ lhs, (op, _), rhs = val
944
951
  warn "comparison '%s' after comparison", op
945
952
  result = new_call lhs, op.to_sym, argl(rhs)
946
953
  }
@@ -1122,8 +1129,9 @@ rule
1122
1129
  | backref
1123
1130
  | tFID
1124
1131
  {
1125
- msg, = val
1132
+ (msg, line), = val
1126
1133
  result = new_call nil, msg.to_sym
1134
+ result.line line
1127
1135
  }
1128
1136
  | k_begin
1129
1137
  {
@@ -1165,15 +1173,13 @@ rule
1165
1173
  }
1166
1174
  | primary_value tCOLON2 tCONSTANT
1167
1175
  {
1168
- expr, _, id = val
1176
+ expr, _, (id, _line) = val
1169
1177
 
1170
1178
  result = s(:colon2, expr, id.to_sym).line expr.line
1171
1179
  }
1172
1180
  | tCOLON3 tCONSTANT
1173
1181
  {
1174
- _, id = val
1175
-
1176
- result = s(:colon3, id.to_sym).line lexer.lineno
1182
+ result = wrap :colon3, val[1]
1177
1183
  }
1178
1184
  | tLBRACK { result = lexer.lineno } aref_args tRBRACK
1179
1185
  {
@@ -1197,15 +1203,21 @@ rule
1197
1203
  }
1198
1204
  | kYIELD tLPAREN2 call_args rparen
1199
1205
  {
1200
- result = new_yield val[2]
1206
+ (_, line), _, args, _ = val
1207
+
1208
+ result = new_yield(args).line line
1201
1209
  }
1202
1210
  | kYIELD tLPAREN2 rparen
1203
1211
  {
1204
- result = new_yield
1212
+ (_, line), _, _ = val
1213
+
1214
+ result = new_yield.line line
1205
1215
  }
1206
1216
  | kYIELD
1207
1217
  {
1208
- result = new_yield
1218
+ (_, line), = val
1219
+
1220
+ result = new_yield.line line
1209
1221
  }
1210
1222
  | kDEFINED opt_nl tLPAREN2 expr rparen
1211
1223
  {
@@ -1220,7 +1232,7 @@ rule
1220
1232
  }
1221
1233
  | kNOT tLPAREN2 rparen
1222
1234
  {
1223
- debug20 14, val, result
1235
+ debug 20
1224
1236
  }
1225
1237
  | fcall brace_block
1226
1238
  {
@@ -1238,9 +1250,10 @@ rule
1238
1250
  iter.insert 1, call # FIX
1239
1251
  result = iter
1240
1252
  }
1241
- | tLAMBDA lambda
1253
+ | lambda
1242
1254
  {
1243
- result = val[1] # TODO: fix lineno
1255
+ expr, = val
1256
+ result = expr
1244
1257
  }
1245
1258
  | k_if expr_value then compstmt if_tail k_end
1246
1259
  {
@@ -1283,7 +1296,6 @@ rule
1283
1296
  }
1284
1297
  cpath superclass
1285
1298
  {
1286
- self.comments.push self.lexer.comments
1287
1299
  if (self.in_def || self.in_single > 0) then
1288
1300
  yyerror "class definition in method body"
1289
1301
  end
@@ -1293,7 +1305,7 @@ rule
1293
1305
  {
1294
1306
  result = new_class val
1295
1307
  self.env.unextend
1296
- self.lexer.comments # we don't care about comments in the body
1308
+ self.lexer.ignore_body_comments
1297
1309
  }
1298
1310
  | k_class tLSHFT
1299
1311
  {
@@ -1314,7 +1326,7 @@ rule
1314
1326
  {
1315
1327
  result = new_sclass val
1316
1328
  self.env.unextend
1317
- self.lexer.comments # we don't care about comments in the body
1329
+ self.lexer.ignore_body_comments
1318
1330
  }
1319
1331
  | k_module
1320
1332
  {
@@ -1322,7 +1334,6 @@ rule
1322
1334
  }
1323
1335
  cpath
1324
1336
  {
1325
- self.comments.push self.lexer.comments
1326
1337
  yyerror "module definition in method body" if
1327
1338
  self.in_def or self.in_single > 0
1328
1339
 
@@ -1332,7 +1343,7 @@ rule
1332
1343
  {
1333
1344
  result = new_module val
1334
1345
  self.env.unextend
1335
- self.lexer.comments # we don't care about comments in the body
1346
+ self.lexer.ignore_body_comments
1336
1347
  }
1337
1348
  | k_def fname
1338
1349
  {
@@ -1342,21 +1353,17 @@ rule
1342
1353
  self.env.extend
1343
1354
  lexer.cmdarg.push false
1344
1355
  lexer.cond.push false
1345
-
1346
- self.comments.push self.lexer.comments
1347
1356
  }
1348
- f_arglist bodystmt { result = lexer.lineno } k_end
1357
+ f_arglist bodystmt k_end
1349
1358
  {
1350
- in_def = val[2]
1351
-
1352
- result = new_defn val
1359
+ result, in_def = new_defn val
1353
1360
 
1354
1361
  lexer.cond.pop # group = local_pop
1355
1362
  lexer.cmdarg.pop
1356
1363
  self.env.unextend
1357
1364
  self.in_def = in_def
1358
1365
 
1359
- self.lexer.comments # we don't care about comments in the body
1366
+ self.lexer.ignore_body_comments
1360
1367
  }
1361
1368
  | k_def singleton dot_or_colon
1362
1369
  {
@@ -1364,7 +1371,7 @@ rule
1364
1371
  }
1365
1372
  fname
1366
1373
  {
1367
- result = [self.in_def, lexer.lineno]
1374
+ result = self.in_def
1368
1375
 
1369
1376
  self.in_single += 1 # TODO: remove?
1370
1377
 
@@ -1374,13 +1381,18 @@ rule
1374
1381
  lexer.cond.push false
1375
1382
 
1376
1383
  lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
1377
- self.comments.push self.lexer.comments
1378
1384
  }
1379
1385
  f_arglist bodystmt k_end
1380
1386
  {
1381
- _, _recv, _, _, _name, (in_def, _lineno), _args, _body, _ = val
1382
1387
 
1383
- result = new_defs val
1388
+ # [kdef, recv, _, _, (name, line), in_def, args, body, kend]
1389
+ # =>
1390
+ # [kdef, recv, (name, line), in_def, args, body, kend]
1391
+
1392
+ val.delete_at 3
1393
+ val.delete_at 2
1394
+
1395
+ result, in_def = new_defs val
1384
1396
 
1385
1397
  lexer.cond.pop # group = local_pop
1386
1398
  lexer.cmdarg.pop
@@ -1391,7 +1403,7 @@ rule
1391
1403
 
1392
1404
  # TODO: restore cur_arg ? what's cur_arg?
1393
1405
 
1394
- self.lexer.comments # we don't care about comments in the body
1406
+ self.lexer.ignore_body_comments
1395
1407
  }
1396
1408
  | kBREAK
1397
1409
  {
@@ -1428,8 +1440,17 @@ rule
1428
1440
  k_case: kCASE
1429
1441
  k_for: kFOR
1430
1442
  k_class: kCLASS
1443
+ {
1444
+ self.comments.push self.lexer.comments
1445
+ }
1431
1446
  k_module: kMODULE
1447
+ {
1448
+ self.comments.push self.lexer.comments
1449
+ }
1432
1450
  k_def: kDEF
1451
+ {
1452
+ self.comments.push self.lexer.comments
1453
+ }
1433
1454
  k_do: kDO
1434
1455
  k_do_block: kDO_BLOCK
1435
1456
  k_rescue: kRESCUE
@@ -1490,51 +1511,42 @@ rule
1490
1511
 
1491
1512
  result = block_var args
1492
1513
  }
1493
- | f_marg_list tCOMMA tSTAR f_norm_arg
1514
+ | f_marg_list tCOMMA f_rest_marg
1494
1515
  {
1495
- args, _, _, splat = val
1516
+ args, _, rest = val
1496
1517
 
1497
- result = block_var args, "*#{splat}".to_sym
1518
+ result = block_var args, rest
1498
1519
  }
1499
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
1520
+ | f_marg_list tCOMMA f_rest_marg tCOMMA f_marg_list
1500
1521
  {
1501
- args, _, _, splat, _, args2 = val
1522
+ lhs, _, splat, _, rhs = val
1502
1523
 
1503
- result = block_var args, "*#{splat}".to_sym, args2
1524
+ result = block_var lhs, splat, rhs
1504
1525
  }
1505
- | f_marg_list tCOMMA tSTAR
1526
+ | f_rest_marg
1506
1527
  {
1507
- args, _, _ = val
1528
+ rest, = val
1508
1529
 
1509
- result = block_var args, :*
1530
+ result = block_var rest
1510
1531
  }
1511
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
1532
+ | f_rest_marg tCOMMA f_marg_list
1512
1533
  {
1513
- args, _, _, _, args2 = val
1534
+ splat, _, rest = val
1514
1535
 
1515
- result = block_var args, :*, args2
1536
+ result = block_var splat, rest
1516
1537
  }
1517
- | tSTAR f_norm_arg
1518
- {
1519
- _, splat = val
1520
1538
 
1521
- result = block_var :"*#{splat}"
1522
- }
1523
- | tSTAR f_norm_arg tCOMMA f_marg_list
1539
+ f_rest_marg: tSTAR f_norm_arg
1524
1540
  {
1525
- _, splat, _, args = val
1541
+ _, (id, line) = val
1526
1542
 
1527
- result = block_var :"*#{splat}", args
1543
+ result = args ["*#{id}".to_sym]
1544
+ result.line line
1528
1545
  }
1529
1546
  | tSTAR
1530
1547
  {
1531
- result = block_var :*
1532
- }
1533
- | tSTAR tCOMMA f_marg_list
1534
- {
1535
- _, _, args = val
1536
-
1537
- result = block_var :*, args
1548
+ result = args [:*]
1549
+ result.line lexer.lineno # FIX: tSTAR -> line
1538
1550
  }
1539
1551
 
1540
1552
  block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
@@ -1551,8 +1563,8 @@ rule
1551
1563
  }
1552
1564
  | f_block_arg
1553
1565
  {
1554
- line = lexer.lineno
1555
- result = call_args val # TODO: push line down
1566
+ (id, line), = val
1567
+ result = call_args [id]
1556
1568
  result.line line
1557
1569
  }
1558
1570
 
@@ -1661,13 +1673,12 @@ opt_block_args_tail: tCOMMA block_args_tail
1661
1673
 
1662
1674
  bvar: tIDENTIFIER
1663
1675
  {
1664
- id, = val
1665
- line = lexer.lineno
1666
- result = s(:shadow, id.to_sym).line line
1676
+ result = wrap :shadow, val[0]
1667
1677
  }
1668
1678
  | f_bad_arg
1669
1679
 
1670
- lambda: {
1680
+ lambda: tLAMBDA
1681
+ {
1671
1682
  self.env.extend :dynamic
1672
1683
  result = [lexer.lineno, lexer.lpar_beg]
1673
1684
  lexer.paren_nest += 1
@@ -1679,14 +1690,14 @@ opt_block_args_tail: tCOMMA block_args_tail
1679
1690
  }
1680
1691
  lambda_body
1681
1692
  {
1682
- (line, lpar), args, _cmdarg, body = val
1693
+ _, (line, lpar), args, _cmdarg, body = val
1683
1694
  lexer.lpar_beg = lpar
1684
1695
 
1685
1696
  lexer.cmdarg.pop
1686
1697
 
1687
1698
  call = s(:lambda).line line
1688
1699
  result = new_iter call, args, body
1689
- result.line = line
1700
+ result.line line
1690
1701
  self.env.unextend # TODO: dynapush & dynapop
1691
1702
  }
1692
1703
 
@@ -1721,23 +1732,28 @@ opt_block_args_tail: tCOMMA block_args_tail
1721
1732
  ## if (nd_type($1) == NODE_YIELD) {
1722
1733
  ## compile_error(PARSER_ARG "block given to yield");
1723
1734
 
1724
- syntax_error "Both block arg and actual block given." if
1725
- val[0].block_pass?
1735
+ cmd, blk = val
1726
1736
 
1727
- val = invert_block_call val if inverted? val
1737
+ syntax_error "Both block arg and actual block given." if
1738
+ cmd.block_pass?
1728
1739
 
1729
- cmd, blk = val
1740
+ if inverted? val then
1741
+ val = invert_block_call val
1742
+ cmd, blk = val
1743
+ end
1730
1744
 
1731
1745
  result = blk
1732
1746
  result.insert 1, cmd
1733
1747
  }
1734
1748
  | block_call call_op2 operation2 opt_paren_args
1735
1749
  {
1736
- result = new_call val[0], val[2].to_sym, val[3]
1750
+ lhs, _, (id, _line), args = val
1751
+
1752
+ result = new_call lhs, id.to_sym, args
1737
1753
  }
1738
1754
  | block_call call_op2 operation2 opt_paren_args brace_block
1739
1755
  {
1740
- iter1, _, name, args, iter2 = val
1756
+ iter1, _, (name, _line), args, iter2 = val
1741
1757
 
1742
1758
  call = new_call iter1, name.to_sym, args
1743
1759
  iter2.insert 1, call
@@ -1746,7 +1762,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1746
1762
  }
1747
1763
  | block_call call_op2 operation2 command_args do_block
1748
1764
  {
1749
- iter1, _, name, args, iter2 = val
1765
+ iter1, _, (name, _line), args, iter2 = val
1750
1766
 
1751
1767
  call = new_call iter1, name.to_sym, args
1752
1768
  iter2.insert 1, call
@@ -1754,28 +1770,29 @@ opt_block_args_tail: tCOMMA block_args_tail
1754
1770
  result = iter2
1755
1771
  }
1756
1772
 
1757
- method_call: fcall
1758
- {
1759
- result = self.lexer.lineno
1760
- }
1761
- paren_args
1773
+ method_call: fcall paren_args
1762
1774
  {
1763
- call, lineno, args = val
1775
+ call, args = val
1764
1776
 
1765
1777
  result = call.concat args.sexp_body if args
1766
- result.line lineno
1767
1778
  }
1768
1779
  | primary_value call_op operation2 opt_paren_args
1769
1780
  {
1770
- result = new_call val[0], val[2].to_sym, val[3], val[1]
1781
+ recv, call_op, (op, _line), args = val
1782
+
1783
+ result = new_call recv, op.to_sym, args, call_op
1771
1784
  }
1772
1785
  | primary_value tCOLON2 operation2 paren_args
1773
1786
  {
1774
- result = new_call val[0], val[2].to_sym, val[3]
1787
+ recv, _, (op, _line), args = val
1788
+
1789
+ result = new_call recv, op.to_sym, args
1775
1790
  }
1776
1791
  | primary_value tCOLON2 operation3
1777
1792
  {
1778
- result = new_call val[0], val[2].to_sym
1793
+ lhs, _, (id, _line) = val
1794
+
1795
+ result = new_call lhs, id.to_sym
1779
1796
  }
1780
1797
  | primary_value call_op paren_args
1781
1798
  {
@@ -1808,7 +1825,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1808
1825
  _, line, body, _ = val
1809
1826
 
1810
1827
  result = body
1811
- result.line = line
1828
+ result.line line
1812
1829
 
1813
1830
  self.env.unextend
1814
1831
  }
@@ -1822,7 +1839,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1822
1839
  _, line, body, _ = val
1823
1840
 
1824
1841
  result = body
1825
- result.line = line
1842
+ result.line line
1826
1843
 
1827
1844
  self.env.unextend
1828
1845
  }
@@ -1851,14 +1868,39 @@ opt_block_args_tail: tCOMMA block_args_tail
1851
1868
  self.env.unextend
1852
1869
  }
1853
1870
 
1871
+ case_args: arg_value
1872
+ {
1873
+ arg, = val
1874
+
1875
+ result = s(:array, arg).line arg.line
1876
+ }
1877
+ | tSTAR arg_value
1878
+ {
1879
+ _, arg = val
1880
+
1881
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
1882
+ }
1883
+ | case_args tCOMMA arg_value
1884
+ {
1885
+ args, _, id = val
1886
+
1887
+ result = self.list_append args, id
1888
+ }
1889
+ | case_args tCOMMA tSTAR arg_value
1890
+ {
1891
+ args, _, _, id = val
1892
+
1893
+ result = self.list_append args, s(:splat, id).line(id.line)
1894
+ }
1895
+
1854
1896
  case_body: k_when
1855
1897
  {
1856
1898
  result = self.lexer.lineno
1857
1899
  }
1858
- args then compstmt cases
1900
+ case_args then compstmt cases
1859
1901
  {
1860
1902
  result = new_when(val[2], val[4])
1861
- result.line = val[1]
1903
+ result.line val[1]
1862
1904
  result << val[5] if val[5]
1863
1905
  }
1864
1906
 
@@ -1904,17 +1946,10 @@ opt_block_args_tail: tCOMMA block_args_tail
1904
1946
 
1905
1947
  literal: numeric
1906
1948
  {
1907
- line = lexer.lineno
1908
- result = s(:lit, val[0])
1909
- result.line = line
1949
+ (lit, line), = val
1950
+ result = s(:lit, lit).line line
1910
1951
  }
1911
1952
  | symbol
1912
- {
1913
- line = lexer.lineno
1914
- result = s(:lit, val[0])
1915
- result.line = line
1916
- }
1917
- | dsym
1918
1953
 
1919
1954
  strings: string
1920
1955
  {
@@ -1925,7 +1960,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1925
1960
 
1926
1961
  string: tCHAR
1927
1962
  {
1928
- debug20 23, val, result
1963
+ debug 37
1929
1964
  }
1930
1965
  | string1
1931
1966
  | string string1
@@ -1935,11 +1970,11 @@ opt_block_args_tail: tCOMMA block_args_tail
1935
1970
 
1936
1971
  string1: tSTRING_BEG string_contents tSTRING_END
1937
1972
  {
1938
- _, str, (_, func) = val
1973
+ (_, line), str, (_, func) = val
1939
1974
 
1940
- str = dedent str if func =~ RubyLexer::STR_FUNC_ICNTNT
1975
+ str = dedent str if func =~ RubyLexer::STR_FUNC_DEDENT
1941
1976
 
1942
- result = str
1977
+ result = str.line line
1943
1978
  }
1944
1979
  | tSTRING
1945
1980
  {
@@ -1959,11 +1994,15 @@ opt_block_args_tail: tCOMMA block_args_tail
1959
1994
 
1960
1995
  words: tWORDS_BEG tSPACE tSTRING_END
1961
1996
  {
1962
- result = s(:array).line lexer.lineno
1997
+ (_, line), _, _ = val
1998
+
1999
+ result = s(:array).line line
1963
2000
  }
1964
2001
  | tWORDS_BEG word_list tSTRING_END
1965
2002
  {
1966
- result = val[1]
2003
+ (_, line), list, _ = val
2004
+
2005
+ result = list.line line
1967
2006
  }
1968
2007
 
1969
2008
  word_list: none
@@ -1983,18 +2022,20 @@ opt_block_args_tail: tCOMMA block_args_tail
1983
2022
 
1984
2023
  symbols: tSYMBOLS_BEG tSPACE tSTRING_END
1985
2024
  {
1986
- result = s(:array).line lexer.lineno
2025
+ (_, line), _, _ = val
2026
+
2027
+ result = s(:array).line line
1987
2028
  }
1988
- | tSYMBOLS_BEG { result = lexer.lineno } symbol_list tSTRING_END
2029
+ | tSYMBOLS_BEG symbol_list tSTRING_END
1989
2030
  {
1990
- _, line, list, _, = val
1991
- list.line = line
2031
+ (_, line), list, _, = val
2032
+ list.line line
1992
2033
  result = list
1993
2034
  }
1994
2035
 
1995
2036
  symbol_list: none
1996
2037
  {
1997
- result = new_symbol_list.line lexer.lineno
2038
+ result = new_symbol_list
1998
2039
  }
1999
2040
  | symbol_list word tSPACE
2000
2041
  {
@@ -2004,20 +2045,28 @@ opt_block_args_tail: tCOMMA block_args_tail
2004
2045
 
2005
2046
  qwords: tQWORDS_BEG tSPACE tSTRING_END
2006
2047
  {
2007
- result = s(:array).line lexer.lineno
2048
+ (_, line), _, _ = val
2049
+
2050
+ result = s(:array).line line
2008
2051
  }
2009
2052
  | tQWORDS_BEG qword_list tSTRING_END
2010
2053
  {
2011
- result = val[1]
2054
+ (_, line), list, _ = val
2055
+
2056
+ result = list.line line
2012
2057
  }
2013
2058
 
2014
2059
  qsymbols: tQSYMBOLS_BEG tSPACE tSTRING_END
2015
2060
  {
2016
- result = s(:array).line lexer.lineno # FIX
2061
+ (_, line), _, _ = val
2062
+
2063
+ result = s(:array).line line
2017
2064
  }
2018
2065
  | tQSYMBOLS_BEG qsym_list tSTRING_END
2019
2066
  {
2020
- result = val[1]
2067
+ (_, line), list, _ = val
2068
+
2069
+ result = list.line line
2021
2070
  }
2022
2071
 
2023
2072
  qword_list: none
@@ -2040,7 +2089,8 @@ opt_block_args_tail: tCOMMA block_args_tail
2040
2089
 
2041
2090
  string_contents: none
2042
2091
  {
2043
- result = s(:str, "").line lexer.lineno
2092
+ line = prev_value_to_lineno _values.last
2093
+ result = s(:str, +"").line line
2044
2094
  }
2045
2095
  | string_contents string_content
2046
2096
  {
@@ -2115,8 +2165,8 @@ regexp_contents: none
2115
2165
  lexer.brace_nest = brace_nest
2116
2166
  lexer.string_nest = string_nest
2117
2167
 
2118
- lexer.cmdarg.pop
2119
2168
  lexer.cond.pop
2169
+ lexer.cmdarg.pop
2120
2170
 
2121
2171
  lexer.lex_state = oldlex_state
2122
2172
 
@@ -2131,29 +2181,42 @@ regexp_contents: none
2131
2181
  when nil then
2132
2182
  result = s(:evstr).line line
2133
2183
  else
2134
- debug20 25
2184
+ debug 38
2135
2185
  raise "unknown string body: #{stmt.inspect}"
2136
2186
  end
2137
2187
  }
2138
2188
 
2139
- string_dvar: tGVAR { result = s(:gvar, val[0].to_sym).line lexer.lineno }
2140
- | tIVAR { result = s(:ivar, val[0].to_sym).line lexer.lineno }
2141
- | tCVAR { result = s(:cvar, val[0].to_sym).line lexer.lineno }
2189
+ string_dvar: tGVAR
2190
+ {
2191
+ result = wrap :gvar, val[0]
2192
+ }
2193
+ | tIVAR
2194
+ {
2195
+ result = wrap :ivar, val[0]
2196
+ }
2197
+ | tCVAR
2198
+ {
2199
+ result = wrap :cvar, val[0]
2200
+ }
2142
2201
  | backref
2143
2202
 
2144
- symbol: tSYMBEG sym
2203
+ symbol: ssym
2204
+ | dsym
2205
+
2206
+ ssym: tSYMBEG sym
2145
2207
  {
2146
2208
  lexer.lex_state = EXPR_END
2147
- result = val[1].to_sym
2209
+ result = wrap :lit, val[1]
2148
2210
  }
2149
2211
  | tSYMBOL
2150
2212
  {
2151
- result = val[0].to_sym
2213
+ lexer.lex_state = EXPR_END
2214
+ result = wrap :lit, val[0]
2152
2215
  }
2153
2216
 
2154
2217
  sym: fname | tIVAR | tGVAR | tCVAR
2155
2218
 
2156
- dsym: tSYMBEG xstring_contents tSTRING_END
2219
+ dsym: tSYMBEG string_contents tSTRING_END
2157
2220
  {
2158
2221
  _, result, _ = val
2159
2222
 
@@ -2169,7 +2232,7 @@ regexp_contents: none
2169
2232
  when :evstr then
2170
2233
  result = s(:dsym, "", result).line result.line
2171
2234
  else
2172
- debug20 26, val, result
2235
+ debug 39
2173
2236
  end
2174
2237
  }
2175
2238
 
@@ -2177,11 +2240,13 @@ regexp_contents: none
2177
2240
  | tFLOAT
2178
2241
  | tUMINUS_NUM tINTEGER =tLOWEST
2179
2242
  {
2180
- result = -val[1] # TODO: pt_testcase
2243
+ _, (num, line) = val
2244
+ result = [-num, line]
2181
2245
  }
2182
2246
  | tUMINUS_NUM tFLOAT =tLOWEST
2183
2247
  {
2184
- result = -val[1] # TODO: pt_testcase
2248
+ _, (num, line) = val
2249
+ result = [-num, line]
2185
2250
  }
2186
2251
 
2187
2252
  user_variable: tIDENTIFIER
@@ -2209,8 +2274,10 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2209
2274
 
2210
2275
  var_ref: user_variable
2211
2276
  {
2212
- var = val[0]
2277
+ raise "NO: #{val.inspect}" if Sexp === val.first
2278
+ (var, line), = val
2213
2279
  result = Sexp === var ? var : self.gettable(var)
2280
+ result.line line
2214
2281
  }
2215
2282
  | keyword_variable
2216
2283
  {
@@ -2225,11 +2292,19 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2225
2292
  | keyword_variable
2226
2293
  {
2227
2294
  result = self.assignable val[0]
2228
- debug20 29, val, result
2295
+ debug 40
2229
2296
  }
2230
2297
 
2231
- backref: tNTH_REF { result = s(:nth_ref, val[0]).line lexer.lineno }
2232
- | tBACK_REF { result = s(:back_ref, val[0]).line lexer.lineno }
2298
+ backref: tNTH_REF
2299
+ {
2300
+ (ref, line), = val
2301
+ result = s(:nth_ref, ref).line line
2302
+ }
2303
+ | tBACK_REF
2304
+ {
2305
+ (ref, line), = val
2306
+ result = s(:back_ref, ref).line line
2307
+ }
2233
2308
 
2234
2309
  superclass: tLT
2235
2310
  {
@@ -2247,9 +2322,7 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2247
2322
 
2248
2323
  f_arglist: tLPAREN2 f_args rparen
2249
2324
  {
2250
- result = val[1]
2251
- self.lexer.lex_state = EXPR_BEG
2252
- self.lexer.command_start = true
2325
+ result = end_args val
2253
2326
  }
2254
2327
  | {
2255
2328
  result = self.in_kwarg
@@ -2258,12 +2331,7 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2258
2331
  }
2259
2332
  f_args term
2260
2333
  {
2261
- kwarg, args, _ = val
2262
-
2263
- self.in_kwarg = kwarg
2264
- result = args
2265
- lexer.lex_state = EXPR_BEG
2266
- lexer.command_start = true
2334
+ result = end_args val
2267
2335
  }
2268
2336
 
2269
2337
  args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
@@ -2348,6 +2416,7 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2348
2416
  |
2349
2417
  {
2350
2418
  result = args val
2419
+ # result.line lexer.lineno
2351
2420
  }
2352
2421
 
2353
2422
 
@@ -2371,31 +2440,24 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2371
2440
  f_norm_arg: f_bad_arg
2372
2441
  | tIDENTIFIER
2373
2442
  {
2374
- identifier = val[0].to_sym
2443
+ (id, line), = val
2444
+ identifier = id.to_sym
2375
2445
  self.env[identifier] = :lvar
2376
2446
 
2377
- result = identifier
2447
+ result = [identifier, line]
2378
2448
  }
2379
2449
 
2380
2450
  f_arg_item: f_norm_arg
2381
2451
  | tLPAREN f_margs rparen
2382
2452
  {
2383
- result = val[1]
2453
+ _, margs, _ = val
2454
+
2455
+ result = margs
2384
2456
  }
2385
2457
 
2386
2458
  f_arg: f_arg_item
2387
2459
  {
2388
- arg, = val
2389
-
2390
- case arg
2391
- when Symbol then
2392
- result = s(:args, arg).line lexer.lineno
2393
- when Sexp then
2394
- result = arg
2395
- else
2396
- debug20 32
2397
- raise "Unknown f_arg type: #{val.inspect}"
2398
- end
2460
+ result = new_arg val
2399
2461
  }
2400
2462
  | f_arg tCOMMA f_arg_item
2401
2463
  {
@@ -2407,7 +2469,7 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2407
2469
  result = s(:args, list).line list.line
2408
2470
  end
2409
2471
 
2410
- result << item
2472
+ result << (Sexp === item ? item : item.first)
2411
2473
  }
2412
2474
 
2413
2475
  f_kw: tLABEL arg_value
@@ -2448,27 +2510,33 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2448
2510
  kwrest_mark: tPOW
2449
2511
  | tDSTAR
2450
2512
 
2513
+
2451
2514
  f_kwrest: kwrest_mark tIDENTIFIER
2452
2515
  {
2453
- name = val[1].to_sym
2454
- self.assignable name
2455
- result = :"**#{name}"
2516
+ _, (id, line) = val
2517
+
2518
+ name = id.to_sym
2519
+ self.assignable [name, line]
2520
+ result = [:"**#{name}", line]
2456
2521
  }
2457
2522
  | kwrest_mark
2458
2523
  {
2459
- result = :"**"
2460
- self.env[result] = :lvar
2524
+ id = :"**"
2525
+ self.env[id] = :lvar # TODO: needed?!?
2526
+ result = [id, lexer.lineno] # TODO: tPOW/tDSTAR include lineno
2461
2527
  }
2462
2528
 
2463
2529
  f_opt: tIDENTIFIER tEQL arg_value
2464
2530
  {
2465
- result = self.assignable val[0], val[2]
2531
+ lhs, _, rhs = val
2532
+ result = self.assignable lhs, rhs
2466
2533
  # TODO: detect duplicate names
2467
2534
  }
2468
2535
 
2469
2536
  f_block_opt: tIDENTIFIER tEQL primary_value
2470
2537
  {
2471
- result = self.assignable val[0], val[2]
2538
+ lhs, _, rhs = val
2539
+ result = self.assignable lhs, rhs
2472
2540
  }
2473
2541
 
2474
2542
  f_block_optarg: f_block_opt
@@ -2498,30 +2566,33 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2498
2566
  f_rest_arg: restarg_mark tIDENTIFIER
2499
2567
  {
2500
2568
  # TODO: differs from parse.y - needs tests
2501
- name = val[1].to_sym
2502
- self.assignable name
2503
- result = :"*#{name}"
2569
+ _, (id, line) = val
2570
+ name = id.to_sym
2571
+ self.assignable [name, line]
2572
+ result = [:"*#{name}", line]
2504
2573
  }
2505
2574
  | restarg_mark
2506
2575
  {
2507
2576
  name = :"*"
2508
2577
  self.env[name] = :lvar
2509
- result = name
2578
+ result = [name, lexer.lineno] # FIX: tSTAR to include lineno
2510
2579
  }
2511
2580
 
2512
2581
  blkarg_mark: tAMPER2 | tAMPER
2513
2582
 
2514
2583
  f_block_arg: blkarg_mark tIDENTIFIER
2515
2584
  {
2516
- identifier = val[1].to_sym
2585
+ _, (id, line) = val
2586
+ identifier = id.to_sym
2517
2587
 
2518
2588
  self.env[identifier] = :lvar
2519
- result = "&#{identifier}".to_sym
2589
+ result = ["&#{identifier}".to_sym, line]
2520
2590
  }
2521
2591
 
2522
2592
  opt_f_block_arg: tCOMMA f_block_arg
2523
2593
  {
2524
- result = val[1]
2594
+ _, arg = val
2595
+ result = arg
2525
2596
  }
2526
2597
  |
2527
2598
  {
@@ -2563,10 +2634,10 @@ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2563
2634
  }
2564
2635
  | tLABEL arg_value
2565
2636
  {
2566
- (label, line), arg = val
2637
+ label, arg = val
2567
2638
 
2568
- lit = s(:lit, label.to_sym).line line
2569
- result = s(:array, lit, arg).line line
2639
+ lit = wrap :lit, label
2640
+ result = s(:array, lit, arg).line lit.line
2570
2641
  }
2571
2642
  | tDSTAR arg_value
2572
2643
  {