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