ruby_parser 3.19.2 → 3.20.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: **