ruby_parser 3.12.0 → 3.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.autotest +18 -29
  4. data/History.rdoc +283 -0
  5. data/Manifest.txt +12 -4
  6. data/README.rdoc +4 -3
  7. data/Rakefile +189 -51
  8. data/bin/ruby_parse +3 -1
  9. data/bin/ruby_parse_extract_error +19 -36
  10. data/compare/normalize.rb +76 -4
  11. data/debugging.md +190 -0
  12. data/gauntlet.md +106 -0
  13. data/lib/rp_extensions.rb +14 -42
  14. data/lib/rp_stringscanner.rb +20 -51
  15. data/lib/ruby20_parser.rb +4659 -4218
  16. data/lib/ruby20_parser.y +953 -602
  17. data/lib/ruby21_parser.rb +4723 -4308
  18. data/lib/ruby21_parser.y +956 -605
  19. data/lib/ruby22_parser.rb +4762 -4337
  20. data/lib/ruby22_parser.y +960 -612
  21. data/lib/ruby23_parser.rb +4761 -4342
  22. data/lib/ruby23_parser.y +961 -613
  23. data/lib/ruby24_parser.rb +4791 -4341
  24. data/lib/ruby24_parser.y +968 -612
  25. data/lib/ruby25_parser.rb +4791 -4341
  26. data/lib/ruby25_parser.y +968 -612
  27. data/lib/ruby26_parser.rb +7287 -0
  28. data/lib/ruby26_parser.y +2749 -0
  29. data/lib/ruby27_parser.rb +8517 -0
  30. data/lib/ruby27_parser.y +3346 -0
  31. data/lib/ruby30_parser.rb +8751 -0
  32. data/lib/ruby30_parser.y +3472 -0
  33. data/lib/ruby3_parser.yy +3476 -0
  34. data/lib/ruby_lexer.rb +611 -826
  35. data/lib/ruby_lexer.rex +48 -40
  36. data/lib/ruby_lexer.rex.rb +122 -46
  37. data/lib/ruby_lexer_strings.rb +638 -0
  38. data/lib/ruby_parser.rb +38 -34
  39. data/lib/ruby_parser.yy +1710 -704
  40. data/lib/ruby_parser_extras.rb +987 -553
  41. data/test/test_ruby_lexer.rb +1718 -1539
  42. data/test/test_ruby_parser.rb +3957 -2164
  43. data/test/test_ruby_parser_extras.rb +39 -4
  44. data/tools/munge.rb +250 -0
  45. data/tools/ripper.rb +44 -0
  46. data.tar.gz.sig +0 -0
  47. metadata +68 -47
  48. metadata.gz.sig +0 -0
  49. data/lib/ruby18_parser.rb +0 -5793
  50. data/lib/ruby18_parser.y +0 -1908
  51. data/lib/ruby19_parser.rb +0 -6185
  52. data/lib/ruby19_parser.y +0 -2116
data/lib/ruby23_parser.y CHANGED
@@ -18,49 +18,53 @@ 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
  tRATIONAL tIMAGINARY
23
23
  tLABEL_END
24
24
  tLONELY
25
25
 
26
- prechigh
27
- right tBANG tTILDE tUPLUS
28
- right tPOW
29
- right tUMINUS_NUM tUMINUS
30
- left tSTAR2 tDIVIDE tPERCENT
31
- left tPLUS tMINUS
32
- left tLSHFT tRSHFT
33
- left tAMPER2
34
- left tPIPE tCARET
35
- left tGT tGEQ tLT tLEQ
36
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
37
- left tANDOP
38
- left tOROP
39
- nonassoc tDOT2 tDOT3
40
- right tEH tCOLON
41
- left kRESCUE_MOD
42
- right tEQL tOP_ASGN
43
- nonassoc kDEFINED
44
- right kNOT
45
- left kOR kAND
46
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
47
- nonassoc tLBRACE_ARG
48
- nonassoc tLOWEST
49
26
  preclow
27
+ nonassoc tLOWEST
28
+ nonassoc tLBRACE_ARG
29
+ nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
30
+ left kOR kAND
31
+ right kNOT
32
+ nonassoc kDEFINED
33
+ right tEQL tOP_ASGN
34
+ left kRESCUE_MOD
35
+ right tEH tCOLON
36
+ nonassoc tDOT2 tDOT3 tBDOT2 tBDOT3
37
+ left tOROP
38
+ left tANDOP
39
+ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
40
+ left tGT tGEQ tLT tLEQ
41
+ left tPIPE tCARET
42
+ left tAMPER2
43
+ left tLSHFT tRSHFT
44
+ left tPLUS tMINUS
45
+ left tSTAR2 tDIVIDE tPERCENT # TODO: tSTAR2 -> tMULT
46
+ right tUMINUS_NUM tUMINUS
47
+ right tPOW
48
+ right tBANG tTILDE tUPLUS
49
+ prechigh
50
50
 
51
51
  rule
52
52
 
53
53
  program: {
54
- self.lexer.lex_state = :expr_beg
54
+ self.lexer.lex_state = EXPR_BEG
55
55
  }
56
56
  top_compstmt
57
57
  {
58
58
  result = new_compstmt val
59
+
60
+ lexer.cond.pop # local_pop
61
+ lexer.cmdarg.pop
59
62
  }
60
63
 
61
64
  top_compstmt: top_stmts opt_terms
62
65
  {
63
- result = val[0]
66
+ stmt, _ = val
67
+ result = stmt
64
68
  }
65
69
 
66
70
  top_stmts: none
@@ -72,30 +76,50 @@ rule
72
76
  | error top_stmt
73
77
 
74
78
  top_stmt: stmt
75
- {
76
- result = val[0]
77
-
78
- # TODO: remove once I have more confidence this is fixed
79
- # result.each_of_type :call_args do |s|
80
- # debug20 666, s, result
81
- # end
82
- }
83
79
  | klBEGIN
84
80
  {
85
81
  if (self.in_def || self.in_single > 0) then
86
- debug20 1
82
+ debug 11
87
83
  yyerror "BEGIN in method"
88
84
  end
89
85
  self.env.extend
90
86
  }
91
- tLCURLY top_compstmt tRCURLY
87
+ begin_block
88
+ {
89
+ (_, lineno), _, iter = val
90
+ iter.line lineno
91
+
92
+ (_, preexe,) = iter
93
+ preexe.line lineno
94
+
95
+ result = iter
96
+ }
97
+
98
+ begin_block: tLCURLY { result = lexer.lineno } top_compstmt tRCURLY
92
99
  {
93
- result = new_iter s(:preexe), nil, val[3]
100
+ _, line, stmt, _ = val
101
+ result = new_iter s(:preexe).line(line), 0, stmt
94
102
  }
95
103
 
96
- bodystmt: compstmt opt_rescue opt_else opt_ensure
104
+ bodystmt: compstmt opt_rescue k_else
97
105
  {
98
- result = new_body val
106
+ res = _values[-2]
107
+ # TODO: move down to main match so I can just use val
108
+
109
+ warn "else without rescue is useless" unless res
110
+ }
111
+ compstmt
112
+ opt_ensure
113
+ {
114
+ body, resc, _, _, els, ens = val
115
+
116
+ result = new_body [body, resc, els, ens]
117
+ }
118
+ | compstmt opt_rescue opt_ensure
119
+ {
120
+ body, resc, ens = val
121
+
122
+ result = new_body [body, resc, nil, ens]
99
123
  }
100
124
 
101
125
  compstmt: stmts opt_terms
@@ -104,33 +128,45 @@ rule
104
128
  }
105
129
 
106
130
  stmts: none
107
- | stmt
108
- | stmts terms stmt
131
+ | stmt_or_begin # TODO: newline_node ?
132
+ | stmts terms stmt_or_begin
109
133
  {
110
134
  result = self.block_append val[0], val[2]
111
135
  }
112
136
  | error stmt
113
137
  {
114
138
  result = val[1]
115
- debug20 2, val, result
139
+ debug 12
140
+ }
141
+
142
+ stmt_or_begin: stmt
143
+ | klBEGIN
144
+ {
145
+ yyerror "BEGIN is permitted only at toplevel"
146
+ }
147
+ begin_block
148
+ {
149
+ result = val[2] # wtf?
116
150
  }
117
151
 
118
152
  stmt: kALIAS fitem
119
153
  {
120
- lexer.lex_state = :expr_fname
121
- result = self.lexer.lineno
154
+ lexer.lex_state = EXPR_FNAME
122
155
  }
123
156
  fitem
124
157
  {
125
- result = s(:alias, val[1], val[3]).line(val[2])
158
+ (_, line), lhs, _, rhs = val
159
+ result = s(:alias, lhs, rhs).line(line).line line
126
160
  }
127
161
  | kALIAS tGVAR tGVAR
128
162
  {
129
- result = s(:valias, val[1].to_sym, val[2].to_sym)
163
+ (_, line), (lhs, _), (rhs, _) = val
164
+ result = s(:valias, lhs.to_sym, rhs.to_sym).line line
130
165
  }
131
166
  | kALIAS tGVAR tBACK_REF
132
167
  {
133
- result = s(:valias, val[1].to_sym, :"$#{val[2]}")
168
+ (_, line), (lhs, _), (rhs, _) = val
169
+ result = s(:valias, lhs.to_sym, :"$#{rhs}").line line
134
170
  }
135
171
  | kALIAS tGVAR tNTH_REF
136
172
  {
@@ -142,170 +178,216 @@ rule
142
178
  }
143
179
  | stmt kIF_MOD expr_value
144
180
  {
145
- result = new_if val[2], val[0], nil
181
+ t, _, c = val
182
+ result = new_if c, t, nil
146
183
  }
147
184
  | stmt kUNLESS_MOD expr_value
148
185
  {
149
- result = new_if val[2], nil, val[0]
186
+ f, _, c = val
187
+ result = new_if c, nil, f
150
188
  }
151
189
  | stmt kWHILE_MOD expr_value
152
190
  {
153
- result = new_while val[0], val[2], true
191
+ e, _, c = val
192
+ result = new_while e, c, true
154
193
  }
155
194
  | stmt kUNTIL_MOD expr_value
156
195
  {
157
- result = new_until val[0], val[2], true
196
+ e, _, c = val
197
+ result = new_until e, c, true
158
198
  }
159
199
  | stmt kRESCUE_MOD stmt
160
200
  {
161
- result = s(:rescue, val[0], new_resbody(s(:array), val[2]))
201
+ body, _, resbody = val
202
+
203
+ resbody = new_resbody s(:array).line(resbody.line), resbody
204
+ result = new_rescue body, resbody
162
205
  }
163
206
  | klEND tLCURLY compstmt tRCURLY
164
207
  {
208
+ (_, line), _, stmt, _ = val
209
+
165
210
  if (self.in_def || self.in_single > 0) then
166
- debug20 3
211
+ debug 13
167
212
  yyerror "END in method; use at_exit"
168
213
  end
169
- result = new_iter s(:postexe), 0, val[2]
214
+
215
+ result = new_iter s(:postexe).line(line), 0, stmt
170
216
  }
171
217
  | command_asgn
172
218
  | mlhs tEQL command_call
173
219
  {
174
220
  result = new_masgn val[0], val[2], :wrap
175
221
  }
176
- | var_lhs tOP_ASGN command_call
222
+ | lhs tEQL mrhs
177
223
  {
178
- result = new_op_asgn val
224
+ lhs, _, rhs = val
225
+ result = new_assign lhs, s(:svalue, rhs).line(rhs.line)
179
226
  }
180
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call
227
+ | mlhs tEQL mrhs_arg
181
228
  {
182
- result = s(:op_asgn1, val[0], val[2], val[4].to_sym, val[5])
229
+ result = new_masgn val[0], val[2]
183
230
  }
184
- | primary_value call_op tIDENTIFIER tOP_ASGN command_call
231
+ | expr
232
+
233
+ command_asgn: lhs tEQL command_rhs
185
234
  {
186
- result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
187
- if val[1] == '&.'
188
- result.sexp_type = :safe_op_asgn
189
- end
190
- result.line = val[0].line
235
+ result = new_assign val[0], val[2]
191
236
  }
192
- | primary_value call_op tCONSTANT tOP_ASGN command_call
237
+ # | lhs tEQL command_asgn
238
+ # {
239
+ # result = new_assign val[0], val[2]
240
+ # }
241
+ | var_lhs tOP_ASGN command_rhs
193
242
  {
194
- result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
195
- if val[1] == '&.'
196
- result.sexp_type = :safe_op_asgn
197
- end
198
- result.line = val[0].line
243
+ result = new_op_asgn val
199
244
  }
200
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
245
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_rhs
201
246
  {
202
- result = s(:op_asgn, val[0], val[4], val[2], val[3])
203
- debug20 4, val, result
247
+ result = new_op_asgn1 val
204
248
  }
205
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
249
+ | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
206
250
  {
207
- result = s(:op_asgn, val[0], val[4], val[2], val[3])
208
- debug20 5, val, result
251
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
252
+
253
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
254
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
255
+ result.line prim.line
209
256
  }
