ruby_parser 3.15.0 → 3.18.0

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