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