210
- | backref tOP_ASGN command_call
257
+ | primary_value call_op tCONSTANT tOP_ASGN command_rhs
211
258
  {
212
- self.backref_assign_error val[0]
259
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
260
+
261
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
262
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
263
+ result.line prim.line
213
264
  }
214
- | lhs tEQL mrhs
265
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
215
266
  {
216
- result = new_assign val[0], s(:svalue, val[2])
267
+ lhs1, _, (lhs2, line), (id, _), rhs = val
268
+
269
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
217
270
  }
218
- | mlhs tEQL mrhs_arg
271
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
219
272
  {
220
- result = new_masgn val[0], val[2]
221
- }
222
- | expr
273
+ lhs1, _, (lhs2, line), (id, _), rhs = val
223
274
 
224
- command_asgn: lhs tEQL command_call
275
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
276
+ }
277
+ | backref tOP_ASGN command_rhs
225
278
  {
226
- result = new_assign val[0], val[2]
279
+ self.backref_assign_error val[0]
227
280
  }
228
- | lhs tEQL command_asgn
281
+
282
+ command_rhs: command_call =tOP_ASGN
229
283
  {
230
- result = new_assign val[0], val[2]
284
+ expr, = val
285
+ result = value_expr expr
231
286
  }
287
+ | command_asgn
232
288
 
233
289
  expr: command_call
234
290
  | expr kAND expr
235
291
  {
236
- result = logical_op :and, val[0], val[2]
292
+ lhs, _, rhs = val
293
+ result = logical_op :and, lhs, rhs
237
294
  }
238
295
  | expr kOR expr
239
296
  {
240
- result = logical_op :or, val[0], val[2]
297
+ lhs, _, rhs = val
298
+ result = logical_op :or, lhs, rhs
241
299
  }
242
300
  | kNOT opt_nl expr
243
301
  {
244
- result = s(:call, val[2], :"!")
302
+ (_, line), _, expr = val
303
+ result = new_call(expr, :"!").line line
304
+ # REFACTOR: call_uni_op
245
305
  }
246
306
  | tBANG command_call
247
307
  {
248
- result = s(:call, val[1], :"!")
308
+ _, cmd = val
309
+ result = new_call(cmd, :"!").line cmd.line
310
+ # TODO: fix line number to tBANG... but causes BAD shift/reduce conflict
311
+ # REFACTOR: call_uni_op -- see parse26.y
249
312
  }
250
- | arg
313
+ | arg =tLBRACE_ARG
251
314
 
252
315
  expr_value: expr
253
316
  {
254
317
  result = value_expr(val[0])
255
318
  }
256
319
 
320
+ expr_value_do: {
321
+ lexer.cond.push true
322
+ }
323
+ expr_value do
324
+ {
325
+ lexer.cond.pop
326
+ }
327
+ {
328
+ _, expr, _, _ = val
329
+ result = expr
330
+ }
331
+
257
332
  command_call: command
258
333
  | block_command
259
334
 
260
335
  block_command: block_call
261
- | block_call dot_or_colon operation2 command_args
336
+ | block_call call_op2 operation2 command_args
262
337
  {
263
- result = new_call val[0], val[2].to_sym, val[3]
338
+ blk, _, (msg, _line), args = val
339
+ result = new_call(blk, msg.to_sym, args).line blk.line
264
340
  }
265
341
 
266
342
  cmd_brace_block: tLBRACE_ARG
267
343
  {
268
- self.env.extend(:dynamic)
344
+ # self.env.extend(:dynamic)
269
345
  result = self.lexer.lineno
270
346
  }
271
- opt_block_param
272
- {
273
- result = nil # self.env.dynamic.keys
274
- }
275
- compstmt tRCURLY
347
+ brace_body tRCURLY
276
348
  {
277
- result = new_iter nil, val[2], val[4]
278
- result.line = val[1]
349
+ _, line, body, _ = val
279
350
 
280
- self.env.unextend
351
+ result = body
352
+ result.line line
353
+
354
+ # self.env.unextend
281
355
  }
282
356
 
283
357
  fcall: operation
284
358
  {
285
- result = new_call nil, val[0].to_sym
359
+ (msg, line), = val
360
+ result = new_call(nil, msg.to_sym).line line
286
361
  }
287
362
 
288
363
  command: fcall command_args =tLOWEST
289
364
  {
290
- result = val[0].concat val[1].sexp_body # REFACTOR pattern
365
+ call, args = val
366
+ result = call.concat args.sexp_body
291
367
  }
292
368
  | fcall command_args cmd_brace_block
293
369
  {
294
- result = val[0].concat val[1].sexp_body
295
- if val[2] then
296
- block_dup_check result, val[2]
370
+ call, args, block = val
371
+
372
+ result = call.concat args.sexp_body
297
373
 
298
- result, operation = val[2], result
374
+ if block then
375
+ block_dup_check result, block
376
+
377
+ result, operation = block, result
299
378
  result.insert 1, operation
300
379
  end
301
380
  }
302
381
  | primary_value call_op operation2 command_args =tLOWEST
303
382
  {
304
- result = new_call val[0], val[2].to_sym, val[3], val[1]
383
+ lhs, callop, (op, _), args = val
384
+
385
+ result = new_call lhs, op.to_sym, args, callop
386
+ result.line lhs.line
305
387
  }
306
388
  | primary_value call_op operation2 command_args cmd_brace_block
307
389
  {
308
- recv, _, msg, args, block = val
390
+ recv, _, (msg, _line), args, block = val
309
391
  call = new_call recv, msg.to_sym, args, val[1]
310
392
 
311
393
  block_dup_check call, block
@@ -315,11 +397,14 @@ rule
315
397
  }
316
398
  | primary_value tCOLON2 operation2 command_args =tLOWEST
317
399
  {
318
- result = new_call val[0], val[2].to_sym, val[3]
400
+ lhs, _, (id, line), args = val
401
+
402
+ result = new_call lhs, id.to_sym, args
403
+ result.line line
319
404
  }
320
405
  | primary_value tCOLON2 operation2 command_args cmd_brace_block
321
406
  {
322
- recv, _, msg, args, block = val
407
+ recv, _, (msg, _line), args, block = val
323
408
  call = new_call recv, msg.to_sym, args
324
409
 
325
410
  block_dup_check call, block
@@ -333,17 +418,19 @@ rule
333
418
  }
334
419
  | kYIELD command_args
335
420
  {
336
- result = new_yield val[1]
421
+ (_, line), args = val
422
+ result = new_yield args
423
+ result.line line # TODO: push to new_yield
337
424
  }
338
- | kRETURN call_args
425
+ | k_return call_args
339
426
  {
340
427
  line = val[0].last
341
428
  result = s(:return, ret_args(val[1])).line(line)
342
429
  }
343
430
  | kBREAK call_args
344
431
  {
345
- line = val[0].last
346
- result = s(:break, ret_args(val[1])).line(line)
432
+ (_, line), args = val
433
+ result = s(:break, ret_args(args)).line line
347
434
  }
348
435
  | kNEXT call_args
349
436
  {
@@ -360,56 +447,79 @@ rule
360
447
  mlhs_inner: mlhs_basic
361
448
  | tLPAREN mlhs_inner rparen
362
449
  {
363
- result = s(:masgn, s(:array, val[1]))
450
+ _, arg, _ = val
451
+ l = arg.line
452
+
453
+ result = s(:masgn, s(:array, arg).line(l)).line l
364
454
  }
365
455
 
366
456
  mlhs_basic: mlhs_head
367
457
  {
368
- result = s(:masgn, val[0])
458
+ head, = val
459
+ result = s(:masgn, head).line head.line
369
460
  }
370
461
  | mlhs_head mlhs_item
371
462
  {
372
- result = s(:masgn, val[0] << val[1].compact)
463
+ lhs, rhs = val
464
+ result = s(:masgn, lhs << rhs.compact).line lhs.line
373
465
  }
374
466
  | mlhs_head tSTAR mlhs_node
375
467
  {
376
- result = s(:masgn, val[0] << s(:splat, val[2]))
468
+ head, _, tail = val
469
+ head << s(:splat, tail).line(tail.line)
470
+ result = s(:masgn, head).line head.line
377
471
  }
378
472
  | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
379
473
  {
380
474
  ary1, _, splat, _, ary2 = val
381
475
 
382
- result = list_append ary1, s(:splat, splat)
476
+ result = list_append ary1, s(:splat, splat).line(splat.line)
383
477
  result.concat ary2.sexp_body
384
- result = s(:masgn, result)
478
+ result = s(:masgn, result).line result.line
385
479
  }
386
480
  | mlhs_head tSTAR
387
481
  {
388
- result = s(:masgn, val[0] << s(:splat))
482
+ head, _ = val
483
+ l = head.line
484
+ result = s(:masgn, head << s(:splat).line(l)).line l
389
485
  }
390
486
  | mlhs_head tSTAR tCOMMA mlhs_post
391
487
  {
392
- ary = list_append val[0], s(:splat)
393
- ary.concat val[3].sexp_body
394
- result = s(:masgn, ary)
488
+ head, _, _, post = val
489
+ ary = list_append head, s(:splat).line(head.line)
490
+ ary.concat post.sexp_body
491
+ result = s(:masgn, ary).line ary.line
395
492
  }
396
493
  | tSTAR mlhs_node
397
494
  {
398
- result = s(:masgn, s(:array, s(:splat, val[1])))
495
+ _, node = val
496
+ l = node.line
497
+ splat = s(:splat, node).line l
498
+ ary = s(:array, splat).line l
499
+ result = s(:masgn, ary).line l
399
500
  }
400
501
  | tSTAR mlhs_node tCOMMA mlhs_post
401
502
  {
402
- ary = s(:array, s(:splat, val[1]))
403
- ary.concat val[3].sexp_body
404
- result = s(:masgn, ary)
503
+ _, node, _, post = val
504
+
505
+ splat = s(:splat, node).line node.line
506
+ ary = s(:array, splat).line splat.line
507
+ ary.concat post.sexp_body
508
+ result = s(:masgn, ary).line ary.line
405
509
  }
406
510
  | tSTAR
407
511
  {
408
- result = s(:masgn, s(:array, s(:splat)))
512
+ l = lexer.lineno
513
+ result = s(:masgn, s(:array, s(:splat).line(l)).line(l)).line l
409
514
  }
410
515
  | tSTAR tCOMMA mlhs_post
411
516
  {
412
- result = s(:masgn, s(:array, s(:splat), *val[2].sexp_body))
517
+ _, _, post = val
518
+ l = post.line
519
+
520
+ splat = s(:splat).line l
521
+ ary = s(:array, splat, *post.sexp_body).line l
522
+ result = s(:masgn, ary).line l
413
523
  }
414
524
 
415
525
  mlhs_item: mlhs_node
@@ -420,7 +530,8 @@ rule
420
530
 
421
531
  mlhs_head: mlhs_item tCOMMA
422
532
  {
423
- result = s(:array, val[0])
533
+ lhs, _ = val
534
+ result = s(:array, lhs).line lhs.line
424
535
  }
425
536
  | mlhs_head mlhs_item tCOMMA
426
537
  {
@@ -429,7 +540,8 @@ rule
429
540
 
430
541
  mlhs_post: mlhs_item
431
542
  {
432
- result = s(:array, val[0])
543
+ item, = val
544
+ result = s(:array, item).line item.line
433
545
  }
434
546
  | mlhs_post tCOMMA mlhs_item
435
547
  {
@@ -450,81 +562,111 @@ rule
450
562
  }
451
563
  | primary_value call_op tIDENTIFIER
452
564
  {
453
- result = new_attrasgn val[0], val[2], val[1]
565
+ lhs, call_op, (id, _line) = val
566
+
567
+ result = new_attrasgn lhs, id, call_op
454
568
  }
455
569
  | primary_value tCOLON2 tIDENTIFIER
456
570
  {
457
- result = s(:attrasgn, val[0], :"#{val[2]}=")
571
+ recv, _, (id, _line) = val
572
+ result = new_attrasgn recv, id
458
573
  }
459
574
  | primary_value call_op tCONSTANT
460
575
  {
461
- result = new_attrasgn val[0], val[2], val[1]
576
+ lhs, call_op, (id, _line) = val
577
+
578
+ result = new_attrasgn lhs, id, call_op
462
579
  }
463
580
  | primary_value tCOLON2 tCONSTANT
464
581
  {
465
582
  if (self.in_def || self.in_single > 0) then
466
- debug20 7
583
+ debug 14
467
584
  yyerror "dynamic constant assignment"
468
585
  end
469
586
 
470
- result = s(:const, s(:colon2, val[0], val[2].to_sym), nil)
587
+ expr, _, (id, _line) = val
588
+ l = expr.line
589
+
590
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l), nil).line l
471
591
  }
472
592
  | tCOLON3 tCONSTANT
