rb-ruby_parser 2.0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1790 @@
1
+ # -*- racc -*-
2
+
3
+ class RubyParser
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 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__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tNTH_REF
11
+ tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT tREGEXP_END tUPLUS
12
+ tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ tGEQ tLEQ tANDOP
13
+ tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF tASET tLSHFT tRSHFT
14
+ tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN tLPAREN2 tRPAREN tLPAREN_ARG
15
+ tLBRACK tRBRACK tLBRACE tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2
16
+ tTILDE tPERCENT tDIVIDE tPLUS tMINUS tLT tGT tPIPE tBANG tCARET
17
+ tLCURLY tRCURLY tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
18
+ tWORDS_BEG tAWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tSTRING
19
+ tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAST_TOKEN
20
+
21
+ prechigh
22
+ right tBANG tTILDE tUPLUS
23
+ right tPOW
24
+ right tUMINUS_NUM tUMINUS
25
+ left tSTAR2 tDIVIDE tPERCENT
26
+ left tPLUS tMINUS
27
+ left tLSHFT tRSHFT
28
+ left tAMPER2
29
+ left tPIPE tCARET
30
+ left tGT tGEQ tLT tLEQ
31
+ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
32
+ left tANDOP
33
+ left tOROP
34
+ nonassoc tDOT2 tDOT3
35
+ right tEH tCOLON
36
+ left kRESCUE_MOD
37
+ right tEQL tOP_ASGN
38
+ nonassoc kDEFINED
39
+ right kNOT
40
+ left kOR kAND
41
+ nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
42
+ nonassoc tLBRACE_ARG
43
+ nonassoc tLOWEST
44
+ preclow
45
+
46
+ rule
47
+
48
+ program: {
49
+ self.lexer.lex_state = :expr_beg
50
+ }
51
+ compstmt
52
+ {
53
+ result = val[1]
54
+ }
55
+
56
+ bodystmt: compstmt opt_rescue opt_else opt_ensure
57
+ {
58
+ result = new_body val
59
+ }
60
+
61
+ compstmt: stmts opt_terms
62
+ {
63
+ result = new_compstmt val
64
+ }
65
+
66
+ stmts: none
67
+ | stmt
68
+ | stmts terms stmt
69
+ {
70
+ result = self.block_append val[0], val[2]
71
+ }
72
+ | error stmt
73
+ {
74
+ result = val[1]
75
+ }
76
+
77
+ stmt: kALIAS fitem
78
+ {
79
+ lexer.lex_state = :expr_fname
80
+ result = self.lexer.lineno
81
+ }
82
+ fitem
83
+ {
84
+ result = s(:alias, val[1], val[3]).line(val[2])
85
+ }
86
+ | kALIAS tGVAR tGVAR
87
+ {
88
+ result = s(:valias, val[1].to_sym, val[2].to_sym)
89
+ }
90
+ | kALIAS tGVAR tBACK_REF
91
+ {
92
+ result = s(:valias, val[1].to_sym, :"$#{val[2]}")
93
+ }
94
+ | kALIAS tGVAR tNTH_REF
95
+ {
96
+ yyerror "can't make alias for the number variables"
97
+ }
98
+ | kUNDEF undef_list
99
+ {
100
+ result = val[1]
101
+ }
102
+ | stmt kIF_MOD expr_value
103
+ {
104
+ result = new_if val[2], val[0], nil
105
+ }
106
+ | stmt kUNLESS_MOD expr_value
107
+ {
108
+ result = new_if val[2], nil, val[0]
109
+ }
110
+ | stmt kWHILE_MOD expr_value
111
+ {
112
+ result = new_while val[0], val[2], true
113
+ }
114
+ | stmt kUNTIL_MOD expr_value
115
+ {
116
+ result = new_until val[0], val[2], true
117
+ }
118
+ | stmt kRESCUE_MOD stmt
119
+ {
120
+ result = s(:rescue, val[0], s(:resbody, s(:array), val[2]))
121
+ }
122
+ | klBEGIN
123
+ {
124
+ if (self.in_def || self.in_single > 0) then
125
+ yyerror "BEGIN in method"
126
+ end
127
+ self.env.extend
128
+ }
129
+ tLCURLY compstmt tRCURLY
130
+ {
131
+ result = new_iter s(:preexe), nil, val[3] # TODO: add test?
132
+ result = nil # TODO: since it isn't supposed to go in the AST
133
+ }
134
+ | klEND tLCURLY compstmt tRCURLY
135
+ {
136
+ if (self.in_def || self.in_single > 0) then
137
+ yyerror "END in method; use at_exit"
138
+ end
139
+ result = new_iter s(:postexe), nil, val[2]
140
+ }
141
+ | lhs tEQL command_call
142
+ {
143
+ result = self.node_assign val[0], val[2]
144
+ }
145
+ | mlhs tEQL command_call
146
+ {
147
+ result = new_masgn val[0], val[2], :wrap
148
+ }
149
+ | var_lhs tOP_ASGN command_call
150
+ {
151
+ result = new_op_asgn val
152
+ }
153
+ | primary_value "[" aref_args tRBRACK tOP_ASGN command_call
154
+ {
155
+ result = s(:op_asgn1, val[0], val[2], val[4].to_sym, val[5])
156
+ }
157
+ | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
158
+ {
159
+ result = s(:op_asgn, val[0], val[4], val[2], val[3])
160
+ }
161
+ | primary_value tDOT tCONSTANT tOP_ASGN command_call
162
+ {
163
+ result = s(:op_asgn, val[0], val[4], val[2], val[3])
164
+ }
165
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
166
+ {
167
+ result = s(:op_asgn, val[0], val[4], val[2], val[3])
168
+ }
169
+ | backref tOP_ASGN command_call
170
+ {
171
+ self.backref_assign_error val[0]
172
+ }
173
+ | lhs tEQL mrhs
174
+ {
175
+ result = self.node_assign val[0], s(:svalue, val[2])
176
+ }
177
+ | mlhs tEQL arg_value
178
+ {
179
+ result = new_masgn val[0], val[2], :wrap
180
+ }
181
+ | mlhs tEQL mrhs
182
+ {
183
+ result = new_masgn val[0], val[2]
184
+ }
185
+ | expr
186
+
187
+ expr: command_call
188
+ | expr kAND expr
189
+ {
190
+ result = logop(:and, val[0], val[2])
191
+ }
192
+ | expr kOR expr
193
+ {
194
+ result = logop(:or, val[0], val[2])
195
+ }
196
+ | kNOT expr
197
+ {
198
+ result = s(:not, val[1])
199
+ }
200
+ | tBANG command_call
201
+ {
202
+ result = s(:not, val[1])
203
+ }
204
+ | arg
205
+
206
+ expr_value: expr
207
+ {
208
+ result = value_expr(val[0])
209
+ }
210
+
211
+ command_call: command
212
+ | block_command
213
+ | kRETURN call_args
214
+ {
215
+ result = s(:return, ret_args(val[1]))
216
+ }
217
+ | kBREAK call_args
218
+ {
219
+ result = s(:break, ret_args(val[1]))
220
+ }
221
+ | kNEXT call_args
222
+ {
223
+ result = s(:next, ret_args(val[1]))
224
+ }
225
+
226
+ block_command: block_call
227
+ | block_call tDOT operation2 command_args
228
+ {
229
+ result = new_call val[0], val[2], val[3]
230
+ }
231
+ | block_call tCOLON2 operation2 command_args
232
+ {
233
+ result = new_call val[0], val[2], val[3]
234
+ }
235
+
236
+ cmd_brace_block: tLBRACE_ARG
237
+ {
238
+ self.env.extend(:dynamic)
239
+ result = self.lexer.lineno
240
+ }
241
+ opt_block_var
242
+ {
243
+ result = self.env.dynamic.keys
244
+ }
245
+ compstmt tRCURLY
246
+ {
247
+ result = new_iter nil, val[2], val[4]
248
+ self.env.unextend
249
+ }
250
+
251
+ command: operation command_args =tLOWEST
252
+ {
253
+ result = new_call nil, val[0].to_sym, val[1]
254
+ }
255
+ | operation command_args cmd_brace_block
256
+ {
257
+ result = new_call nil, val[0].to_sym, val[1]
258
+ if val[2] then
259
+ if result[0] == :block_pass then
260
+ raise "both block arg and actual block given"
261
+ end
262
+ result, operation = val[2], result
263
+ result.insert 1, operation
264
+ end
265
+ }
266
+ | primary_value tDOT operation2 command_args =tLOWEST
267
+ {
268
+ result = new_call val[0], val[2].to_sym, val[3]
269
+ }
270
+ | primary_value tDOT operation2 command_args cmd_brace_block
271
+ {
272
+ result = new_call val[0], val[2].to_sym, val[3]
273
+ }
274
+ | primary_value tCOLON2 operation2 command_args =tLOWEST
275
+ {
276
+ result = new_call val[0], val[2].to_sym, val[3]
277
+ }
278
+ | primary_value tCOLON2 operation2 command_args cmd_brace_block
279
+ {
280
+ result = new_call val[0], val[2].to_sym, val[3]
281
+ if val[4] then
282
+ if result[0] == :block_pass then # REFACTOR
283
+ raise "both block arg and actual block given"
284
+ end
285
+ val[2] << result
286
+ result = val[2]
287
+ end
288
+ }
289
+ | kSUPER command_args
290
+ {
291
+ result = new_super val[1]
292
+ }
293
+ | kYIELD command_args
294
+ {
295
+ result = new_yield val[1]
296
+ }
297
+
298
+ mlhs: mlhs_basic
299
+ | tLPAREN mlhs_entry tRPAREN
300
+ {
301
+ result = val[1]
302
+ }
303
+
304
+ mlhs_entry: mlhs_basic
305
+ | tLPAREN mlhs_entry tRPAREN
306
+ {
307
+ result = s(:masgn, s(:array, val[1]))
308
+ }
309
+
310
+ mlhs_basic: mlhs_head
311
+ {
312
+ result = s(:masgn, val[0])
313
+ }
314
+ | mlhs_head mlhs_item
315
+ {
316
+ result = s(:masgn, val[0] << val[1].compact)
317
+ }
318
+ | mlhs_head tSTAR mlhs_node
319
+ {
320
+ result = s(:masgn, val[0] << s(:splat, val[2]))
321
+ }
322
+ | mlhs_head tSTAR
323
+ {
324
+ result = s(:masgn, val[0] << s(:splat))
325
+ }
326
+ | tSTAR mlhs_node
327
+ {
328
+ result = s(:masgn, s(:array, s(:splat, val[1])))
329
+ }
330
+ | tSTAR
331
+ {
332
+ result = s(:masgn, s(:array, s(:splat)))
333
+ }
334
+
335
+ mlhs_item: mlhs_node
336
+ | tLPAREN mlhs_entry tRPAREN
337
+ {
338
+ result = val[1]
339
+ }
340
+
341
+ mlhs_head: mlhs_item tCOMMA
342
+ {
343
+ result = s(:array, val[0])
344
+ }
345
+ | mlhs_head mlhs_item tCOMMA
346
+ {
347
+ result = val[0] << val[1].compact
348
+ }
349
+
350
+ mlhs_node: variable
351
+ {
352
+ result = self.assignable val[0]
353
+ }
354
+ | primary_value "[" aref_args tRBRACK
355
+ {
356
+ result = self.aryset val[0], val[2]
357
+ }
358
+ | primary_value tDOT tIDENTIFIER
359
+ {
360
+ result = s(:attrasgn, val[0], :"#{val[2]}=", s(:arglist))
361
+ }
362
+ | primary_value tCOLON2 tIDENTIFIER
363
+ {
364
+ result = s(:attrasgn, val[0], :"#{val[2]}=", s(:arglist))
365
+ }
366
+ | primary_value tDOT tCONSTANT
367
+ {
368
+ result = s(:attrasgn, val[0], :"#{val[2]}=", s(:arglist))
369
+ }
370
+ | primary_value tCOLON2 tCONSTANT
371
+ {
372
+ if (self.in_def || self.in_single > 0) then
373
+ yyerror "dynamic constant assignment"
374
+ end
375
+
376
+ result = s(:const, s(:colon2, val[0], val[2].to_sym), nil)
377
+ }
378
+ | tCOLON3 tCONSTANT
379
+ {
380
+ if (self.in_def || self.in_single > 0) then
381
+ yyerror "dynamic constant assignment"
382
+ end
383
+
384
+ result = s(:const, nil, s(:colon3, val[1].to_sym))
385
+ }
386
+ | backref
387
+ {
388
+ self.backref_assign_error val[0]
389
+ }
390
+
391
+ lhs: variable
392
+ {
393
+ result = self.assignable val[0]
394
+ }
395
+ | primary_value "[" aref_args tRBRACK
396
+ {
397
+ result = self.aryset val[0], val[2]
398
+ }
399
+ | primary_value tDOT tIDENTIFIER
400
+ {
401
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
402
+ }
403
+ | primary_value tCOLON2 tIDENTIFIER
404
+ {
405
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
406
+ }
407
+ | primary_value tDOT tCONSTANT
408
+ {
409
+ result = s(:attrasgn, val[0], :"#{val[2]}=")
410
+ }
411
+ | primary_value tCOLON2 tCONSTANT
412
+ {
413
+ if (self.in_def || self.in_single > 0) then
414
+ yyerror "dynamic constant assignment"
415
+ end
416
+
417
+ result = s(:const, s(:colon2, val[0], val[2].to_sym))
418
+ }
419
+ | tCOLON3 tCONSTANT
420
+ {
421
+ if (self.in_def || self.in_single > 0) then
422
+ yyerror "dynamic constant assignment"
423
+ end
424
+
425
+ result = s(:const, s(:colon3, val[1].to_sym))
426
+ }
427
+ | backref
428
+ {
429
+ self.backref_assign_error val[0]
430
+ }
431
+
432
+ cname: tIDENTIFIER
433
+ {
434
+ yyerror "class/module name must be CONSTANT"
435
+ }
436
+ | tCONSTANT
437
+
438
+ cpath: tCOLON3 cname
439
+ {
440
+ result = s(:colon3, val[1].to_sym)
441
+ }
442
+ | cname
443
+ {
444
+ result = val[0].to_sym
445
+ }
446
+ | primary_value tCOLON2 cname
447
+ {
448
+ result = s(:colon2, val[0], val[2].to_sym)
449
+ }
450
+
451
+ fname: tIDENTIFIER | tCONSTANT | tFID
452
+ | op
453
+ {
454
+ lexer.lex_state = :expr_end
455
+ result = val[0]
456
+ }
457
+
458
+ | reswords
459
+ {
460
+ lexer.lex_state = :expr_end
461
+ result = val[0]
462
+ }
463
+
464
+ # TODO: cruby has fsym and dsym
465
+ fitem: fname { result = s(:lit, val[0].to_sym) }
466
+ | symbol { result = s(:lit, val[0]) }
467
+
468
+ undef_list: fitem
469
+ {
470
+ result = new_undef val[0]
471
+ }
472
+ |
473
+ undef_list tCOMMA
474
+ {
475
+ lexer.lex_state = :expr_fname
476
+ }
477
+ fitem
478
+ {
479
+ result = new_undef val[0], val[3]
480
+ }
481
+
482
+ op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
483
+ | tMATCH | tGT | tGEQ | tLT | tLEQ | tLSHFT
484
+ | tRSHFT | tPLUS | tMINUS | tSTAR2 | tSTAR | tDIVIDE
485
+ | tPERCENT | tPOW | tTILDE | tUPLUS | tUMINUS | tAREF
486
+ | tASET | tBACK_REF2
487
+
488
+ reswords: k__LINE__ | k__FILE__ | klBEGIN | klEND | kALIAS | kAND
489
+ | kBEGIN | kBREAK | kCASE | kCLASS | kDEF | kDEFINED
490
+ | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
491
+ | kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
492
+ | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF
493
+ | kSUPER | kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
494
+ | kIF_MOD | kUNLESS_MOD | kWHILE_MOD | kUNTIL_MOD | kRESCUE_MOD
495
+
496
+ arg: lhs tEQL arg
497
+ {
498
+ result = self.node_assign val[0], val[2]
499
+ }
500
+ | lhs tEQL arg kRESCUE_MOD arg
501
+ {
502
+ result = self.node_assign val[0], s(:rescue, val[2], s(:resbody, s(:array), val[4]))
503
+ # result.line = val[0].line
504
+ }
505
+ | var_lhs tOP_ASGN arg
506
+ {
507
+ result = new_op_asgn val
508
+ }
509
+ | primary_value "[" aref_args tRBRACK tOP_ASGN arg
510
+ {
511
+ result = s(:op_asgn1, val[0], val[2], val[4].to_sym, val[5])
512
+ val[2][0] = :arglist
513
+ }
514
+ | primary_value tDOT tIDENTIFIER tOP_ASGN arg
515
+ {
516
+ result = s(:op_asgn2, val[0], :"#{val[2]}=", val[3].to_sym, val[4])
517
+ }
518
+ | primary_value tDOT tCONSTANT tOP_ASGN arg
519
+ {
520
+ result = s(:op_asgn2, val[0], :"#{val[2]}=", val[3].to_sym, val[4])
521
+ }
522
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
523
+ {
524
+ result = s(:op_asgn, val[0], val[4], val[2], val[3])
525
+ }
526
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
527
+
528
+ {
529
+ yyerror "constant re-assignment"
530
+ }
531
+ | tCOLON3 tCONSTANT tOP_ASGN arg
532
+ {
533
+ yyerror "constant re-assignment"
534
+ }
535
+ | backref tOP_ASGN arg
536
+ {
537
+ self.backref_assign_error val[0]
538
+ }
539
+ | arg tDOT2 arg
540
+ {
541
+ v1, v2 = val[0], val[2]
542
+ if v1.node_type == :lit and v2.node_type == :lit and Fixnum === v1.last and Fixnum === v2.last then
543
+ result = s(:lit, (v1.last)..(v2.last))
544
+ else
545
+ result = s(:dot2, v1, v2)
546
+ end
547
+ }
548
+ | arg tDOT3 arg
549
+ {
550
+ v1, v2 = val[0], val[2]
551
+ if v1.node_type == :lit and v2.node_type == :lit and Fixnum === v1.last and Fixnum === v2.last then
552
+ result = s(:lit, (v1.last)...(v2.last))
553
+ else
554
+ result = s(:dot3, v1, v2)
555
+ end
556
+ }
557
+ | arg tPLUS arg
558
+ {
559
+ result = new_call val[0], :+, s(:arglist, val[2])
560
+ }
561
+ | arg tMINUS arg
562
+ {
563
+ result = new_call val[0], :-, s(:arglist, val[2])
564
+ }
565
+ | arg tSTAR2 arg
566
+ {
567
+ result = new_call val[0], :*, s(:arglist, val[2])
568
+ }
569
+ | arg tDIVIDE arg
570
+ {
571
+ result = new_call val[0], :"/", s(:arglist, val[2])
572
+ }
573
+ | arg tPERCENT arg
574
+ {
575
+ result = new_call val[0], :%, s(:arglist, val[2])
576
+ }
577
+ | arg tPOW arg
578
+ {
579
+ result = new_call val[0], :**, s(:arglist, val[2])
580
+ }
581
+ | tUMINUS_NUM tINTEGER tPOW arg
582
+ {
583
+ result = new_call(new_call(s(:lit, val[1]), :"**", s(:arglist, val[3])), :"-@", s(:arglist))
584
+ }
585
+ | tUMINUS_NUM tFLOAT tPOW arg
586
+ {
587
+ result = new_call(new_call(s(:lit, val[1]), :"**", s(:arglist, val[3])), :"-@", s(:arglist))
588
+ }
589
+ | tUPLUS arg
590
+ {
591
+ if val[1][0] == :lit then
592
+ result = val[1]
593
+ else
594
+ result = new_call val[1], :"+@", s(:arglist)
595
+ end
596
+ }
597
+ | tUMINUS arg
598
+ {
599
+ result = new_call val[1], :"-@", s(:arglist)
600
+ }
601
+ | arg tPIPE arg
602
+ {
603
+ result = new_call val[0], :"|", s(:arglist, val[2])
604
+ }
605
+ | arg tCARET arg
606
+ {
607
+ result = new_call val[0], :"^", s(:arglist, val[2])
608
+ }
609
+ | arg tAMPER2 arg
610
+ {
611
+ result = new_call val[0], :"&", s(:arglist, val[2])
612
+ }
613
+ | arg tCMP arg
614
+ {
615
+ result = new_call val[0], :"<=>", s(:arglist, val[2])
616
+ }
617
+ | arg tGT arg
618
+ {
619
+ result = new_call val[0], :">", s(:arglist, val[2])
620
+ }
621
+ | arg tGEQ arg
622
+ {
623
+ result = new_call val[0], :">=", s(:arglist, val[2])
624
+ }
625
+ | arg tLT arg
626
+ {
627
+ result = new_call val[0], :"<", s(:arglist, val[2])
628
+ }
629
+ | arg tLEQ arg
630
+ {
631
+ result = new_call val[0], :"<=", s(:arglist, val[2])
632
+ }
633
+ | arg tEQ arg
634
+ {
635
+ result = new_call val[0], :"==", s(:arglist, val[2])
636
+ }
637
+ | arg tEQQ arg
638
+ {
639
+ result = new_call val[0], :"===", s(:arglist, val[2])
640
+ }
641
+ | arg tNEQ arg
642
+ {
643
+ val[0] = value_expr val[0] # TODO: port call_op and clean these
644
+ val[2] = value_expr val[2]
645
+ result = s(:not, new_call(val[0], :"==", s(:arglist, val[2])))
646
+ }
647
+ | arg tMATCH arg
648
+ {
649
+ result = self.get_match_node val[0], val[2]
650
+ }
651
+ | arg tNMATCH arg
652
+ {
653
+ result = s(:not, self.get_match_node(val[0], val[2]))
654
+ }
655
+ | tBANG arg
656
+ {
657
+ result = s(:not, val[1])
658
+ }
659
+ | tTILDE arg
660
+ {
661
+ val[2] = value_expr val[2]
662
+ result = new_call val[1], :"~", s(:arglist)
663
+ }
664
+ | arg tLSHFT arg
665
+ {
666
+ val[0] = value_expr val[0]
667
+ val[2] = value_expr val[2]
668
+ result = new_call val[0], :"\<\<", s(:arglist, val[2])
669
+ }
670
+ | arg tRSHFT arg
671
+ {
672
+ val[0] = value_expr val[0]
673
+ val[2] = value_expr val[2]
674
+ result = new_call val[0], :">>", s(:arglist, val[2])
675
+ }
676
+ | arg tANDOP arg
677
+ {
678
+ result = logop(:and, val[0], val[2])
679
+ }
680
+ | arg tOROP arg
681
+ {
682
+ result = logop(:or, val[0], val[2])
683
+ }
684
+ | kDEFINED opt_nl arg
685
+ {
686
+ result = s(:defined, val[2])
687
+ }
688
+ | arg tEH arg tCOLON arg
689
+ {
690
+ result = s(:if, val[0], val[2], val[4])
691
+ }
692
+ | primary
693
+
694
+ arg_value: arg
695
+ {
696
+ result = value_expr(val[0])
697
+ }
698
+
699
+ aref_args: none
700
+ | command opt_nl
701
+ {
702
+ warning 'parenthesize argument(s) for future version'
703
+ result = s(:array, val[0])
704
+ }
705
+ | args trailer
706
+ {
707
+ result = val[0]
708
+ }
709
+ | args tCOMMA tSTAR arg opt_nl
710
+ {
711
+ result = self.arg_concat val[0], val[3]
712
+ }
713
+ | assocs trailer
714
+ {
715
+ result = s(:array, s(:hash, *val[0].values))
716
+ }
717
+ | tSTAR arg opt_nl
718
+ {
719
+ result = s(:array, s(:splat, val[1]))
720
+ }
721
+
722
+ paren_args: tLPAREN2 none tRPAREN
723
+ {
724
+ result = val[1]
725
+ }
726
+ | tLPAREN2 call_args opt_nl tRPAREN
727
+ {
728
+ result = val[1]
729
+ }
730
+ | tLPAREN2 block_call opt_nl tRPAREN
731
+ {
732
+ warning "parenthesize argument(s) for future version"
733
+ result = s(:array, val[1])
734
+ }
735
+ | tLPAREN2 args tCOMMA block_call opt_nl tRPAREN
736
+ {
737
+ warning "parenthesize argument(s) for future version"
738
+ result = val[1].add val[3]
739
+ }
740
+
741
+ opt_paren_args: none
742
+ | paren_args
743
+
744
+ call_args: command
745
+ {
746
+ warning "parenthesize argument(s) for future version"
747
+ result = s(:array, val[0])
748
+ }
749
+ | args opt_block_arg
750
+ {
751
+ result = self.arg_blk_pass val[0], val[1]
752
+ }
753
+ | args tCOMMA tSTAR arg_value opt_block_arg
754
+ {
755
+ result = self.arg_concat val[0], val[3]
756
+ result = self.arg_blk_pass result, val[4]
757
+ }
758
+ | assocs opt_block_arg
759
+ {
760
+ result = s(:array, s(:hash, *val[0].values))
761
+ result = self.arg_blk_pass result, val[1]
762
+ }
763
+ | assocs tCOMMA tSTAR arg_value opt_block_arg
764
+ {
765
+ result = self.arg_concat s(:array, s(:hash, *val[0].values)), val[3]
766
+ result = self.arg_blk_pass result, val[4]
767
+ }
768
+ | args tCOMMA assocs opt_block_arg
769
+ {
770
+ result = val[0] << s(:hash, *val[2].values)
771
+ result = self.arg_blk_pass result, val[3]
772
+ }
773
+ | args tCOMMA assocs tCOMMA tSTAR arg opt_block_arg
774
+ {
775
+ val[0] << s(:hash, *val[2].values)
776
+ result = self.arg_concat val[0], val[5]
777
+ result = self.arg_blk_pass result, val[6]
778
+ }
779
+ | tSTAR arg_value opt_block_arg
780
+ {
781
+ result = self.arg_blk_pass s(:splat, val[1]), val[2]
782
+ }
783
+ | block_arg
784
+
785
+ call_args2: arg_value tCOMMA args opt_block_arg
786
+ {
787
+ args = self.list_prepend val[0], val[2]
788
+ result = self.arg_blk_pass args, val[3]
789
+ }
790
+ | arg_value tCOMMA block_arg
791
+ {
792
+ result = self.arg_blk_pass val[0], val[2]
793
+ }
794
+ | arg_value tCOMMA tSTAR arg_value opt_block_arg
795
+ {
796
+ result = self.arg_concat s(:array, val[0]), val[3]
797
+ result = self.arg_blk_pass result, val[4]
798
+ }
799
+ | arg_value tCOMMA args tCOMMA tSTAR arg_value opt_block_arg
800
+ {
801
+ result = self.arg_concat s(:array, val[0], s(:hash, *val[2].values)), val[5]
802
+ result = self.arg_blk_pass result, val[6]
803
+ }
804
+ | assocs opt_block_arg
805
+ {
806
+ result = s(:array, s(:hash, *val[0].values))
807
+ result = self.arg_blk_pass result, val[1]
808
+ }
809
+ | assocs tCOMMA tSTAR arg_value opt_block_arg
810
+ {
811
+ result = s(:array, s(:hash, *val[0].values), val[3])
812
+ result = self.arg_blk_pass result, val[4]
813
+ }
814
+ | arg_value tCOMMA assocs opt_block_arg
815
+ {
816
+ result = s(:array, val[0], s(:hash, *val[2].values))
817
+ result = self.arg_blk_pass result, val[3]
818
+ }
819
+ | arg_value tCOMMA args tCOMMA assocs opt_block_arg
820
+ {
821
+ result = s(:array, val[0]).add_all(val[2]).add(s(:hash, *val[4].values))
822
+ result = self.arg_blk_pass result, val[5]
823
+ }
824
+ | arg_value tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
825
+ {
826
+ result = self.arg_concat s(:array, val[0]).add(s(:hash, *val[2].values)), val[5]
827
+ result = self.arg_blk_pass result, val[6]
828
+ }
829
+ | arg_value tCOMMA args tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
830
+ {
831
+ result = self.arg_concat s(:array, val[0]).add_all(val[2]).add(s(:hash, *val[4].values)), val[7]
832
+ result = self.arg_blk_pass result, val[8]
833
+ }
834
+ | tSTAR arg_value opt_block_arg
835
+ {
836
+ result = self.arg_blk_pass s(:splat, val[1]), val[2]
837
+ }
838
+ | block_arg
839
+
840
+ command_args: {
841
+ result = lexer.cmdarg.stack.dup
842
+ lexer.cmdarg.push true
843
+ }
844
+ open_args
845
+ {
846
+ lexer.cmdarg.stack.replace val[0]
847
+ result = val[1]
848
+ }
849
+
850
+ open_args: call_args
851
+ | tLPAREN_ARG
852
+ {
853
+ lexer.lex_state = :expr_endarg
854
+ }
855
+ tRPAREN
856
+ {
857
+ warning "don't put space before argument parentheses"
858
+ result = nil
859
+ }
860
+ | tLPAREN_ARG call_args2
861
+ {
862
+ lexer.lex_state = :expr_endarg
863
+ }
864
+ tRPAREN
865
+ {
866
+ warning "don't put space before argument parentheses"
867
+ result = val[1]
868
+ }
869
+
870
+ block_arg: tAMPER arg_value
871
+ {
872
+ result = s(:block_pass, val[1])
873
+ }
874
+
875
+ opt_block_arg: tCOMMA block_arg
876
+ {
877
+ result = val[1]
878
+ }
879
+ | none_block_pass
880
+
881
+ args: arg_value
882
+ {
883
+ result = s(:array, val[0])
884
+ }
885
+ | args tCOMMA arg_value
886
+ {
887
+ result = self.list_append val[0], val[2]
888
+ }
889
+
890
+ mrhs: args tCOMMA arg_value
891
+ {
892
+ result = val[0] << val[2]
893
+ }
894
+ | args tCOMMA tSTAR arg_value
895
+ {
896
+ result = self.arg_concat val[0], val[3]
897
+ }
898
+ | tSTAR arg_value
899
+ {
900
+ result = s(:splat, val[1])
901
+ }
902
+
903
+ primary: literal
904
+ | strings
905
+ | xstring
906
+ | regexp
907
+ | words
908
+ | awords
909
+ | var_ref
910
+ | backref
911
+ | tFID
912
+ {
913
+ result = new_call nil, val[0].to_sym
914
+ }
915
+ | kBEGIN
916
+ {
917
+ result = self.lexer.lineno
918
+ }
919
+ bodystmt kEND
920
+ {
921
+ unless val[2] then
922
+ result = s(:nil)
923
+ else
924
+ result = s(:begin, val[2])
925
+ end
926
+
927
+ result.line = val[1]
928
+ }
929
+ | tLPAREN_ARG expr
930
+ {
931
+ lexer.lex_state = :expr_endarg
932
+ }
933
+ opt_nl tRPAREN
934
+ {
935
+ warning "(...) interpreted as grouped expression"
936
+ result = val[1]
937
+ }
938
+ | tLPAREN compstmt tRPAREN
939
+ {
940
+ result = val[1] || s(:nil)
941
+ result.paren = true
942
+ }
943
+ | primary_value tCOLON2 tCONSTANT
944
+ {
945
+ result = s(:colon2, val[0], val[2].to_sym)
946
+ }
947
+ | tCOLON3 tCONSTANT
948
+ {
949
+ result = s(:colon3, val[1].to_sym)
950
+ }
951
+ | primary_value "[" aref_args tRBRACK
952
+ {
953
+ result = new_aref val
954
+ }
955
+ | tLBRACK aref_args tRBRACK
956
+ {
957
+ result = val[1] || s(:array)
958
+ }
959
+ | tLBRACE assoc_list tRCURLY
960
+ {
961
+ result = s(:hash, *val[1].values)
962
+ }
963
+ | kRETURN
964
+ {
965
+ result = s(:return)
966
+ }
967
+ | kYIELD tLPAREN2 call_args tRPAREN
968
+ {
969
+ result = new_yield val[2]
970
+ }
971
+ | kYIELD tLPAREN2 tRPAREN
972
+ {
973
+ result = new_yield
974
+ }
975
+ | kYIELD
976
+ {
977
+ result = new_yield
978
+ }
979
+ | kDEFINED opt_nl tLPAREN2 expr tRPAREN
980
+ {
981
+ result = s(:defined, val[3])
982
+ }
983
+ | operation brace_block
984
+ {
985
+ oper, iter = val[0], val[1]
986
+ call = new_call(nil, oper.to_sym)
987
+ iter.insert 1, call
988
+ result = iter
989
+ call.line ||= iter.line
990
+ }
991
+ | method_call
992
+ | method_call brace_block
993
+ {
994
+ call, iter = val[0], val[1]
995
+ iter.insert 1, call
996
+ result = iter
997
+ }
998
+ | kIF expr_value then compstmt if_tail kEND
999
+ {
1000
+ result = new_if val[1], val[3], val[4]
1001
+ }
1002
+ | kUNLESS expr_value then compstmt opt_else kEND
1003
+ {
1004
+ result = new_if val[1], val[4], val[3]
1005
+ }
1006
+ | kWHILE
1007
+ {
1008
+ lexer.cond.push true
1009
+ }
1010
+ expr_value do
1011
+ {
1012
+ lexer.cond.pop
1013
+ }
1014
+ compstmt kEND
1015
+ {
1016
+ result = new_while val[5], val[2], true
1017
+ }
1018
+ | kUNTIL
1019
+ {
1020
+ lexer.cond.push true
1021
+ }
1022
+ expr_value do
1023
+ {
1024
+ lexer.cond.pop
1025
+ }
1026
+ compstmt kEND
1027
+ {
1028
+ result = new_until val[5], val[2], true
1029
+ }
1030
+ | kCASE expr_value opt_terms case_body kEND
1031
+ {
1032
+ result = new_case val[1], val[3]
1033
+ }
1034
+ | kCASE opt_terms case_body kEND
1035
+ {
1036
+ result = new_case nil, val[2]
1037
+ }
1038
+ | kCASE opt_terms kELSE compstmt kEND # TODO: need a test
1039
+ {
1040
+ result = new_case nil, val[3]
1041
+ }
1042
+ | kFOR block_var kIN
1043
+ {
1044
+ lexer.cond.push true
1045
+ }
1046
+ expr_value do
1047
+ {
1048
+ lexer.cond.pop
1049
+ }
1050
+ compstmt kEND
1051
+ {
1052
+ result = new_for val[4], val[1], val[7]
1053
+ }
1054
+ | kCLASS
1055
+ {
1056
+ result = self.lexer.lineno
1057
+ }
1058
+ cpath superclass
1059
+ {
1060
+ self.comments.push self.lexer.comments
1061
+ if (self.in_def || self.in_single > 0) then
1062
+ yyerror "class definition in method body"
1063
+ end
1064
+ self.env.extend
1065
+ }
1066
+ bodystmt kEND
1067
+ {
1068
+ result = new_class val
1069
+ self.env.unextend
1070
+ }
1071
+ | kCLASS tLSHFT
1072
+ {
1073
+ result = self.lexer.lineno
1074
+ }
1075
+ expr
1076
+ {
1077
+ result = self.in_def
1078
+ self.in_def = false
1079
+ }
1080
+ term
1081
+ {
1082
+ result = self.in_single
1083
+ self.in_single = 0
1084
+ self.env.extend
1085
+ }
1086
+ bodystmt kEND
1087
+ {
1088
+ result = new_sclass val
1089
+ self.env.unextend
1090
+ }
1091
+ | kMODULE
1092
+ {
1093
+ result = self.lexer.lineno
1094
+ }
1095
+ cpath
1096
+ {
1097
+ self.comments.push self.lexer.comments
1098
+ yyerror "module definition in method body" if
1099
+ self.in_def or self.in_single > 0
1100
+
1101
+ self.env.extend
1102
+ }
1103
+ bodystmt kEND
1104
+ {
1105
+ result = new_module val
1106
+ self.env.unextend
1107
+ }
1108
+ | kDEF fname
1109
+ {
1110
+ self.comments.push self.lexer.comments
1111
+ self.in_def = true
1112
+ self.env.extend
1113
+ result = lexer.lineno, lexer.src.beginning_of_line?
1114
+ }
1115
+ f_arglist bodystmt kEND
1116
+ {
1117
+ result = new_defn val
1118
+ self.env.unextend
1119
+ self.in_def = false
1120
+ }
1121
+ | kDEF singleton dot_or_colon
1122
+ {
1123
+ self.comments.push self.lexer.comments
1124
+ lexer.lex_state = :expr_fname
1125
+ }
1126
+ fname
1127
+ {
1128
+ self.in_single += 1
1129
+ self.env.extend
1130
+ lexer.lex_state = :expr_end # force for args
1131
+ }
1132
+ f_arglist bodystmt kEND
1133
+ {
1134
+ result = new_defs val
1135
+
1136
+ self.env.unextend
1137
+ self.in_single -= 1
1138
+ }
1139
+ | kBREAK
1140
+ {
1141
+ result = s(:break)
1142
+ }
1143
+ | kNEXT
1144
+ {
1145
+ result = s(:next)
1146
+ }
1147
+ | kREDO
1148
+ {
1149
+ result = s(:redo)
1150
+ }
1151
+ | kRETRY
1152
+ {
1153
+ result = s(:retry)
1154
+ }
1155
+
1156
+ primary_value: primary
1157
+ {
1158
+ result = value_expr(val[0])
1159
+ }
1160
+
1161
+ then: term
1162
+ | tCOLON
1163
+ | kTHEN
1164
+ | term kTHEN
1165
+
1166
+ do: term
1167
+ | tCOLON
1168
+ | kDO_COND
1169
+
1170
+ if_tail: opt_else
1171
+ | kELSIF expr_value then compstmt if_tail
1172
+ {
1173
+ result = s(:if, val[1], val[3], val[4])
1174
+ }
1175
+
1176
+ opt_else: none
1177
+ | kELSE compstmt
1178
+ {
1179
+ result = val[1]
1180
+ }
1181
+
1182
+ block_var: lhs
1183
+ | mlhs
1184
+ {
1185
+ val[0].delete_at 1 if val[0][1].nil? # HACK
1186
+ }
1187
+
1188
+ opt_block_var: none
1189
+ | tPIPE tPIPE
1190
+ {
1191
+ result = 0
1192
+ }
1193
+ | tOROP
1194
+ {
1195
+ result = 0
1196
+ }
1197
+ | tPIPE block_var tPIPE
1198
+ {
1199
+ result = val[1]
1200
+ }
1201
+
1202
+ do_block: kDO_BLOCK
1203
+ {
1204
+ self.env.extend :dynamic
1205
+ }
1206
+ opt_block_var
1207
+ {
1208
+ result = self.env.dynamic.keys
1209
+ }
1210
+ compstmt kEND
1211
+ {
1212
+ vars = val[2]
1213
+ body = val[4]
1214
+ result = new_iter nil, vars, body
1215
+
1216
+ self.env.unextend
1217
+ }
1218
+
1219
+ block_call: command do_block
1220
+ {
1221
+ raise SyntaxError, "Both block arg and actual block given." if
1222
+ val[0] && val[0][0] == :blockpass
1223
+
1224
+ result = val[1]
1225
+ result.insert 1, val[0]
1226
+ }
1227
+ | block_call tDOT operation2 opt_paren_args
1228
+ {
1229
+ result = new_call val[0], val[2], val[3]
1230
+ }
1231
+ | block_call tCOLON2 operation2 opt_paren_args
1232
+ {
1233
+ result = new_call val[0], val[2], val[3]
1234
+ }
1235
+
1236
+ method_call: operation
1237
+ {
1238
+ result = self.lexer.lineno
1239
+ }
1240
+ paren_args
1241
+ {
1242
+ result = new_call nil, val[0].to_sym, val[2]
1243
+ }
1244
+ | primary_value tDOT operation2 opt_paren_args
1245
+ {
1246
+ result = new_call val[0], val[2].to_sym, val[3]
1247
+ }
1248
+ | primary_value tCOLON2 operation2 paren_args
1249
+ {
1250
+ result = new_call val[0], val[2].to_sym, val[3]
1251
+ }
1252
+ | primary_value tCOLON2 operation3
1253
+ {
1254
+ result = new_call val[0], val[2].to_sym
1255
+ }
1256
+ | kSUPER paren_args
1257
+ {
1258
+ result = new_super val[1]
1259
+ }
1260
+ | kSUPER
1261
+ {
1262
+ result = s(:zsuper)
1263
+ }
1264
+
1265
+ brace_block: tLCURLY
1266
+ {
1267
+ self.env.extend :dynamic
1268
+ result = self.lexer.lineno
1269
+ }
1270
+ opt_block_var
1271
+ {
1272
+ result = self.env.dynamic.keys
1273
+ }
1274
+ compstmt tRCURLY
1275
+ {
1276
+ # REFACTOR
1277
+ args = val[2]
1278
+ body = val[4]
1279
+ result = new_iter nil, args, body
1280
+ self.env.unextend
1281
+ result.line = val[1]
1282
+ }
1283
+ | kDO
1284
+ {
1285
+ self.env.extend :dynamic
1286
+ result = self.lexer.lineno
1287
+ }
1288
+ opt_block_var
1289
+ {
1290
+ result = self.env.dynamic.keys
1291
+ }
1292
+ compstmt kEND
1293
+ {
1294
+ args = val[2]
1295
+ body = val[4]
1296
+ result = new_iter nil, args, body
1297
+ self.env.unextend
1298
+ result.line = val[1]
1299
+ }
1300
+
1301
+ case_body: kWHEN
1302
+ {
1303
+ result = self.lexer.lineno
1304
+ }
1305
+ when_args then compstmt cases
1306
+ {
1307
+ result = s(:when, val[2], val[4])
1308
+ result.line = val[1]
1309
+ result << val[5] if val[5]
1310
+ }
1311
+
1312
+ when_args: args
1313
+ | args tCOMMA tSTAR arg_value
1314
+ {
1315
+ result = self.list_append val[0], s(:when, val[3], nil)
1316
+ }
1317
+ | tSTAR arg_value
1318
+ {
1319
+ result = s(:array, s(:when, val[1], nil))
1320
+ }
1321
+
1322
+ cases: opt_else | case_body
1323
+
1324
+ opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
1325
+ {
1326
+ klasses, var, body, rest = val[1], val[2], val[4], val[5]
1327
+
1328
+ klasses ||= s(:array)
1329
+ klasses << node_assign(var, s(:gvar, :"$!")) if var
1330
+
1331
+ result = s(:resbody, klasses, body)
1332
+ result << rest if rest # UGH, rewritten above
1333
+ }
1334
+ |
1335
+ {
1336
+ result = nil
1337
+ }
1338
+
1339
+ exc_list: arg_value
1340
+ {
1341
+ result = s(:array, val[0])
1342
+ }
1343
+ | mrhs
1344
+ | none
1345
+
1346
+ exc_var: tASSOC lhs
1347
+ {
1348
+ result = val[1]
1349
+ }
1350
+ | none
1351
+
1352
+ opt_ensure: kENSURE compstmt
1353
+ {
1354
+ if (val[1] != nil) then
1355
+ result = val[1]
1356
+ else
1357
+ result = s(:nil)
1358
+ end
1359
+ }
1360
+ | none
1361
+
1362
+ literal: numeric { result = s(:lit, val[0]) }
1363
+ | symbol { result = s(:lit, val[0]) }
1364
+ | dsym
1365
+
1366
+ strings: string
1367
+ {
1368
+ val[0] = s(:dstr, val[0].value) if val[0][0] == :evstr
1369
+ result = val[0]
1370
+ }
1371
+
1372
+ string: string1
1373
+ | string string1
1374
+ {
1375
+ result = self.literal_concat val[0], val[1]
1376
+ }
1377
+
1378
+ string1: tSTRING_BEG string_contents tSTRING_END
1379
+ {
1380
+ result = val[1]
1381
+ }
1382
+ | tSTRING
1383
+ {
1384
+ result = s(:str, val[0])
1385
+ }
1386
+
1387
+ xstring: tXSTRING_BEG xstring_contents tSTRING_END
1388
+ {
1389
+ result = new_xstring val[1]
1390
+ }
1391
+
1392
+ regexp: tREGEXP_BEG xstring_contents tREGEXP_END
1393
+ {
1394
+ result = new_regexp val
1395
+ }
1396
+
1397
+ words: tWORDS_BEG tSPACE tSTRING_END
1398
+ {
1399
+ result = s(:array)
1400
+ }
1401
+ | tWORDS_BEG word_list tSTRING_END
1402
+ {
1403
+ result = val[1]
1404
+ }
1405
+
1406
+ word_list: none
1407
+ {
1408
+ result = s(:array)
1409
+ }
1410
+ | word_list word tSPACE
1411
+ {
1412
+ word = val[1][0] == :evstr ? s(:dstr, "", val[1]) : val[1]
1413
+ result = val[0] << word
1414
+ }
1415
+
1416
+ word: string_content
1417
+ | word string_content
1418
+ {
1419
+ result = self.literal_concat val[0], val[1]
1420
+ }
1421
+
1422
+ awords: tAWORDS_BEG tSPACE tSTRING_END
1423
+ {
1424
+ result = s(:array)
1425
+ }
1426
+ | tAWORDS_BEG qword_list tSTRING_END
1427
+ {
1428
+ result = val[1]
1429
+ }
1430
+
1431
+ qword_list: none
1432
+ {
1433
+ result = s(:array)
1434
+ }
1435
+ | qword_list tSTRING_CONTENT tSPACE
1436
+ {
1437
+ result = val[0] << s(:str, val[1])
1438
+ }
1439
+
1440
+ string_contents: none
1441
+ {
1442
+ result = s(:str, "")
1443
+ }
1444
+ | string_contents string_content
1445
+ {
1446
+ result = literal_concat(val[0], val[1])
1447
+ }
1448
+
1449
+ xstring_contents: none
1450
+ {
1451
+ result = nil
1452
+ }
1453
+ | xstring_contents string_content
1454
+ {
1455
+ result = literal_concat(val[0], val[1])
1456
+ }
1457
+
1458
+ string_content: tSTRING_CONTENT
1459
+ {
1460
+ result = s(:str, val[0])
1461
+ }
1462
+ | tSTRING_DVAR
1463
+ {
1464
+ result = lexer.lex_strterm
1465
+ lexer.lex_strterm = nil
1466
+ lexer.lex_state = :expr_beg
1467
+ }
1468
+ string_dvar
1469
+ {
1470
+ lexer.lex_strterm = val[1]
1471
+ result = s(:evstr, val[2])
1472
+ }
1473
+ | tSTRING_DBEG
1474
+ {
1475
+ result = lexer.lex_strterm
1476
+ lexer.lex_strterm = nil
1477
+ lexer.lex_state = :expr_beg
1478
+ lexer.cond.push false
1479
+ lexer.cmdarg.push false
1480
+ }
1481
+ compstmt tRCURLY
1482
+ {
1483
+ lexer.lex_strterm = val[1]
1484
+ lexer.cond.lexpop
1485
+ lexer.cmdarg.lexpop
1486
+
1487
+ case val[2]
1488
+ when Sexp then
1489
+ case val[2][0]
1490
+ when :str, :dstr, :evstr then
1491
+ result = val[2]
1492
+ else
1493
+ result = s(:evstr, val[2])
1494
+ end
1495
+ when nil then
1496
+ result = s(:evstr)
1497
+ else
1498
+ raise "unknown rescue body: #{val[2].inspect}"
1499
+ end
1500
+ }
1501
+
1502
+ string_dvar: tGVAR { result = s(:gvar, val[0].to_sym) }
1503
+ | tIVAR { result = s(:ivar, val[0].to_sym) }
1504
+ | tCVAR { result = s(:cvar, val[0].to_sym) }
1505
+ | backref
1506
+
1507
+
1508
+ symbol: tSYMBEG sym
1509
+ {
1510
+ lexer.lex_state = :expr_end
1511
+ result = val[1].to_sym
1512
+ }
1513
+ | tSYMBOL
1514
+ {
1515
+ result = val[0].to_sym
1516
+ }
1517
+
1518
+ sym: fname | tIVAR | tGVAR | tCVAR
1519
+
1520
+ dsym: tSYMBEG xstring_contents tSTRING_END
1521
+ {
1522
+ lexer.lex_state = :expr_end
1523
+ result = val[1]
1524
+
1525
+ yyerror "empty symbol literal" if
1526
+ result.nil? or result.empty?
1527
+
1528
+ case result[0]
1529
+ when :dstr then
1530
+ result[0] = :dsym
1531
+ when :str then
1532
+ result = s(:lit, result.last.intern)
1533
+ else
1534
+ result = s(:dsym, "", result)
1535
+ end
1536
+ }
1537
+
1538
+ numeric: tINTEGER
1539
+ | tFLOAT
1540
+ | tUMINUS_NUM tINTEGER =tLOWEST
1541
+ {
1542
+ result = -val[1] # TODO: pt_testcase
1543
+ }
1544
+ | tUMINUS_NUM tFLOAT =tLOWEST
1545
+ {
1546
+ result = -val[1] # TODO: pt_testcase
1547
+ }
1548
+
1549
+ variable: tIDENTIFIER
1550
+ | tIVAR
1551
+ | tGVAR
1552
+ | tCONSTANT
1553
+ | tCVAR
1554
+ | kNIL { result = :nil }
1555
+ | kSELF { result = :self }
1556
+ | kTRUE { result = :true }
1557
+ | kFALSE { result = :false }
1558
+ | k__FILE__ { result = :__FILE__ }
1559
+ | k__LINE__ { result = :__LINE__ }
1560
+
1561
+ var_ref: variable
1562
+ {
1563
+ result = self.gettable val[0]
1564
+ }
1565
+
1566
+ var_lhs: variable
1567
+ {
1568
+ result = self.assignable val[0]
1569
+ }
1570
+
1571
+ backref: tNTH_REF { result = s(:nth_ref, val[0]) }
1572
+ | tBACK_REF { result = s(:back_ref, val[0]) }
1573
+
1574
+ superclass: term
1575
+ {
1576
+ result = nil
1577
+ }
1578
+ | tLT
1579
+ {
1580
+ lexer.lex_state = :expr_beg
1581
+ }
1582
+ expr_value term
1583
+ {
1584
+ result = val[2]
1585
+ }
1586
+ | error term
1587
+ {
1588
+ yyerrok
1589
+ result = nil
1590
+ }
1591
+
1592
+ f_arglist: tLPAREN2 f_args opt_nl tRPAREN
1593
+ {
1594
+ result = val[1]
1595
+ lexer.lex_state = :expr_beg
1596
+ }
1597
+ | f_args term
1598
+ {
1599
+ result = val[0]
1600
+ }
1601
+
1602
+ f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg
1603
+ {
1604
+ result = args val[0], val[2], val[4], val[5]
1605
+ }
1606
+ | f_arg tCOMMA f_optarg opt_f_block_arg
1607
+ {
1608
+ result = args val[0], val[2], nil, val[3]
1609
+ }
1610
+ | f_arg tCOMMA f_rest_arg opt_f_block_arg
1611
+ {
1612
+ result = args val[0], nil, val[2], val[3]
1613
+ }
1614
+ | f_arg opt_f_block_arg
1615
+ {
1616
+ result = args val[0], nil, nil, val[1]
1617
+ }
1618
+ | f_optarg tCOMMA f_rest_arg opt_f_block_arg
1619
+ {
1620
+ result = args nil, val[0], val[2], val[3]
1621
+ }
1622
+ | f_optarg opt_f_block_arg
1623
+ {
1624
+ result = args nil, val[0], nil, val[1]
1625
+ }
1626
+ | f_rest_arg opt_f_block_arg
1627
+ {
1628
+ result = args nil, nil, val[0], val[1]
1629
+ }
1630
+ | f_block_arg
1631
+ {
1632
+ result = args nil, nil, nil, val[0]
1633
+ }
1634
+ |
1635
+ {
1636
+ result = args nil, nil, nil, nil
1637
+ }
1638
+
1639
+ f_norm_arg: tCONSTANT
1640
+ {
1641
+ yyerror "formal argument cannot be a constant: #{val[0]}"
1642
+ }
1643
+ | tIVAR
1644
+ {
1645
+ yyerror "formal argument cannot be an instance variable"
1646
+ }
1647
+ | tCVAR
1648
+ {
1649
+ yyerror "formal argument cannot be a class variable"
1650
+ }
1651
+ | tIDENTIFIER
1652
+ {
1653
+ identifier = val[0].to_sym
1654
+ self.env[identifier] = :lvar
1655
+
1656
+ result = val[0]
1657
+ }
1658
+
1659
+ f_arg: f_norm_arg
1660
+ {
1661
+ result = s(:args)
1662
+ result << val[0].to_sym
1663
+ }
1664
+ | f_arg tCOMMA f_norm_arg
1665
+ {
1666
+ val[0] << val[2].to_sym
1667
+ result = val[0]
1668
+ }
1669
+
1670
+ f_opt: tIDENTIFIER tEQL arg_value
1671
+ {
1672
+ result = self.assignable val[0], val[2]
1673
+ # TODO: detect duplicate names
1674
+ }
1675
+
1676
+ f_optarg: f_opt
1677
+ {
1678
+ result = s(:block, val[0])
1679
+ }
1680
+ | f_optarg tCOMMA f_opt
1681
+ {
1682
+ result = self.append_to_block val[0], val[2]
1683
+ }
1684
+
1685
+ restarg_mark: tSTAR2 | tSTAR
1686
+
1687
+ f_rest_arg: restarg_mark tIDENTIFIER
1688
+ {
1689
+ # TODO: differs from parse.y - needs tests
1690
+ name = val[1].to_sym
1691
+ self.assignable name
1692
+ result = :"*#{name}"
1693
+ }
1694
+ | restarg_mark
1695
+ {
1696
+ name = :"*"
1697
+ self.env[name] = :lvar
1698
+ result = name
1699
+ }
1700
+
1701
+ blkarg_mark: tAMPER2 | tAMPER
1702
+
1703
+ f_block_arg: blkarg_mark tIDENTIFIER
1704
+ {
1705
+ identifier = val[1].to_sym
1706
+
1707
+ self.env[identifier] = :lvar
1708
+ result = s(:block_arg, identifier.to_sym)
1709
+ }
1710
+
1711
+ opt_f_block_arg: tCOMMA f_block_arg
1712
+ {
1713
+ result = val[1]
1714
+ }
1715
+ |
1716
+ {
1717
+ result = nil
1718
+ }
1719
+
1720
+ singleton: var_ref
1721
+ | tLPAREN2
1722
+ {
1723
+ lexer.lex_state = :expr_beg
1724
+ }
1725
+ expr opt_nl tRPAREN
1726
+ {
1727
+ result = val[2]
1728
+ yyerror "Can't define single method for literals." if
1729
+ result[0] == :lit
1730
+ }
1731
+
1732
+ assoc_list: none # [!nil]
1733
+ {
1734
+ result = s(:array)
1735
+ }
1736
+ | assocs trailer # [!nil]
1737
+ {
1738
+ result = val[0]
1739
+ }
1740
+ | args trailer
1741
+ {
1742
+ size = val[0].size
1743
+ if (size % 2 != 1) then # != 1 because of leading :array
1744
+ yyerror "Odd number (#{size}) list for Hash. #{val[0].inspect}"
1745
+ end
1746
+ result = val[0]
1747
+ }
1748
+
1749
+ assocs: assoc
1750
+ | assocs tCOMMA assoc
1751
+ {
1752
+ list = val[0].dup
1753
+ more = val[2][1..-1]
1754
+ list.push(*more) unless more.empty?
1755
+ result = list
1756
+ }
1757
+
1758
+ assoc: arg_value tASSOC arg_value
1759
+ {
1760
+ result = s(:array, val[0], val[2])
1761
+ }
1762
+
1763
+ operation: tIDENTIFIER | tCONSTANT | tFID
1764
+ operation2: tIDENTIFIER | tCONSTANT | tFID | op
1765
+ operation3: tIDENTIFIER | tFID | op
1766
+ dot_or_colon: tDOT | tCOLON2
1767
+ opt_terms: | terms
1768
+ opt_nl: | tNL
1769
+ trailer: | tNL | tCOMMA
1770
+
1771
+ term: tSEMI { yyerrok }
1772
+ | tNL
1773
+
1774
+ terms: term
1775
+ | terms tSEMI { yyerrok }
1776
+
1777
+ none: { result = nil }
1778
+
1779
+ none_block_pass: { result = nil }
1780
+
1781
+ end
1782
+
1783
+ ---- inner
1784
+
1785
+ require "ruby_lexer"
1786
+ require "ruby_parser_extras"
1787
+
1788
+ # Local Variables: **
1789
+ # racc-token-length-max:14 **
1790
+ # End: **