ruby_parser 3.0.0 → 3.19.1

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