473
593
  {
474
594
  if (self.in_def || self.in_single > 0) then
475
- debug20 8
595
+ debug 15
476
596
  yyerror "dynamic constant assignment"
477
597
  end
478
598
 
479
- result = s(:const, nil, s(:colon3, val[1].to_sym))
599
+ _, (id, l) = val
600
+
601
+ result = s(:const, nil, s(:colon3, id.to_sym).line(l)).line l
480
602
  }
481
603
  | backref
482
604
  {
483
- self.backref_assign_error val[0]
605
+ ref, = val
606
+
607
+ self.backref_assign_error ref
484
608
  }
485
609
 
486
610
  lhs: user_variable
487
611
  {
488
- result = self.assignable val[0]
612
+ var, = val
613
+
614
+ result = self.assignable var
489
615
  }
490
616
  | keyword_variable
491
617
  {
492
- result = self.assignable val[0]
493
- debug20 9, val, result
618
+ var, = val
619
+
620
+ result = self.assignable var
621
+
622
+ debug 16
494
623
  }
495
624
  | primary_value tLBRACK2 opt_call_args rbracket
496
625
  {
497
- result = self.aryset val[0], val[2]
626
+ lhs, _, args, _ = val
627
+
628
+ result = self.aryset lhs, args
498
629
  }
499
630
  | primary_value call_op tIDENTIFIER # REFACTOR
500
631
  {
501
- result = new_attrasgn val[0], val[2], val[1]
632
+ lhs, op, (id, _line) = val
633
+
634
+ result = new_attrasgn lhs, id, op
502
635
  }
503
636
  | primary_value tCOLON2 tIDENTIFIER
504
637
  {
505
- result = s(:attrasgn, val[0], :"#{val[2]}=")
638
+ lhs, _, (id, _line) = val
639
+
640
+ result = new_attrasgn lhs, id
506
641
  }
507
642
  | primary_value call_op tCONSTANT # REFACTOR?
508
643
  {
509
- result = new_attrasgn val[0], val[2], val[1]
644
+ lhs, call_op, (id, _line) = val
645
+
646
+ result = new_attrasgn lhs, id, call_op
510
647
  }
511
648
  | primary_value tCOLON2 tCONSTANT
512
649
  {
650
+ expr, _, (id, _line) = val
651
+
513
652
  if (self.in_def || self.in_single > 0) then
514
- debug20 10
653
+ debug 17
515
654
  yyerror "dynamic constant assignment"
516
655
  end
517
656
 
518
- result = s(:const, s(:colon2, val[0], val[2].to_sym))
657
+ l = expr.line
658
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l)).line l
519
659
  }
520
660
  | tCOLON3 tCONSTANT
521
661
  {
662
+ _, (id, l) = val
663
+
522
664
  if (self.in_def || self.in_single > 0) then
523
- debug20 11
665
+ debug 18
524
666
  yyerror "dynamic constant assignment"
525
667
  end
526
668
 
527
- result = s(:const, s(:colon3, val[1].to_sym))
669
+ result = s(:const, s(:colon3, id.to_sym).line(l)).line l
528
670
  }
529
671
  | backref
530
672
  {
@@ -539,37 +681,37 @@ rule
539
681
 
540
682
  cpath: tCOLON3 cname
541
683
  {
542
- result = s(:colon3, val[1].to_sym)
684
+ _, (name, line) = val
685
+ result = s(:colon3, name.to_sym).line line
543
686
  }
544
687
  | cname
545
688
  {
546
- result = val[0].to_sym
689
+ (id, line), = val
690
+ result = [id.to_sym, line] # TODO: sexp?
547
691
  }
548
692
  | primary_value tCOLON2 cname
549
693
  {
550
- result = s(:colon2, val[0], val[2].to_sym)
694
+ pval, _, (name, _line) = val
695
+
696
+ result = s(:colon2, pval, name.to_sym)
697
+ result.line pval.line
551
698
  }
552
699
 
553
700
  fname: tIDENTIFIER | tCONSTANT | tFID
554
701
  | op
555
702
  {
556
- lexer.lex_state = :expr_end
557
- result = val[0]
703
+ lexer.lex_state = EXPR_END
558
704
  }
559
705
 
560
706
  | reswords
561
- {
562
- lexer.lex_state = :expr_end
563
- result = val[0]
564
- }
565
-
566
- fsym: fname | symbol
567
707
 
568
- fitem: fsym
708
+ fitem: fname
569
709
  {
570
- result = s(:lit, val[0].to_sym)
710
+ (id, line), = val
711
+
712
+ result = s(:lit, id.to_sym).line line
571
713
  }
572
- | dsym
714
+ | symbol
573
715
 
574
716
  undef_list: fitem
575
717
  {
@@ -578,7 +720,7 @@ rule
578
720
  |
579
721
  undef_list tCOMMA
580
722
  {
581
- lexer.lex_state = :expr_fname
723
+ lexer.lex_state = EXPR_FNAME
582
724
  }
583
725
  fitem
584
726
  {
@@ -601,70 +743,72 @@ rule
601
743
  | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
602
744
  | kUNTIL
603
745
 
604
- arg: lhs tEQL arg
746
+ arg: lhs tEQL arg_rhs
605
747
  {
606
748
  result = new_assign val[0], val[2]
607
749
  }
608
- | lhs tEQL arg kRESCUE_MOD arg
609
- {
610
- result = new_assign val[0], s(:rescue, val[2], new_resbody(s(:array), val[4]))
611
- }
612
- | var_lhs tOP_ASGN arg
750
+ | var_lhs tOP_ASGN arg_rhs
613
751
  {
614
752
  result = new_op_asgn val
615
753
  }
616
- | var_lhs tOP_ASGN arg kRESCUE_MOD arg
754
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg_rhs
617
755
  {
618
- result = new_op_asgn val
619
- result = s(:rescue, result, new_resbody(s(:array), val[4]))
756
+ result = new_op_asgn1 val
620
757
  }
621
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
622
- {
623
- val[2].sexp_type = :arglist if val[2]
624
- result = s(:op_asgn1, val[0], val[2], val[4].to_sym, val[5])
625
- }
626
- | primary_value call_op tIDENTIFIER tOP_ASGN arg
758
+ | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
627
759
  {
628
760
  result = new_op_asgn2 val
629
761
  }
630
- | primary_value call_op tCONSTANT tOP_ASGN arg
762
+ | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
631
763
  {
632
764
  result = new_op_asgn2 val
633
765
  }
634
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
766
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
635
767
  {
636
- result = s(:op_asgn, val[0], val[4], val[2].to_sym, val[3].to_sym)
768
+ lhs, _, (id, _line), (op, _), rhs = val
769
+
770
+ result = s(:op_asgn, lhs, rhs, id.to_sym, op.to_sym).line lhs.line
637
771
  }
638
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
772
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
639
773
  {
640
- yyerror "constant re-assignment"
774
+ lhs1, _, (lhs2, _line), op, rhs = val
775
+
776
+ lhs = s(:colon2, lhs1, lhs2.to_sym).line lhs1.line
777
+ result = new_const_op_asgn [lhs, op, rhs]
641
778
  }
642
- | tCOLON3 tCONSTANT tOP_ASGN arg
779
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
643
780
  {
644
- yyerror "constant re-assignment"
781
+ _, (lhs, line), op, rhs = val
782
+
783
+ lhs = s(:colon3, lhs.to_sym).line line
784
+ result = new_const_op_asgn [lhs, op, rhs]
645
785
  }
646
- | backref tOP_ASGN arg
786
+ | backref tOP_ASGN arg_rhs
647
787
  {
648
- self.backref_assign_error val[0]
788
+ # TODO: lhs = var_field val[0]
789
+ asgn = new_op_asgn val
790
+ result = self.backref_assign_error asgn
649
791
  }
650
792
  | arg tDOT2 arg
651
793
  {
652
794
  v1, v2 = val[0], val[2]
653
- if v1.node_type == :lit and v2.node_type == :lit and Integer === v1.last and Integer === v2.last then
654
- result = s(:lit, (v1.last)..(v2.last))
795
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
796
+ result = s(:lit, (v1.last)..(v2.last)).line v1.line
655
797
  else
656
- result = s(:dot2, v1, v2)
798
+ result = s(:dot2, v1, v2).line v1.line
657
799
  end
658
800
  }
659
801
  | arg tDOT3 arg
660
802
  {
661
803
  v1, v2 = val[0], val[2]
662
- if v1.node_type == :lit and v2.node_type == :lit and Integer === v1.last and Integer === v2.last then
663
- result = s(:lit, (v1.last)...(v2.last))
804
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
805
+ result = s(:lit, (v1.last)...(v2.last)).line v1.line
664
806
  else
665
- result = s(:dot3, v1, v2)
807
+ result = s(:dot3, v1, v2).line v1.line
666
808
  end
667
809
  }
810
+
811
+
668
812
  | arg tPLUS arg
669
813
  {
670
814
  result = new_call val[0], :+, argl(val[2])
@@ -691,7 +835,10 @@ rule
691
835
  }
692
836
  | tUMINUS_NUM simple_numeric tPOW arg
693
837
  {
694
- result = new_call(new_call(s(:lit, val[1]), :"**", argl(val[3])), :"-@")
838
+ _, (num, line), _, arg = val
839
+ lit = s(:lit, num).line line
840
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
841
+
695
842
  }
696
843
  | tUPLUS arg
697
844
  {
@@ -717,22 +864,7 @@ rule
717
864
  {
718
865
  result = new_call val[0], :"<=>", argl(val[2])
719
866
  }
720
- | arg tGT arg
721
- {
722
- result = new_call val[0], :">", argl(val[2])
723
- }
724
- | arg tGEQ arg
725
- {
726
- result = new_call val[0], :">=", argl(val[2])
727
- }
728
- | arg tLT arg
729
- {
730
- result = new_call val[0], :"<", argl(val[2])
731
- }
732
- | arg tLEQ arg
733
- {
734
- result = new_call val[0], :"<=", argl(val[2])
735
- }
867
+ | rel_expr =tCMP
736
868
  | arg tEQ arg
737
869
  {
738
870
  result = new_call val[0], :"==", argl(val[2])
@@ -747,15 +879,19 @@ rule
747
879
  }
748
880
  | arg tMATCH arg
749
881
  {
750
- result = new_match val[0], val[2]
882
+ lhs, _, rhs = val
883
+ result = new_match lhs, rhs
751
884
  }
752
885
  | arg tNMATCH arg
753
886
  {
754
- result = s(:not, new_match(val[0], val[2]))
887
+ lhs, _, rhs = val
888
+ result = s(:not, new_match(lhs, rhs)).line lhs.line
755
889
  }
756
890
  | tBANG arg
757
891
  {
758
- result = new_call val[1], :"!"
892
+ _, arg = val
893
+ result = new_call arg, :"!"
894
+ result.line arg.line
759
895
  }
760
896
  | tTILDE arg
761
897
  {
@@ -783,14 +919,33 @@ rule
783
919
  }
784
920
  | kDEFINED opt_nl arg
785
921
  {
786
- result = s(:defined, val[2])
922
+ (_, line), _, arg = val
923
+ result = s(:defined, arg).line line
787
924
  }
788
925
  | arg tEH arg opt_nl tCOLON arg
789
926
  {
790
- result = s(:if, val[0], val[2], val[5])
927
+ c, _, t, _, _, f = val
928
+ result = s(:if, c, t, f).line c.line
791
929
  }
792
930
  | primary
793
931
 
932
+ relop: tGT
933
+ | tLT
934
+ | tGEQ
935
+ | tLEQ
936
+
937
+ rel_expr: arg relop arg =tGT
938
+ {
939
+ lhs, (op, _), rhs = val
940
+ result = new_call lhs, op.to_sym, argl(rhs)
941
+ }
942
+ | rel_expr relop arg =tGT
943
+ {
944
+ lhs, (op, _), rhs = val
945
+ warn "comparison '%s' after comparison", op
946
+ result = new_call lhs, op.to_sym, argl(rhs)
947
+ }
948
+
794
949
  arg_value: arg
795
950
  {
796
951
  result = value_expr(val[0])
@@ -810,22 +965,28 @@ rule
810
965
  result = args [array_to_hash(val[0])]
811
966
  }
812
967
 
968
+ arg_rhs: arg =tOP_ASGN
969
+ | arg kRESCUE_MOD arg
970
+ {
971
+ body, (_, line), resbody = val
972
+ body = value_expr body
973
+ resbody = remove_begin resbody
974
+
975
+ ary = s(:array).line line
976
+ result = new_rescue(body, new_resbody(ary, resbody))
977
+ }
978
+
813
979
  paren_args: tLPAREN2 opt_call_args rparen
814
980
  {
815
- result = val[1]
981
+ _, args, _ = val
982
+ result = args
816
983
  }
817
984
 
818
985
  opt_paren_args: none
819
986
  | paren_args
820
987
 
821
988
  opt_call_args: none
822
- {
823
- result = val[0]
824
- }
825
989
  | call_args
826
- {
827
- result = val[0]
828
- }
829
990
  | args tCOMMA
830
991
  {
831
992
  result = args val
@@ -847,17 +1008,14 @@ rule
847
1008
  | args opt_block_arg
848
1009
  {
849
1010
  result = call_args val
850
- result = self.arg_blk_pass val[0], val[1]
851
1011
  }
852
1012
  | assocs opt_block_arg
853
1013
  {
854
- result = call_args [array_to_hash(val[0])]
855
- result = self.arg_blk_pass result, val[1]
1014
+ result = call_args [array_to_hash(val[0]), val[1]]
856
1015
  }
857
1016
  | args tCOMMA assocs opt_block_arg
858
1017
  {
859
- result = call_args [val[0], array_to_hash(val[2])]
860
- result = self.arg_blk_pass result, val[3]
1018
+ result = call_args [val[0], array_to_hash(val[2]), val[3]]
861
1019
  }
862
1020
  | block_arg
863
1021
  {
@@ -865,18 +1023,45 @@ rule
865
1023
  }
866
1024
 
867
1025
  command_args: {
868
- result = lexer.cmdarg.stack.dup # TODO: smell?
1026
+ # parse26.y line 2200
1027
+
1028
+ # If call_args starts with a open paren '(' or
1029
+ # '[', look-ahead reading of the letters calls
1030
+ # CMDARG_PUSH(0), but the push must be done
1031
+ # after CMDARG_PUSH(1). So this code makes them
1032
+ # consistent by first cancelling the premature
1033
+ # CMDARG_PUSH(0), doing CMDARG_PUSH(1), and
1034
+ # finally redoing CMDARG_PUSH(0).
1035
+
1036
+ result = yychar = self.last_token_type.first
1037
+ lookahead = [:tLPAREN, :tLPAREN_ARG, :tLPAREN2, :tLBRACK, :tLBRACK2].include?(yychar)
1038
+ lexer.cmdarg.pop if lookahead
869
1039
  lexer.cmdarg.push true
1040
+ lexer.cmdarg.push false if lookahead
870
1041
  }
871
1042
  call_args
872
1043
  {
873
- lexer.cmdarg.stack.replace val[0]
874
- result = val[1]
1044
+ yychar, args = val
1045
+
1046
+ # call_args can be followed by tLBRACE_ARG (that
1047
+ # does CMDARG_PUSH(0) in the lexer) but the push
1048
+ # must be done after CMDARG_POP() in the parser.
1049
+ # So this code does CMDARG_POP() to pop 0 pushed
1050
+ # by tLBRACE_ARG, CMDARG_POP() to pop 1 pushed
1051
+ # by command_args, and CMDARG_PUSH(0) to restore
1052
+ # back the flag set by tLBRACE_ARG.
1053
+
1054
+ lookahead = [:tLBRACE_ARG].include?(yychar)
1055
+ lexer.cmdarg.pop if lookahead
1056
+ lexer.cmdarg.pop
1057
+ lexer.cmdarg.push false if lookahead
1058
+ result = args
875
1059
  }
876
1060
 
877
1061
  block_arg: tAMPER arg_value
878
1062
  {
879
- result = s(:block_pass, val[1])
1063
+ _, arg = val
1064
+ result = s(:block_pass, arg).line arg.line
880
1065
  }
881
1066
 
882
1067
  opt_block_arg: tCOMMA block_arg
@@ -887,19 +1072,27 @@ rule
887
1072
 
888
1073
  args: arg_value
889
1074
  {
890
- result = s(:array, val[0])
1075
+ arg, = val
1076
+ lineno = arg.line || lexer.lineno # HACK
1077
+
1078
+ result = s(:array, arg).line lineno
891
1079
  }
892
1080
  | tSTAR arg_value
893
1081
  {
894
- result = s(:array, s(:splat, val[1]))
1082
+ _, arg = val
1083
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
895
1084
  }
896
1085
  | args tCOMMA arg_value
897
1086
  {
898
- result = self.list_append val[0], val[2]
1087
+ args, _, id = val
1088
+ result = self.list_append args, id
899
1089
  }
900
1090
  | args tCOMMA tSTAR arg_value
901
1091
  {
902
- result = self.list_append val[0], s(:splat, val[3])
1092
+ # TODO: the line number from tSTAR has been dropped
1093
+ args, _, _, id = val
1094
+ line = lexer.lineno
1095
+ result = self.list_append args, s(:splat, id).line(line)
903
1096
  }
904
1097
 
905
1098
  mrhs_arg: mrhs
@@ -917,11 +1110,14 @@ rule
917
1110
  }
918
1111
  | args tCOMMA tSTAR arg_value
919
1112
  {
920
- result = self.arg_concat val[0], val[3]
1113
+ # TODO: make all tXXXX terminals include lexer.lineno
1114
+ arg, _, _, splat = val
1115
+ result = self.arg_concat arg, splat
921
1116
  }
922
1117
  | tSTAR arg_value
923
1118
  {
924
- result = s(:splat, val[1])
1119
+ _, arg = val
1120
+ result = s(:splat, arg).line arg.line
925
1121
  }
926
1122
 
927
1123
  primary: literal
@@ -936,58 +1132,66 @@ rule
936
1132
  | backref
937
1133
  | tFID
938
1134
  {
939
- result = new_call nil, val[0].to_sym
1135
+ (msg, line), = val
1136
+ result = new_call nil, msg.to_sym
1137
+ result.line line
940
1138
  }
941
- | kBEGIN
1139
+ | k_begin
942
1140
  {
1141
+ lexer.cmdarg.push false
943
1142
  result = self.lexer.lineno
944
1143
  }
945
- bodystmt kEND
1144
+ bodystmt k_end
946
1145
  {
947
- unless val[2] then
948
- result = s(:nil)
949
- else
950
- result = s(:begin, val[2])
951
- end
952
-
953
- result.line = val[1]
1146
+ lexer.cmdarg.pop
1147
+ result = new_begin val
954
1148
  }
955
- | tLPAREN_ARG rparen
1149
+ | tLPAREN_ARG
956
1150
  {
957
- debug20 13, val, result
1151
+ lexer.lex_state = EXPR_ENDARG
1152
+ result = lexer.lineno
958
1153
  }
959
- | tLPAREN_ARG
1154
+ rparen
960
1155
  {
961
- result = self.lexer.cmdarg.stack.dup
962
- lexer.cmdarg.stack.replace [false] # TODO add api for these
1156
+ _, line, _ = val
1157
+ result = s(:begin).line line
963
1158
  }
964
- expr
1159
+ | tLPAREN_ARG
1160
+ stmt
965
1161
  {
966
- lexer.lex_state = :expr_endarg
1162
+ lexer.lex_state = EXPR_ENDARG
967
1163
  }
968
1164
  rparen
969
1165
  {
970
- warning "(...) interpreted as grouped expression"
971
- lexer.cmdarg.stack.replace val[1]
972
- result = val[2]
1166
+ _, stmt, _, _, = val
1167
+ # warning "(...) interpreted as grouped expression"
1168
+ result = stmt
973
1169
  }
974
1170
  | tLPAREN compstmt tRPAREN
975
1171
  {
976
- result = val[1] || s(:nil)
1172
+ _, stmt, _ = val
1173
+ result = stmt
1174
+ result ||= s(:nil).line lexer.lineno
977
1175
  result.paren = true
978
1176
  }
979
1177
  | primary_value tCOLON2 tCONSTANT
980
1178
  {
981
- result = s(:colon2, val[0], val[2].to_sym)
1179
+ expr, _, (id, _line) = val
1180
+
1181
+ result = s(:colon2, expr, id.to_sym).line expr.line
982
1182
  }
983
1183
  | tCOLON3 tCONSTANT
984
1184
  {
985
- result = s(:colon3, val[1].to_sym)
1185
+ _, (id, line) = val
1186
+
1187
+ result = s(:colon3, id.to_sym).line line
986
1188
  }
987
- | tLBRACK aref_args tRBRACK
1189
+ | tLBRACK { result = lexer.lineno } aref_args tRBRACK
988
1190
  {
989
- result = val[1] || s(:array)
1191
+ _, line, args, _ = val
1192
+ result = args || s(:array)
990
1193
  result.sexp_type = :array # aref_args is :args
1194
+ result.line line
991
1195
  }
992
1196
  | tLBRACE
993
1197
  {
@@ -997,41 +1201,51 @@ rule
997
1201
  {
998
1202
  result = new_hash val
999
1203
  }
1000
- | kRETURN
1204
+ | k_return
1001
1205
  {
1002
- result = s(:return)
1206
+ (_, line), = val
1207
+ result = s(:return).line line
1003
1208
  }
1004
1209
  | kYIELD tLPAREN2 call_args rparen
1005
1210
  {
1006
- result = new_yield val[2]
1211
+ (_, line), _, args, _ = val
1212
+
1213
+ result = new_yield(args).line line
1007
1214
  }
1008
1215
  | kYIELD tLPAREN2 rparen
1009
1216
  {
1010
- result = new_yield
1217
+ (_, line), _, _ = val
1218
+
1219
+ result = new_yield.line line
1011
1220
  }
1012
1221
  | kYIELD
1013
1222
  {
1014
- result = new_yield
1223
+ (_, line), = val
1224
+
1225
+ result = new_yield.line line
1015
1226
  }
1016
1227
  | kDEFINED opt_nl tLPAREN2 expr rparen
1017
1228
  {
1018
- result = s(:defined, val[3])
1229
+ (_, line), _, _, arg, _ = val
1230
+
1231
+ result = s(:defined, arg).line line
1019
1232
  }
1020
1233
  | kNOT tLPAREN2 expr rparen
1021
1234
  {
1022
- result = s(:call, val[2], :"!")
1235
+ _, _, lhs, _ = val
1236
+ result = new_call lhs, :"!"
1023
1237
  }
1024
1238
  | kNOT tLPAREN2 rparen
1025
1239
  {
1026
- debug20 14, val, result
1240
+ debug 20
1027
1241
  }
1028
1242
  | fcall brace_block
1029
1243
  {
1030
- oper, iter = val[0], val[1]
1031
- call = oper # FIX
1244
+ call, iter = val
1245
+
1032
1246
  iter.insert 1, call
1033
1247
  result = iter
1034
- call.line = iter.line
1248
+ # FIX: probably not: call.line = iter.line
1035
1249
  }
1036
1250
  | method_call
1037
1251
  | method_call brace_block
@@ -1041,83 +1255,64 @@ rule
1041
1255
  iter.insert 1, call # FIX
1042
1256
  result = iter
1043
1257
  }
1044
- | tLAMBDA lambda
1258
+ | lambda
1045
1259
  {
1046
- result = val[1] # TODO: fix lineno
1260
+ expr, = val
1261
+ result = expr
1047
1262
  }
1048
- | kIF expr_value then compstmt if_tail kEND
1263
+ | k_if expr_value then compstmt if_tail k_end
1049
1264
  {
1050
- result = new_if val[1], val[3], val[4]
1265
+ _, c, _, t, f, _ = val
1266
+ result = new_if c, t, f
1051
1267
  }
1052
- | kUNLESS expr_value then compstmt opt_else kEND
1268
+ | k_unless expr_value then compstmt opt_else k_end
1053
1269
  {
1054
- result = new_if val[1], val[4], val[3]
1270
+ _, c, _, t, f, _ = val
1271
+ result = new_if c, f, t
1055
1272
  }
1056
- | kWHILE
1273
+ | k_while expr_value_do compstmt k_end
1057
1274
  {
1058
- lexer.cond.push true
1275
+ _, cond, body, _ = val
1276
+ result = new_while body, cond, true
1059
1277
  }
1060
- expr_value do
1061
- {
1062
- lexer.cond.pop
1063
- }
1064
- compstmt kEND
1278
+ | k_until expr_value_do compstmt k_end
1065
1279
  {
1066
- result = new_while val[5], val[2], true
1280
+ _, cond, body, _ = val
1281
+ result = new_until body, cond, true
1067
1282
  }
1068
- | kUNTIL
1069
- {
1070
- lexer.cond.push true
1071
- }
1072
- expr_value do
1073
- {
1074
- lexer.cond.pop
1075
- }
1076
- compstmt kEND
1077
- {
1078
- result = new_until val[5], val[2], true
1079
- }
1080
- | kCASE expr_value opt_terms case_body kEND
1283
+ | k_case expr_value opt_terms case_body k_end
1081
1284
  {
1082
1285
  (_, line), expr, _, body, _ = val
1083
1286
  result = new_case expr, body, line
1084
1287
  }
1085
- | kCASE opt_terms case_body kEND
1288
+ | k_case opt_terms case_body k_end
1086
1289
  {
1087
1290
  (_, line), _, body, _ = val
1088
1291
  result = new_case nil, body, line
1089
1292
  }
1090
- | kFOR for_var kIN
1091
- {
1092
- lexer.cond.push true
1093
- }
1094
- expr_value do
1095
- {
1096
- lexer.cond.pop
1097
- }
1098
- compstmt kEND
1293
+ | k_for for_var kIN expr_value_do compstmt k_end
1099
1294
  {
1100
- result = new_for val[4], val[1], val[7]
1295
+ _, var, _, iter, body, _ = val
1296
+ result = new_for iter, var, body
1101
1297
  }
1102
- | kCLASS
1298
+ | k_class
1103
1299
  {
1104
1300
  result = self.lexer.lineno
1105
1301
  }
1106
1302
  cpath superclass
1107
1303
  {
1108
- self.comments.push self.lexer.comments
1109
1304
  if (self.in_def || self.in_single > 0) then
1110
1305
  yyerror "class definition in method body"
1111
1306
  end
1112
1307
  self.env.extend
1113
1308
  }
1114
- bodystmt kEND
1309
+ bodystmt k_end
1115
1310
  {
1116
1311
  result = new_class val
1117
1312
  self.env.unextend
1118
- self.lexer.comments # we don't care about comments in the body
1313
+ self.lexer.ignore_body_comments
1119
1314
  }
1120
- | kCLASS tLSHFT
1315
+ | k_class tLSHFT
1121
1316
  {
1122
1317
  result = self.lexer.lineno
1123
1318
  }
@@ -1132,92 +1327,108 @@ rule
1132
1327
  self.in_single = 0
1133
1328
  self.env.extend
1134
1329
  }
1135
- bodystmt kEND
1330
+ bodystmt k_end
1136
1331
  {
1137
1332
  result = new_sclass val
1138
1333
  self.env.unextend
1139
- self.lexer.comments # we don't care about comments in the body
1334
+ self.lexer.ignore_body_comments
1140
1335
  }
1141
- | kMODULE
1336
+ | k_module
1142
1337
  {
1143
1338
  result = self.lexer.lineno
1144
1339
  }
1145
1340
  cpath
1146
1341
  {
1147
- self.comments.push self.lexer.comments
1148
1342
  yyerror "module definition in method body" if
1149
1343
  self.in_def or self.in_single > 0
1150
1344
 
1151
1345
  self.env.extend
1152
1346
  }
1153
- bodystmt kEND
1347
+ bodystmt k_end
1154
1348
  {
1155
1349
  result = new_module val
1156
1350
  self.env.unextend
1157
- self.lexer.comments # we don't care about comments in the body
1351
+ self.lexer.ignore_body_comments
1158
1352
  }
1159
- | kDEF fname
1353
+ | k_def fname
1160
1354
  {
1161
- result = [self.in_def, self.lexer.cmdarg.stack.dup]
1355
+ result = self.in_def
1162
1356
 
1163
- self.comments.push self.lexer.comments
1164
- self.in_def = true
1357
+ self.in_def = true # group = local_push
1165
1358
  self.env.extend
1166
- # TODO: local->cmdargs = cmdarg_stack;
1167
- # TODO: port local_push_gen and local_pop_gen
1168
- lexer.cmdarg.stack.replace [false]
1359
+ lexer.cmdarg.push false
1360
+ lexer.cond.push false
1169
1361
  }
1170
- f_arglist bodystmt kEND
1362
+ f_arglist bodystmt k_end
1171
1363
  {
1172
- in_def, cmdarg = val[2]
1364
+ result, in_def = new_defn val
1173
1365
 
1174
- result = new_defn val
1175
-
1176
- lexer.cmdarg.stack.replace cmdarg
1366
+ lexer.cond.pop # group = local_pop
1367
+ lexer.cmdarg.pop
1177
1368
  self.env.unextend
1178
1369
  self.in_def = in_def
1179
- self.lexer.comments # we don't care about comments in the body
1370
+
1371
+ self.lexer.ignore_body_comments
1180
1372
  }
1181
- | kDEF singleton dot_or_colon
1373
+ | k_def singleton dot_or_colon
1182
1374
  {
1183
- self.comments.push self.lexer.comments
1184
- lexer.lex_state = :expr_fname
1375
+ lexer.lex_state = EXPR_FNAME
1185
1376
  }
1186
1377
  fname
1187
1378
  {
1188
- self.in_single += 1
1379
+ result = self.in_def
1380
+
1381
+ self.in_single += 1 # TODO: remove?
1382
+
1383
+ self.in_def = true # local_push
1189
1384
  self.env.extend
1190
- lexer.lex_state = :expr_endfn # force for args
1191
- result = [lexer.lineno, self.lexer.cmdarg.stack.dup]
1192
- lexer.cmdarg.stack.replace [false]
1385
+ lexer.cmdarg.push false
1386
+ lexer.cond.push false
1387
+
1388
+ lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
1193
1389
  }
1194
- f_arglist bodystmt kEND
1390
+ f_arglist bodystmt k_end
1195
1391
  {
1196
- line, cmdarg = val[5]
1197
- result = new_defs val
1198
- result[3].line line
1199
1392
 
1200
- lexer.cmdarg.stack.replace cmdarg
1393
+ # [kdef, recv, _, _, (name, line), in_def, args, body, kend]
1394
+ # =>
1395
+ # [kdef, recv, (name, line), in_def, args, body, kend]
1396
+
1397
+ val.delete_at 3
1398
+ val.delete_at 2
1399
+
1400
+ result, in_def = new_defs val
1201
1401
 
1402
+ lexer.cond.pop # group = local_pop
1403
+ lexer.cmdarg.pop
1202
1404
  self.env.unextend
1405
+ self.in_def = in_def
1406
+
1203
1407
  self.in_single -= 1
1204
- self.lexer.comments # we don't care about comments in the body
1408
+
1409
+ # TODO: restore cur_arg ? what's cur_arg?
1410
+
1411
+ self.lexer.ignore_body_comments
1205
1412
  }
1206
1413
  | kBREAK
1207
1414
  {
1208
- result = s(:break)
1415
+ (_, line), = val
1416
+ result = s(:break).line line
1209
1417
  }
1210
1418
  | kNEXT
1211
1419
  {
1212
- result = s(:next)
1420
+ (_, line), = val
1421
+ result = s(:next).line line
1213
1422
  }
1214
1423
  | kREDO
1215
1424
  {
1216
- result = s(:redo)
1425
+ (_, line), = val
1426
+ result = s(:redo).line line
1217
1427
  }
1218
1428
  | kRETRY
1219
1429
  {
1220
- result = s(:retry)
1430
+ (_, line), = val
1431
+ result = s(:retry).line line
1221
1432
  }
1222
1433
 
1223
1434
  primary_value: primary
@@ -1234,9 +1445,26 @@ rule
1234
1445
  k_case: kCASE
1235
1446
  k_for: kFOR
1236
1447
  k_class: kCLASS
1448
+ {
1449
+ self.comments.push self.lexer.comments
1450
+ }
1237
1451
  k_module: kMODULE
1452
+ {
1453
+ self.comments.push self.lexer.comments
1454
+ }
1238
1455
  k_def: kDEF
1456
+ {
1457
+ self.comments.push self.lexer.comments
1458
+ }
1459
+ k_do: kDO
1460
+ k_do_block: kDO_BLOCK
1461
+ k_rescue: kRESCUE
1462
+ k_ensure: kENSURE
1463
+ k_when: kWHEN
1464
+ k_else: kELSE
1465
+ k_elsif: kELSIF
1239
1466
  k_end: kEND
1467
+ k_return: kRETURN
1240
1468
 
1241
1469
  then: term
1242
1470
  | kTHEN
@@ -1246,9 +1474,11 @@ rule
1246
1474
  | kDO_COND
1247
1475
 
1248
1476
  if_tail: opt_else
1249
- | kELSIF expr_value then compstmt if_tail
1477
+ | k_elsif expr_value then compstmt if_tail
1250
1478
  {
1251
- result = s(:if, val[1], val[3], val[4])
1479
+ (_, line), c, _, t, rest = val
1480
+
1481
+ result = s(:if, c, t, rest).line line
1252
1482
  }
1253
1483
 
1254
1484
  opt_else: none
@@ -1271,7 +1501,9 @@ rule
1271
1501
 
1272
1502
  f_marg_list: f_marg
1273
1503
  {
1274
- result = s(:array, val[0])
1504
+ sym, = val
1505
+
1506
+ result = s(:array, sym).line lexer.lineno
1275
1507
  }
1276
1508
  | f_marg_list tCOMMA f_marg
1277
1509
  {
@@ -1284,51 +1516,42 @@ rule
1284
1516
 
1285
1517
  result = block_var args
1286
1518
  }
1287
- | f_marg_list tCOMMA tSTAR f_norm_arg
1519
+ | f_marg_list tCOMMA f_rest_marg
1288
1520
  {
1289
- args, _, _, splat = val
1521
+ args, _, rest = val
1290
1522
 
1291
- result = block_var args, "*#{splat}".to_sym
1523
+ result = block_var args, rest
1292
1524
  }
1293
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
1525
+ | f_marg_list tCOMMA f_rest_marg tCOMMA f_marg_list
1294
1526
  {
1295
- args, _, _, splat, _, args2 = val
1527
+ lhs, _, splat, _, rhs = val
1296
1528
 
1297
- result = block_var args, "*#{splat}".to_sym, args2
1529
+ result = block_var lhs, splat, rhs
1298
1530
  }
1299
- | f_marg_list tCOMMA tSTAR
1531
+ | f_rest_marg
1300
1532
  {
1301
- args, _, _ = val
1533
+ rest, = val
1302
1534
 
1303
- result = block_var args, :*
1535
+ result = block_var rest
1304
1536
  }
1305
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
1537
+ | f_rest_marg tCOMMA f_marg_list
1306
1538
  {
1307
- args, _, _, _, args2 = val
1539
+ splat, _, rest = val
1308
1540
 
1309
- result = block_var args, :*, args2
1541
+ result = block_var splat, rest
1310
1542
  }
1311
- | tSTAR f_norm_arg
1312
- {
1313
- _, splat = val
1314
1543
 
1315
- result = block_var :"*#{splat}"
1316
- }
1317
- | tSTAR f_norm_arg tCOMMA f_marg_list
1544
+ f_rest_marg: tSTAR f_norm_arg
1318
1545
  {
1319
- _, splat, _, args = val
1546
+ _, (id, line) = val
1320
1547
 
1321
- result = block_var :"*#{splat}", args
1548
+ result = args ["*#{id}".to_sym]
1549
+ result.line line
1322
1550
  }
1323
1551
  | tSTAR
1324
1552
  {
1325
- result = block_var :*
1326
- }
1327
- | tSTAR tCOMMA f_marg_list
1328
- {
1329
- _, _, args = val
1330
-
1331
- result = block_var :*, args
1553
+ result = args [:*]
1554
+ result.line lexer.lineno # FIX: tSTAR -> line
1332
1555
  }
1333
1556
 
1334
1557
  block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
@@ -1345,7 +1568,9 @@ rule
1345
1568
  }
1346
1569
  | f_block_arg
1347
1570
  {
1348
- result = call_args val
1571
+ (id, line), = val
1572
+ result = call_args [id]
1573
+ result.line line
1349
1574
  }
1350
1575
 
1351
1576
  opt_block_args_tail: tCOMMA block_args_tail
@@ -1376,7 +1601,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1376
1601
  }
1377
1602
  | f_arg tCOMMA
1378
1603
  {
1379
- result = args val
1604
+ result = args(val) << nil
1380
1605
  }
1381
1606
  | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1382
1607
  {
@@ -1417,18 +1642,22 @@ opt_block_args_tail: tCOMMA block_args_tail
1417
1642
 
1418
1643
  opt_block_param: none { result = 0 }
1419
1644
  | block_param_def
1645
+ {
1646
+ self.lexer.command_start = true
1647
+ }
1420
1648
 
1421
1649
  block_param_def: tPIPE opt_bv_decl tPIPE
1422
1650
  {
1651
+ # TODO: current_arg = 0
1423
1652
  result = args val
1424
1653
  }
1425
1654
  | tOROP
1426
1655
  {
1427
- self.lexer.command_start = true
1428
- result = s(:args)
1656
+ result = s(:args).line lexer.lineno
1429
1657
  }
1430
1658
  | tPIPE block_param opt_bv_decl tPIPE
1431
1659
  {
1660
+ # TODO: current_arg = 0
1432
1661
  result = args val
1433
1662
  }
1434
1663
 
@@ -1449,26 +1678,33 @@ opt_block_args_tail: tCOMMA block_args_tail
1449
1678
 
1450
1679
  bvar: tIDENTIFIER
1451
1680
  {
1452
- result = s(:shadow, val[0].to_sym)
1681
+ (id, line), = val
1682
+ result = s(:shadow, id.to_sym).line line
1453
1683
  }
1454
1684
  | f_bad_arg
1455
1685
 
1456
- lambda: {
1686
+ lambda: tLAMBDA
1687
+ {
1457
1688
  self.env.extend :dynamic
1458
- result = self.lexer.lineno
1459
-
1460
- result = lexer.lpar_beg
1689
+ result = [lexer.lineno, lexer.lpar_beg]
1461
1690
  lexer.paren_nest += 1
1462
1691
  lexer.lpar_beg = lexer.paren_nest
1463
1692
  }
1464
- f_larglist lambda_body
1693
+ f_larglist
1694
+ {
1695
+ lexer.cmdarg.push false
1696
+ }
1697
+ lambda_body
1465
1698
  {
1466
- lpar, args, body = val
1699
+ _, (line, lpar), args, _cmdarg, body = val
1467
1700
  lexer.lpar_beg = lpar
1468
1701
 
1469
- call = new_call nil, :lambda
1702
+ lexer.cmdarg.pop
1703
+
1704
+ call = s(:lambda).line line
1470
1705
  result = new_iter call, args, body
1471
- self.env.unextend
1706
+ result.line line
1707
+ self.env.unextend # TODO: dynapush & dynapop
1472
1708
  }
1473
1709
 
1474
1710
  f_larglist: tLPAREN2 f_args opt_bv_decl rparen
@@ -1485,28 +1721,15 @@ opt_block_args_tail: tCOMMA block_args_tail
1485
1721
  {
1486
1722
  result = val[1]
1487
1723
  }
1488
- | kDO_LAMBDA compstmt kEND
1724
+ | kDO_LAMBDA bodystmt kEND
1489
1725
  {
1490
1726
  result = val[1]
1491
1727
  }
1492
1728
 
1493
- do_block: kDO_BLOCK
1494
- {
1495
- self.env.extend :dynamic
1496
- result = self.lexer.lineno
1497
- }
1498
- opt_block_param
1729
+ do_block: k_do_block do_body kEND
1499
1730
  {
1500
- result = nil # self.env.dynamic.keys
1501
- }
1502
- compstmt kEND
1503
- {
1504
- args = val[2]
1505
- body = val[4]
1506
- result = new_iter nil, args, body
1507
- result.line = val[1]
1508
-
1509
- self.env.unextend
1731
+ (_, line), iter, _ = val
1732
+ result = iter.line line
1510
1733
  }
1511
1734
 
1512
1735
  block_call: command do_block
@@ -1515,30 +1738,37 @@ opt_block_args_tail: tCOMMA block_args_tail
1515
1738
  ## if (nd_type($1) == NODE_YIELD) {
1516
1739
  ## compile_error(PARSER_ARG "block given to yield");
1517
1740
 
1741
+ cmd, blk = val
1742
+
1518
1743
  syntax_error "Both block arg and actual block given." if
1519
- val[0].block_pass?
1744
+ cmd.block_pass?
1520
1745
 
1521
- val = invert_block_call val if inverted? val
1746
+ if inverted? val then
1747
+ val = invert_block_call val
1748
+ cmd, blk = val
1749
+ end
1522
1750
 
1523
- result = val[1]
1524
- result.insert 1, val[0]
1751
+ result = blk
1752
+ result.insert 1, cmd
1525
1753
  }
1526
- | block_call dot_or_colon operation2 opt_paren_args
1754
+ | block_call call_op2 operation2 opt_paren_args
1527
1755
  {
1528
- result = new_call val[0], val[2].to_sym, val[3]
1756
+ lhs, _, (id, _line), args = val
1757
+
1758
+ result = new_call lhs, id.to_sym, args
1529
1759
  }
1530
- | block_call dot_or_colon operation2 opt_paren_args brace_block
1760
+ | block_call call_op2 operation2 opt_paren_args brace_block
1531
1761
  {
1532
- iter1, _, name, args, iter2 = val
1762
+ iter1, _, (name, _line), args, iter2 = val
1533
1763
 
1534
1764
  call = new_call iter1, name.to_sym, args
1535
1765
  iter2.insert 1, call
1536
1766
 
1537
1767
  result = iter2
1538
1768
  }
1539
- | block_call dot_or_colon operation2 command_args do_block
1769
+ | block_call call_op2 operation2 command_args do_block
1540
1770
  {
1541
- iter1, _, name, args, iter2 = val
1771
+ iter1, _, (name, _line), args, iter2 = val
1542
1772
 
1543
1773
  call = new_call iter1, name.to_sym, args
1544
1774
  iter2.insert 1, call
@@ -1546,26 +1776,29 @@ opt_block_args_tail: tCOMMA block_args_tail
1546
1776
  result = iter2
1547
1777
  }
1548
1778
 
1549
- method_call: fcall
1779
+ method_call: fcall paren_args
1550
1780
  {
1551
- result = self.lexer.lineno
1552
- }
1553
- paren_args
1554
- {
1555
- args = self.call_args val[2..-1]
1556
- result = val[0].concat args.sexp_body
1781
+ call, args = val
1782
+
1783
+ result = call.concat args.sexp_body if args
1557
1784
  }
1558
1785
  | primary_value call_op operation2 opt_paren_args
1559
1786
  {
1560
- result = new_call val[0], val[2].to_sym, val[3], val[1]
1787
+ recv, call_op, (op, _line), args = val
1788
+
1789
+ result = new_call recv, op.to_sym, args, call_op
1561
1790
  }
1562
1791
  | primary_value tCOLON2 operation2 paren_args
1563
1792
  {
1564
- result = new_call val[0], val[2].to_sym, val[3]
1793
+ recv, _, (op, _line), args = val
1794
+
1795
+ result = new_call recv, op.to_sym, args
1565
1796
  }
1566
1797
  | primary_value tCOLON2 operation3
1567
1798
  {
1568
- result = new_call val[0], val[2].to_sym
1799
+ lhs, _, (id, _line) = val
1800
+
1801
+ result = new_call lhs, id.to_sym
1569
1802
  }
1570
1803
  | primary_value call_op paren_args
1571
1804
  {
@@ -1581,7 +1814,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1581
1814
  }
1582
1815
  | kSUPER
1583
1816
  {
1584
- result = s(:zsuper)
1817
+ result = s(:zsuper).line lexer.lineno
1585
1818
  }
1586
1819
  | primary_value tLBRACK2 opt_call_args rbracket
1587
1820
  {
@@ -1593,57 +1826,98 @@ opt_block_args_tail: tCOMMA block_args_tail
1593
1826
  self.env.extend :dynamic
1594
1827
  result = self.lexer.lineno
1595
1828
  }
1596
- opt_block_param
1597
- {
1598
- result = nil # self.env.dynamic.keys
1599
- }
1600
- compstmt tRCURLY
1829
+ brace_body tRCURLY
1601
1830
  {
1602
- _, line, args, _, body, _ = val
1831
+ _, line, body, _ = val
1603
1832
 
1604
- result = new_iter nil, args, body
1605
- result.line = line
1833
+ result = body
1834
+ result.line line
1606
1835
 
1607
1836
  self.env.unextend
1608
1837
  }
1609
- | kDO
1838
+ | k_do
1610
1839
  {
1611
1840
  self.env.extend :dynamic
1612
1841
  result = self.lexer.lineno
1613
1842
  }
1614
- opt_block_param
1843
+ do_body kEND
1615
1844
  {
1616
- result = nil # self.env.dynamic.keys
1845
+ _, line, body, _ = val
1846
+
1847
+ result = body
1848
+ result.line line
1849
+
1850
+ self.env.unextend
1617
1851
  }
1618
- compstmt kEND
1852
+
1853
+ brace_body: { self.env.extend :dynamic; result = self.lexer.lineno }
1854
+ { result = lexer.cmdarg.store(false) }
1855
+ opt_block_param compstmt
1619
1856
  {
1620
- _, line, args, _, body, _ = val
1857
+ line, cmdarg, param, cmpstmt = val
1621
1858
 
1622
- result = new_iter nil, args, body
1623
- result.line = line
1859
+ result = new_brace_body param, cmpstmt, line
1860
+ self.env.unextend
1861
+ lexer.cmdarg.restore cmdarg
1862
+ lexer.cmdarg.pop # because of: cmdarg_stack >> 1 ?
1863
+ }
1864
+
1865
+ do_body: { self.env.extend :dynamic; result = self.lexer.lineno }
1866
+ { lexer.cmdarg.push false }
1867
+ opt_block_param
1868
+ compstmt
1869
+ {
1870
+ line, _cmdarg, param, cmpstmt = val
1624
1871
 
1872
+ result = new_do_body param, cmpstmt, line
1873
+ lexer.cmdarg.pop
1625
1874
  self.env.unextend
1626
1875
  }
1627
1876
 
1628
- case_body: kWHEN
1877
+ case_args: arg_value
1878
+ {
1879
+ arg, = val
1880
+
1881
+ result = s(:array, arg).line arg.line
1882
+ }
1883
+ | tSTAR arg_value
1884
+ {
1885
+ _, arg = val
1886
+
1887
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
1888
+ }
1889
+ | case_args tCOMMA arg_value
1890
+ {
1891
+ args, _, id = val
1892
+
1893
+ result = self.list_append args, id
1894
+ }
1895
+ | case_args tCOMMA tSTAR arg_value
1896
+ {
1897
+ args, _, _, id = val
1898
+
1899
+ result = self.list_append args, s(:splat, id).line(id.line)
1900
+ }
1901
+
1902
+ case_body: k_when
1629
1903
  {
1630
1904
  result = self.lexer.lineno
1631
1905
  }
1632
- args then compstmt cases
1906
+ case_args then compstmt cases
1633
1907
  {
1634
1908
  result = new_when(val[2], val[4])
1635
- result.line = val[1]
1909
+ result.line val[1]
1636
1910
  result << val[5] if val[5]
1637
1911
  }
1638
1912
 
1639
1913
  cases: opt_else | case_body
1640
1914
 
1641
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
1915
+ opt_rescue: k_rescue exc_list exc_var then compstmt opt_rescue
1642
1916
  {
1643
1917
  (_, line), klasses, var, _, body, rest = val
1644
1918
 
1645
1919
  klasses ||= s(:array)
1646
- klasses << new_assign(var, s(:gvar, :"$!")) if var
1920
+ klasses << new_assign(var, s(:gvar, :"$!").line(var.line)) if var
1647
1921
  klasses.line line
1648
1922
 
1649
1923
  result = new_resbody(klasses, body)
@@ -1656,7 +1930,8 @@ opt_block_args_tail: tCOMMA block_args_tail
1656
1930
 
1657
1931
  exc_list: arg_value
1658
1932
  {
1659
- result = s(:array, val[0])
1933
+ arg, = val
1934
+ result = s(:array, arg).line arg.line
1660
1935
  }
1661
1936
  | mrhs
1662
1937
  | none
@@ -1667,33 +1942,31 @@ opt_block_args_tail: tCOMMA block_args_tail
1667
1942
  }
1668
1943
  | none
1669
1944
 
1670
- opt_ensure: kENSURE compstmt
1945
+ opt_ensure: k_ensure compstmt
1671
1946
  {
1672
- _, body = val
1947
+ (_, line), body = val
1673
1948
 
1674
- result = body || s(:nil)
1949
+ result = body || s(:nil).line(line)
1675
1950
  }
1676
1951
  | none
1677
1952
 
1678
1953
  literal: numeric
1679
1954
  {
1680
- result = s(:lit, val[0])
1955
+ (lit, line), = val
1956
+ result = s(:lit, lit).line line
1681
1957
  }
1682
1958
  | symbol
1683
- {
1684
- result = s(:lit, val[0])
1685
- }
1686
- | dsym
1687
1959
 
1688
1960
  strings: string
1689
1961
  {
1690
- val[0] = s(:dstr, val[0].value) if val[0].sexp_type == :evstr
1691
- result = val[0]
1962
+ str, = val
1963
+ str = s(:dstr, str.value) if str.sexp_type == :evstr
1964
+ result = str
1692
1965
  }
1693
1966
 
1694
1967
  string: tCHAR
1695
1968
  {
1696
- debug20 23, val, result
1969
+ debug 37
1697
1970
  }
1698
1971
  | string1
1699
1972
  | string string1
@@ -1703,7 +1976,11 @@ opt_block_args_tail: tCOMMA block_args_tail
1703
1976
 
1704
1977
  string1: tSTRING_BEG string_contents tSTRING_END
1705
1978
  {
1706
- result = val[1]
1979
+ (_, line), str, (_, func) = val
1980
+
1981
+ str = dedent str if func =~ RubyLexer::STR_FUNC_DEDENT
1982
+
1983
+ result = str.line line
1707
1984
  }
1708
1985
  | tSTRING
1709
1986
  {
@@ -1712,7 +1989,8 @@ opt_block_args_tail: tCOMMA block_args_tail
1712
1989
 
1713
1990
  xstring: tXSTRING_BEG xstring_contents tSTRING_END
1714
1991
  {
1715
- result = new_xstring val[1]
1992
+ result = new_xstring val
1993
+ # TODO: dedent?!?! SERIOUSLY?!?
1716
1994
  }
1717
1995
 
1718
1996
  regexp: tREGEXP_BEG regexp_contents tREGEXP_END
@@ -1722,11 +2000,15 @@ opt_block_args_tail: tCOMMA block_args_tail
1722
2000
 
1723
2001
  words: tWORDS_BEG tSPACE tSTRING_END
1724
2002
  {
1725
- result = s(:array)
2003
+ (_, line), _, _ = val
2004
+
2005
+ result = s(:array).line line
1726
2006
  }
1727
2007
  | tWORDS_BEG word_list tSTRING_END
1728
2008
  {
1729
- result = val[1]
2009
+ (_, line), list, _ = val
2010
+
2011
+ result = list.line line
1730
2012
  }
1731
2013
 
1732
2014
  word_list: none
@@ -1746,11 +2028,15 @@ opt_block_args_tail: tCOMMA block_args_tail
1746
2028
 
1747
2029
  symbols: tSYMBOLS_BEG tSPACE tSTRING_END
1748
2030
  {
1749
- result = s(:array)
2031
+ (_, line), _, _ = val
2032
+
2033
+ result = s(:array).line line
1750
2034
  }
1751
2035
  | tSYMBOLS_BEG symbol_list tSTRING_END
1752
2036
  {
1753
- result = val[1]
2037
+ (_, line), list, _, = val
2038
+ list.line line
2039
+ result = list
1754
2040
  }
1755
2041
 
1756
2042
  symbol_list: none
@@ -1759,25 +2045,34 @@ opt_block_args_tail: tCOMMA block_args_tail
1759
2045
  }
1760
2046
  | symbol_list word tSPACE
1761
2047
  {
1762
- result = val[0].dup << new_symbol_list_entry(val)
2048
+ list, * = val
2049
+ result = list.dup << new_symbol_list_entry(val)
1763
2050
  }
1764
2051
 
1765
2052
  qwords: tQWORDS_BEG tSPACE tSTRING_END
1766
2053
  {
1767
- result = s(:array)
2054
+ (_, line), _, _ = val
2055
+
2056
+ result = s(:array).line line
1768
2057
  }
1769
2058
  | tQWORDS_BEG qword_list tSTRING_END
1770
2059
  {
1771
- result = val[1]
2060
+ (_, line), list, _ = val
2061
+
2062
+ result = list.line line
1772
2063
  }
1773
2064
 
1774
2065
  qsymbols: tQSYMBOLS_BEG tSPACE tSTRING_END
1775
2066
  {
1776
- result = s(:array)
2067
+ (_, line), _, _ = val
2068
+
2069
+ result = s(:array).line line
1777
2070
  }
1778
2071
  | tQSYMBOLS_BEG qsym_list tSTRING_END
1779
2072
  {
1780
- result = val[1]
2073
+ (_, line), list, _ = val
2074
+
2075
+ result = list.line line
1781
2076
  }
1782
2077
 
1783
2078
  qword_list: none
@@ -1800,11 +2095,13 @@ opt_block_args_tail: tCOMMA block_args_tail
1800
2095
 
1801
2096
  string_contents: none
1802
2097
  {
1803
- result = s(:str, "")
2098
+ line = prev_value_to_lineno _values.last
2099
+ result = s(:str, +"").line line
1804
2100
  }
1805
2101
  | string_contents string_content
1806
2102
  {
1807
- result = literal_concat(val[0], val[1])
2103
+ v1, v2 = val
2104
+ result = literal_concat v1, v2
1808
2105
  }
1809
2106
 
1810
2107
  xstring_contents: none
@@ -1813,7 +2110,8 @@ xstring_contents: none
1813
2110
  }
1814
2111
  | xstring_contents string_content
1815
2112
  {
1816
- result = literal_concat(val[0], val[1])
2113
+ v1, v2 = val
2114
+ result = literal_concat v1, v2
1817
2115
  }
1818
2116
 
1819
2117
  regexp_contents: none
@@ -1822,7 +2120,8 @@ regexp_contents: none
1822
2120
  }
1823
2121
  | regexp_contents string_content
1824
2122
  {
1825
- result = literal_concat(val[0], val[1])
2123
+ v1, v2 = val
2124
+ result = literal_concat v1, v2
1826
2125
  }
1827
2126
 
1828
2127
  string_content: tSTRING_CONTENT
@@ -1834,42 +2133,46 @@ regexp_contents: none
1834
2133
  result = lexer.lex_strterm
1835
2134
 
1836
2135
  lexer.lex_strterm = nil
1837
- lexer.lex_state = :expr_beg # TODO: expr_value ?
2136
+ lexer.lex_state = EXPR_BEG
1838
2137
  }
1839
2138
  string_dvar
1840
2139
  {
1841
- lexer.lex_strterm = val[1]
1842
- result = s(:evstr, val[2])
2140
+ _, strterm, str = val
2141
+ lexer.lex_strterm = strterm
2142
+ result = s(:evstr, str).line str.line
1843
2143
  }
1844
2144
  | tSTRING_DBEG
1845
2145
  {
1846
2146
  result = [lexer.lex_strterm,
1847
2147
  lexer.brace_nest,
1848
2148
  lexer.string_nest, # TODO: remove
1849
- lexer.cond.store,
1850
- lexer.cmdarg.store,
1851
2149
  lexer.lex_state,
2150
+ lexer.lineno,
1852
2151
  ]
1853
2152
 
2153
+ lexer.cmdarg.push false
2154
+ lexer.cond.push false
2155
+
1854
2156
  lexer.lex_strterm = nil
1855
2157
  lexer.brace_nest = 0
1856
2158
  lexer.string_nest = 0
1857
2159
 
1858
- lexer.lex_state = :expr_value
2160
+ lexer.lex_state = EXPR_BEG
1859
2161
  }
1860
- compstmt tRCURLY
2162
+ compstmt
2163
+ tSTRING_DEND
1861
2164
  {
1862
- # TODO: tRCURLY -> tSTRING_END
1863
2165
  _, memo, stmt, _ = val
1864
2166
 
1865
- lex_strterm, brace_nest, string_nest, oldcond, oldcmdarg, oldlex_state = memo
2167
+ lex_strterm, brace_nest, string_nest, oldlex_state, line = memo
2168
+ # TODO: heredoc_indent
1866
2169
 
1867
2170
  lexer.lex_strterm = lex_strterm
1868
2171
  lexer.brace_nest = brace_nest
1869
2172
  lexer.string_nest = string_nest
1870
2173
 
1871
- lexer.cond.restore oldcond
1872
- lexer.cmdarg.restore oldcmdarg
2174
+ lexer.cond.pop
2175
+ lexer.cmdarg.pop
1873
2176
 
1874
2177
  lexer.lex_state = oldlex_state
1875
2178
 
@@ -1879,56 +2182,78 @@ regexp_contents: none
1879
2182
  when :str, :dstr, :evstr then
1880
2183
  result = stmt
1881
2184
  else
1882
- result = s(:evstr, stmt)
2185
+ result = s(:evstr, stmt).line line
1883
2186
  end
1884
2187
  when nil then
1885
- result = s(:evstr)
2188
+ result = s(:evstr).line line
1886
2189
  else
1887
- debug20 25
2190
+ debug 38
1888
2191
  raise "unknown string body: #{stmt.inspect}"
1889
2192
  end
1890
2193
  }
1891
2194
 
1892
- string_dvar: tGVAR { result = s(:gvar, val[0].to_sym) }
1893
- | tIVAR { result = s(:ivar, val[0].to_sym) }
1894
- | tCVAR { result = s(:cvar, val[0].to_sym) }
2195
+ string_dvar: tGVAR
2196
+ {
2197
+ (id, line), = val
2198
+ result = s(:gvar, id.to_sym).line line
2199
+ }
2200
+ | tIVAR
2201
+ {
2202
+ (id, line), = val
2203
+ result = s(:ivar, id.to_sym).line line
2204
+ }
2205
+ | tCVAR
2206
+ {
2207
+ (id, line), = val
2208
+ result = s(:cvar, id.to_sym).line line
2209
+ }
1895
2210
  | backref
1896
2211
 
1897
- symbol: tSYMBEG sym
2212
+ symbol: ssym
2213
+ | dsym
2214
+
2215
+ ssym: tSYMBEG sym
1898
2216
  {
1899
- lexer.lex_state = :expr_end
1900
- result = val[1].to_sym
2217
+ _, (id, line) = val
2218
+
2219
+ lexer.lex_state = EXPR_END
2220
+ result = s(:lit, id.to_sym).line line
1901
2221
  }
1902
2222
  | tSYMBOL
1903
2223
  {
1904
- result = val[0].to_sym
2224
+ (id, line), = val
2225
+
2226
+ lexer.lex_state = EXPR_END
2227
+ result = s(:lit, id.to_sym).line line
1905
2228
  }
1906
2229
 
1907
2230
  sym: fname | tIVAR | tGVAR | tCVAR
1908
2231
 
1909
- dsym: tSYMBEG xstring_contents tSTRING_END
2232
+ dsym: tSYMBEG string_contents tSTRING_END
1910
2233
  {
1911
- lexer.lex_state = :expr_end
1912
- result = val[1]
2234
+ _, result, _ = val
2235
+
2236
+ lexer.lex_state = EXPR_END
1913
2237
 
1914
- result ||= s(:str, "")
2238
+ result ||= s(:str, "").line lexer.lineno
1915
2239
 
1916
2240
  case result.sexp_type
1917
2241
  when :dstr then
1918
2242
  result.sexp_type = :dsym
1919
2243
  when :str then
1920
- result = s(:lit, result.last.to_sym)
2244
+ result = s(:lit, result.last.to_sym).line result.line
1921
2245
  when :evstr then
1922
- result = s(:dsym, "", result)
2246
+ result = s(:dsym, "", result).line result.line
1923
2247
  else
1924
- debug20 26, val, result
2248
+ debug 39
1925
2249
  end
1926
2250
  }
1927
2251
 
1928
2252
  numeric: simple_numeric
1929
- | tUMINUS_NUM simple_numeric
2253
+ | tUMINUS_NUM simple_numeric =tLOWEST
1930
2254
  {
1931
- result = -val[1] # TODO: pt_testcase
2255
+ _, (num, line) = val
2256
+ result = [-num, line]
1932
2257
  }
1933
2258
 
1934
2259
  simple_numeric: tINTEGER
@@ -1942,26 +2267,29 @@ regexp_contents: none
1942
2267
  | tCONSTANT
1943
2268
  | tCVAR
1944
2269
 
1945
- keyword_variable: kNIL { result = s(:nil) }
1946
- | kSELF { result = s(:self) }
1947
- | kTRUE { result = s(:true) }
1948
- | kFALSE { result = s(:false) }
1949
- | k__FILE__ { result = s(:str, self.file) }
1950
- | k__LINE__ { result = s(:lit, lexer.lineno) }
2270
+ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2271
+ | kSELF { result = s(:self).line lexer.lineno }
2272
+ | kTRUE { result = s(:true).line lexer.lineno }
2273
+ | kFALSE { result = s(:false).line lexer.lineno }
2274
+ | k__FILE__ { result = s(:str, self.file).line lexer.lineno }
2275
+ | k__LINE__ { result = s(:lit, lexer.lineno).line lexer.lineno }
1951
2276
  | k__ENCODING__
1952
2277
  {
2278
+ l = lexer.lineno
1953
2279
  result =
1954
2280
  if defined? Encoding then
1955
- s(:colon2, s(:const, :Encoding), :UTF_8)
2281
+ s(:colon2, s(:const, :Encoding).line(l), :UTF_8).line l
1956
2282
  else
1957
- s(:str, "Unsupported!")
2283
+ s(:str, "Unsupported!").line l
1958
2284
  end
1959
2285
  }
1960
2286
 
1961
2287
  var_ref: user_variable
1962
2288
  {
1963
- var = val[0]
2289
+ raise "NO: #{val.inspect}" if Sexp === val.first
2290
+ (var, line), = val
1964
2291
  result = Sexp === var ? var : self.gettable(var)
2292
+ result.line line
1965
2293
  }
1966
2294
  | keyword_variable
1967
2295
  {
@@ -1976,46 +2304,46 @@ keyword_variable: kNIL { result = s(:nil) }
1976
2304
  | keyword_variable
1977
2305
  {
1978
2306
  result = self.assignable val[0]
1979
- debug20 29, val, result
2307
+ debug 40
1980
2308
  }
1981
2309
 
1982
- backref: tNTH_REF { result = s(:nth_ref, val[0]) }
1983
- | tBACK_REF { result = s(:back_ref, val[0]) }
1984
-
1985
- superclass: term
2310
+ backref: tNTH_REF
1986
2311
  {
1987
- result = nil
2312
+ (ref, line), = val
2313
+ result = s(:nth_ref, ref).line line
1988
2314
  }
1989
- | tLT
2315
+ | tBACK_REF
2316
+ {
2317
+ (ref, line), = val
2318
+ result = s(:back_ref, ref).line line
2319
+ }
2320
+
2321
+ superclass: tLT
1990
2322
  {
1991
- lexer.lex_state = :expr_beg
2323
+ lexer.lex_state = EXPR_BEG
2324
+ lexer.command_start = true
1992
2325
  }
1993
2326
  expr_value term
1994
2327
  {
1995
2328
  result = val[2]
1996
2329
  }
1997
- | error term
2330
+ | none
1998
2331
  {
1999
- yyerrok
2000
2332
  result = nil
2001
- debug20 30, val, result
2002
2333
  }
2003
2334
 
2004
2335
  f_arglist: tLPAREN2 f_args rparen
2005
2336
  {
2006
- result = val[1]
2007
- self.lexer.lex_state = :expr_beg
2008
- self.lexer.command_start = true
2009
- # TODO:
2010
- # $<num>$ = parser->parser_in_kwarg;
2011
- # parser->parser_in_kwarg = 1;
2337
+ result = end_args val
2338
+ }
2339
+ | {
2340
+ result = self.in_kwarg
2341
+ self.in_kwarg = true
2342
+ self.lexer.lex_state |= EXPR_LABEL
2012
2343
  }
2013
- | f_args term
2344
+ f_args term
2014
2345
  {
2015
- # TODO: parser->parser_in_kwarg = $<num>1;
2016
- result = val[0]
2017
- self.lexer.lex_state = :expr_beg
2018
- self.lexer.command_start = true
2346
+ result = end_args val
2019
2347
  }
2020
2348
 
2021
2349
  args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
@@ -2100,8 +2428,10 @@ keyword_variable: kNIL { result = s(:nil) }
2100
2428
  |
2101
2429
  {
2102
2430
  result = args val
2431
+ # result.line lexer.lineno
2103
2432
  }
2104
2433
 
2434
+
2105
2435
  f_bad_arg: tCONSTANT
2106
2436
  {
2107
2437
  yyerror "formal argument cannot be a constant"
@@ -2122,10 +2452,11 @@ keyword_variable: kNIL { result = s(:nil) }
2122
2452
  f_norm_arg: f_bad_arg
2123
2453
  | tIDENTIFIER
2124
2454
  {
2125
- identifier = val[0].to_sym
2455
+ (id, line), = val
2456
+ identifier = id.to_sym
2126
2457
  self.env[identifier] = :lvar
2127
2458
 
2128
- result = identifier
2459
+ result = [identifier, line]
2129
2460
  }
2130
2461
 
2131
2462
  f_arg_asgn: f_norm_arg
@@ -2133,21 +2464,14 @@ keyword_variable: kNIL { result = s(:nil) }
2133
2464
  f_arg_item: f_arg_asgn
2134
2465
  | tLPAREN f_margs rparen
2135
2466
  {
2136
- result = val[1]
2467
+ _, margs, _ = val
2468
+
2469
+ result = margs
2137
2470
  }
2138
2471
 
2139
2472
  f_arg: f_arg_item
2140
2473
  {
2141
- case val[0]
2142
- when Symbol then
2143
- result = s(:args)
2144
- result << val[0]
2145
- when Sexp then
2146
- result = val[0]
2147
- else
2148
- debug20 32
2149
- raise "Unknown f_arg type: #{val.inspect}"
2150
- end
2474
+ result = new_arg val
2151
2475
  }
2152
2476
  | f_arg tCOMMA f_arg_item
2153
2477
  {
@@ -2156,48 +2480,52 @@ keyword_variable: kNIL { result = s(:nil) }
2156
2480
  if list.sexp_type == :args then
2157
2481
  result = list
2158
2482
  else
2159
- result = s(:args, list)
2483
+ result = s(:args, list).line list.line
2160
2484
  end
2161
2485
 
2162
- result << item
2486
+ result << (Sexp === item ? item : item.first)
2163
2487
  }
2164
2488
 
2165
2489
  f_label: tLABEL
2166
2490
 
2167
2491
  f_kw: f_label arg_value
2168
2492
  {
2169
- # TODO: call_args
2170
- label, _ = val[0] # TODO: fix lineno?
2493
+ # TODO: new_kw_arg
2494
+ (label, line), arg = val
2495
+
2171
2496
  identifier = label.to_sym
2172
2497
  self.env[identifier] = :lvar
2173
2498
 
2174
- result = s(:array, s(:kwarg, identifier, val[1]))
2499
+ kwarg = s(:kwarg, identifier, arg).line line
2500
+ result = s(:array, kwarg).line line
2175
2501
  }
2176
2502
  | f_label
2177
2503
  {
2178
- label, _ = val[0] # TODO: fix lineno?
2179
- identifier = label.to_sym
2180
- self.env[identifier] = :lvar
2504
+ (label, line), = val
2505
+
2506
+ id = label.to_sym
2507
+ self.env[id] = :lvar
2181
2508
 
2182
- result = s(:array, s(:kwarg, identifier))
2509
+ result = s(:array, s(:kwarg, id).line(line)).line line
2183
2510
  }
2184
2511
 
2185
2512
  f_block_kw: f_label primary_value
2186
2513
  {
2187
- # TODO: call_args
2188
- label, _ = val[0] # TODO: fix lineno?
2189
- identifier = label.to_sym
2190
- self.env[identifier] = :lvar
2514
+ # TODO: new_kw_arg
2515
+ (label, line), expr = val
2516
+ id = label.to_sym
2517
+ self.env[id] = :lvar
2191
2518
 
2192
- result = s(:array, s(:kwarg, identifier, val[1]))
2519
+ result = s(:array, s(:kwarg, id, expr).line(line)).line line
2193
2520
  }
2194
2521
  | f_label
2195
2522
  {
2196
- label, _ = val[0] # TODO: fix lineno?
2197
- identifier = label.to_sym
2198
- self.env[identifier] = :lvar
2523
+ # TODO: new_kw_arg
2524
+ (label, line), = val
2525
+ id = label.to_sym
2526
+ self.env[id] = :lvar
2199
2527
 
2200
- result = s(:array, s(:kwarg, identifier))
2528
+ result = s(:array, s(:kwarg, id).line(line)).line line
2201
2529
  }
2202
2530
 
2203
2531
  f_block_kwarg: f_block_kw
@@ -2216,39 +2544,51 @@ keyword_variable: kNIL { result = s(:nil) }
2216
2544
  kwrest_mark: tPOW
2217
2545
  | tDSTAR
2218
2546
 
2547
+
2219
2548
  f_kwrest: kwrest_mark tIDENTIFIER
2220
2549
  {
2221
- result = :"**#{val[1]}"
2550
+ _, (id, line) = val
2551
+
2552
+ name = id.to_sym
2553
+ self.assignable [name, line]
2554
+ result = [:"**#{name}", line]
2222
2555
  }
2223
2556
  | kwrest_mark
2224
2557
  {
2225
- result = :"**"
2558
+ id = :"**"
2559
+ self.env[id] = :lvar # TODO: needed?!?
2560
+ result = [id, lexer.lineno] # TODO: tPOW/tDSTAR include lineno
2226
2561
  }
2227
2562
 
2228
2563
  f_opt: f_arg_asgn tEQL arg_value
2229
2564
  {
2230
- result = self.assignable val[0], val[2]
2565
+ lhs, _, rhs = val
2566
+ result = self.assignable lhs, rhs
2231
2567
  # TODO: detect duplicate names
2232
2568
  }
2233
2569
 
2234
2570
  f_block_opt: f_arg_asgn tEQL primary_value
2235
2571
  {
2236
- result = self.assignable val[0], val[2]
2572
+ lhs, _, rhs = val
2573
+ result = self.assignable lhs, rhs
2237
2574
  }
2238
2575
 
2239
2576
  f_block_optarg: f_block_opt
2240
2577
  {
2241
- result = s(:block, val[0])
2578
+ optblk, = val
2579
+ result = s(:block, optblk).line optblk.line
2242
2580
  }
2243
2581
  | f_block_optarg tCOMMA f_block_opt
2244
2582
  {
2245
- result = val[0]
2246
- result << val[2]
2583
+ optarg, _, optblk = val
2584
+ result = optarg
2585
+ result << optblk
2247
2586
  }
2248
2587
 
2249
2588
  f_optarg: f_opt
2250
2589
  {
2251
- result = s(:block, val[0])
2590
+ opt, = val
2591
+ result = s(:block, opt).line opt.line
2252
2592
  }
2253
2593
  | f_optarg tCOMMA f_opt
2254
2594
  {
@@ -2260,30 +2600,33 @@ keyword_variable: kNIL { result = s(:nil) }
2260
2600
  f_rest_arg: restarg_mark tIDENTIFIER
2261
2601
  {
2262
2602
  # TODO: differs from parse.y - needs tests
2263
- name = val[1].to_sym
2264
- self.assignable name
2265
- result = :"*#{name}"
2603
+ _, (id, line) = val
2604
+ name = id.to_sym
2605
+ self.assignable [name, line]
2606
+ result = [:"*#{name}", line]
2266
2607
  }
2267
2608
  | restarg_mark
2268
2609
  {
2269
2610
  name = :"*"
2270
2611
  self.env[name] = :lvar
2271
- result = name
2612
+ result = [name, lexer.lineno] # FIX: tSTAR to include lineno
2272
2613
  }
2273
2614
 
2274
2615
  blkarg_mark: tAMPER2 | tAMPER
2275
2616
 
2276
2617
  f_block_arg: blkarg_mark tIDENTIFIER
2277
2618
  {
2278
- identifier = val[1].to_sym
2619
+ _, (id, line) = val
2620
+ identifier = id.to_sym
2279
2621
 
2280
2622
  self.env[identifier] = :lvar
2281
- result = "&#{identifier}".to_sym
2623
+ result = ["&#{identifier}".to_sym, line]
2282
2624
  }
2283
2625
 
2284
2626
  opt_f_block_arg: tCOMMA f_block_arg
2285
2627
  {
2286
- result = val[1]
2628
+ _, arg = val
2629
+ result = arg
2287
2630
  }
2288
2631
  |
2289
2632
  {
@@ -2293,7 +2636,7 @@ keyword_variable: kNIL { result = s(:nil) }
2293
2636
  singleton: var_ref
2294
2637
  | tLPAREN2
2295
2638
  {
2296
- lexer.lex_state = :expr_beg
2639
+ lexer.lex_state = EXPR_BEG
2297
2640
  }
2298
2641
  expr rparen
2299
2642
  {
@@ -2302,14 +2645,11 @@ keyword_variable: kNIL { result = s(:nil) }
2302
2645
  result.sexp_type == :lit
2303
2646
  }
2304
2647
 
2305
- assoc_list: none # [!nil]
2306
- {
2307
- result = s(:array)
2308
- }
2309
- | assocs trailer # [!nil]
2648
+ assoc_list: none
2310
2649
  {
2311
- result = val[0]
2650
+ result = s(:array).line lexer.lineno
2312
2651
  }
2652
+ | assocs trailer
2313
2653
 
2314
2654
  assocs: assoc
2315
2655
  | assocs tCOMMA assoc
@@ -2323,26 +2663,29 @@ keyword_variable: kNIL { result = s(:nil) }
2323
2663
 
2324
2664
  assoc: arg_value tASSOC arg_value
2325
2665
  {
2326
- result = s(:array, val[0], val[2])
2666
+ v1, _, v2 = val
2667
+ result = s(:array, v1, v2).line v1.line
2327
2668
  }
2328
- | tLABEL opt_nl arg_value
2669
+ | tLABEL arg_value
2329
2670
  {
2330
- result = s(:array, s(:lit, val[0][0].to_sym), val.last)
2671
+ (label, line), arg = val
2672
+
2673
+ lit = s(:lit, label.to_sym).line line
2674
+ result = s(:array, lit, arg).line line
2331
2675
  }
2332
2676
  | tSTRING_BEG string_contents tLABEL_END arg_value
2333
2677
  {
2334
- _, sym, _, value = val
2678
+ (_, line), sym, _, value = val
2679
+
2335
2680
  sym.sexp_type = :dsym
2336
- result = s(:array, sym, value)
2337
- }
2338
- | tSYMBOL arg_value
2339
- {
2340
- raise "not yet: #{val.inspect}"
2341
- # result = s(:array, s(:lit, val[1].to_sym), val[1])
2681
+
2682
+ result = s(:array, sym, value).line line
2342
2683
  }
2343
2684
  | tDSTAR arg_value
2344
2685
  {
2345
- result = s(:array, s(:kwsplat, val[1]))
2686
+ _, arg = val
2687
+ line = arg.line
2688
+ result = s(:array, s(:kwsplat, arg).line(line)).line line
2346
2689
  }
2347
2690
 
2348
2691
  operation: tIDENTIFIER | tCONSTANT | tFID
@@ -2350,7 +2693,11 @@ keyword_variable: kNIL { result = s(:nil) }
2350
2693
  operation3: tIDENTIFIER | tFID | op
2351
2694
  dot_or_colon: tDOT | tCOLON2
2352
2695
  call_op: tDOT
2353
- | tLONELY
2696
+ | tLONELY # TODO: rename tANDDOT?
2697
+
2698
+ call_op2: call_op
2699
+ | tCOLON2
2700
+
2354
2701
  opt_terms: | terms
2355
2702
  opt_nl: | tNL
2356
2703
  rparen: opt_nl tRPAREN
@@ -2370,6 +2717,7 @@ end
2370
2717
 
2371
2718
  require "ruby_lexer"
2372
2719
  require "ruby_parser_extras"
2720
+ include RubyLexer::State::Values
2373
2721
 
2374
2722
  # :stopdoc:
2375
2723