fabiokung-ruby_parser 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/ruby_parser.y ADDED
@@ -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
+ result.endline = lexer.lineno
1119
+ self.env.unextend
1120
+ self.in_def = false
1121
+ }
1122
+ | kDEF singleton dot_or_colon
1123
+ {
1124
+ self.comments.push self.lexer.comments
1125
+ lexer.lex_state = :expr_fname
1126
+ }
1127
+ fname
1128
+ {
1129
+ self.in_single += 1
1130
+ self.env.extend
1131
+ lexer.lex_state = :expr_end # force for args
1132
+ }
1133
+ f_arglist bodystmt kEND
1134
+ {
1135
+ result = new_defs val
1136
+
1137
+ self.env.unextend
1138
+ self.in_single -= 1
1139
+ }
1140
+ | kBREAK
1141
+ {
1142
+ result = s(:break)
1143
+ }
1144
+ | kNEXT
1145
+ {
1146
+ result = s(:next)
1147
+ }
1148
+ | kREDO
1149
+ {
1150
+ result = s(:redo)
1151
+ }
1152
+ | kRETRY
1153
+ {
1154
+ result = s(:retry)
1155
+ }
1156
+
1157
+ primary_value: primary
1158
+ {
1159
+ result = value_expr(val[0])
1160
+ }
1161
+
1162
+ then: term
1163
+ | tCOLON
1164
+ | kTHEN
1165
+ | term kTHEN
1166
+
1167
+ do: term
1168
+ | tCOLON
1169
+ | kDO_COND
1170
+
1171
+ if_tail: opt_else
1172
+ | kELSIF expr_value then compstmt if_tail
1173
+ {
1174
+ result = s(:if, val[1], val[3], val[4])
1175
+ }
1176
+
1177
+ opt_else: none
1178
+ | kELSE compstmt
1179
+ {
1180
+ result = val[1]
1181
+ }
1182
+
1183
+ block_var: lhs
1184
+ | mlhs
1185
+ {
1186
+ val[0].delete_at 1 if val[0][1].nil? # HACK
1187
+ }
1188
+
1189
+ opt_block_var: none
1190
+ | tPIPE tPIPE
1191
+ {
1192
+ result = 0
1193
+ }
1194
+ | tOROP
1195
+ {
1196
+ result = 0
1197
+ }
1198
+ | tPIPE block_var tPIPE
1199
+ {
1200
+ result = val[1]
1201
+ }
1202
+
1203
+ do_block: kDO_BLOCK
1204
+ {
1205
+ self.env.extend :dynamic
1206
+ }
1207
+ opt_block_var
1208
+ {
1209
+ result = self.env.dynamic.keys
1210
+ }
1211
+ compstmt kEND
1212
+ {
1213
+ vars = val[2]
1214
+ body = val[4]
1215
+ result = new_iter nil, vars, body
1216
+
1217
+ self.env.unextend
1218
+ }
1219
+
1220
+ block_call: command do_block
1221
+ {
1222
+ raise SyntaxError, "Both block arg and actual block given." if
1223
+ val[0] && val[0][0] == :blockpass
1224
+
1225
+ result = val[1]
1226
+ result.insert 1, val[0]
1227
+ }
1228
+ | block_call tDOT operation2 opt_paren_args
1229
+ {
1230
+ result = new_call val[0], val[2], val[3]
1231
+ }
1232
+ | block_call tCOLON2 operation2 opt_paren_args
1233
+ {
1234
+ result = new_call val[0], val[2], val[3]
1235
+ }
1236
+
1237
+ method_call: operation
1238
+ {
1239
+ result = self.lexer.lineno
1240
+ }
1241
+ paren_args
1242
+ {
1243
+ result = new_call nil, val[0].to_sym, val[2]
1244
+ }
1245
+ | primary_value tDOT operation2 opt_paren_args
1246
+ {
1247
+ result = new_call val[0], val[2].to_sym, val[3]
1248
+ }
1249
+ | primary_value tCOLON2 operation2 paren_args
1250
+ {
1251
+ result = new_call val[0], val[2].to_sym, val[3]
1252
+ }
1253
+ | primary_value tCOLON2 operation3
1254
+ {
1255
+ result = new_call val[0], val[2].to_sym
1256
+ }
1257
+ | kSUPER paren_args
1258
+ {
1259
+ result = new_super val[1]
1260
+ }
1261
+ | kSUPER
1262
+ {
1263
+ result = s(:zsuper)
1264
+ }
1265
+
1266
+ brace_block: tLCURLY
1267
+ {
1268
+ self.env.extend :dynamic
1269
+ result = self.lexer.lineno
1270
+ }
1271
+ opt_block_var
1272
+ {
1273
+ result = self.env.dynamic.keys
1274
+ }
1275
+ compstmt tRCURLY
1276
+ {
1277
+ # REFACTOR
1278
+ args = val[2]
1279
+ body = val[4]
1280
+ result = new_iter nil, args, body
1281
+ self.env.unextend
1282
+ result.line = val[1]
1283
+ }
1284
+ | kDO
1285
+ {
1286
+ self.env.extend :dynamic
1287
+ result = self.lexer.lineno
1288
+ }
1289
+ opt_block_var
1290
+ {
1291
+ result = self.env.dynamic.keys
1292
+ }
1293
+ compstmt kEND
1294
+ {
1295
+ args = val[2]
1296
+ body = val[4]
1297
+ result = new_iter nil, args, body
1298
+ self.env.unextend
1299
+ result.line = val[1]
1300
+ }
1301
+
1302
+ case_body: kWHEN
1303
+ {
1304
+ result = self.lexer.lineno
1305
+ }
1306
+ when_args then compstmt cases
1307
+ {
1308
+ result = s(:when, val[2], val[4])
1309
+ result.line = val[1]
1310
+ result << val[5] if val[5]
1311
+ }
1312
+
1313
+ when_args: args
1314
+ | args tCOMMA tSTAR arg_value
1315
+ {
1316
+ result = self.list_append val[0], s(:when, val[3], nil)
1317
+ }
1318
+ | tSTAR arg_value
1319
+ {
1320
+ result = s(:array, s(:when, val[1], nil))
1321
+ }
1322
+
1323
+ cases: opt_else | case_body
1324
+
1325
+ opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
1326
+ {
1327
+ klasses, var, body, rest = val[1], val[2], val[4], val[5]
1328
+
1329
+ klasses ||= s(:array)
1330
+ klasses << node_assign(var, s(:gvar, :"$!")) if var
1331
+
1332
+ result = s(:resbody, klasses, body)
1333
+ result << rest if rest # UGH, rewritten above
1334
+ }
1335
+ |
1336
+ {
1337
+ result = nil
1338
+ }
1339
+
1340
+ exc_list: arg_value
1341
+ {
1342
+ result = s(:array, val[0])
1343
+ }
1344
+ | mrhs
1345
+ | none
1346
+
1347
+ exc_var: tASSOC lhs
1348
+ {
1349
+ result = val[1]
1350
+ }
1351
+ | none
1352
+
1353
+ opt_ensure: kENSURE compstmt
1354
+ {
1355
+ if (val[1] != nil) then
1356
+ result = val[1]
1357
+ else
1358
+ result = s(:nil)
1359
+ end
1360
+ }
1361
+ | none
1362
+
1363
+ literal: numeric { result = s(:lit, val[0]) }
1364
+ | symbol { result = s(:lit, val[0]) }
1365
+ | dsym
1366
+
1367
+ strings: string
1368
+ {
1369
+ val[0] = s(:dstr, val[0].value) if val[0][0] == :evstr
1370
+ result = val[0]
1371
+ }
1372
+
1373
+ string: string1
1374
+ | string string1
1375
+ {
1376
+ result = self.literal_concat val[0], val[1]
1377
+ }
1378
+
1379
+ string1: tSTRING_BEG string_contents tSTRING_END
1380
+ {
1381
+ result = val[1]
1382
+ }
1383
+ | tSTRING
1384
+ {
1385
+ result = s(:str, val[0])
1386
+ }
1387
+
1388
+ xstring: tXSTRING_BEG xstring_contents tSTRING_END
1389
+ {
1390
+ result = new_xstring val[1]
1391
+ }
1392
+
1393
+ regexp: tREGEXP_BEG xstring_contents tREGEXP_END
1394
+ {
1395
+ result = new_regexp val
1396
+ }
1397
+
1398
+ words: tWORDS_BEG tSPACE tSTRING_END
1399
+ {
1400
+ result = s(:array)
1401
+ }
1402
+ | tWORDS_BEG word_list tSTRING_END
1403
+ {
1404
+ result = val[1]
1405
+ }
1406
+
1407
+ word_list: none
1408
+ {
1409
+ result = s(:array)
1410
+ }
1411
+ | word_list word tSPACE
1412
+ {
1413
+ word = val[1][0] == :evstr ? s(:dstr, "", val[1]) : val[1]
1414
+ result = val[0] << word
1415
+ }
1416
+
1417
+ word: string_content
1418
+ | word string_content
1419
+ {
1420
+ result = self.literal_concat val[0], val[1]
1421
+ }
1422
+
1423
+ awords: tAWORDS_BEG tSPACE tSTRING_END
1424
+ {
1425
+ result = s(:array)
1426
+ }
1427
+ | tAWORDS_BEG qword_list tSTRING_END
1428
+ {
1429
+ result = val[1]
1430
+ }
1431
+
1432
+ qword_list: none
1433
+ {
1434
+ result = s(:array)
1435
+ }
1436
+ | qword_list tSTRING_CONTENT tSPACE
1437
+ {
1438
+ result = val[0] << s(:str, val[1])
1439
+ }
1440
+
1441
+ string_contents: none
1442
+ {
1443
+ result = s(:str, "")
1444
+ }
1445
+ | string_contents string_content
1446
+ {
1447
+ result = literal_concat(val[0], val[1])
1448
+ }
1449
+
1450
+ xstring_contents: none
1451
+ {
1452
+ result = nil
1453
+ }
1454
+ | xstring_contents string_content
1455
+ {
1456
+ result = literal_concat(val[0], val[1])
1457
+ }
1458
+
1459
+ string_content: tSTRING_CONTENT
1460
+ {
1461
+ result = s(:str, val[0])
1462
+ }
1463
+ | tSTRING_DVAR
1464
+ {
1465
+ result = lexer.lex_strterm
1466
+ lexer.lex_strterm = nil
1467
+ lexer.lex_state = :expr_beg
1468
+ }
1469
+ string_dvar
1470
+ {
1471
+ lexer.lex_strterm = val[1]
1472
+ result = s(:evstr, val[2])
1473
+ }
1474
+ | tSTRING_DBEG
1475
+ {
1476
+ result = lexer.lex_strterm
1477
+ lexer.lex_strterm = nil
1478
+ lexer.lex_state = :expr_beg
1479
+ lexer.cond.push false
1480
+ lexer.cmdarg.push false
1481
+ }
1482
+ compstmt tRCURLY
1483
+ {
1484
+ lexer.lex_strterm = val[1]
1485
+ lexer.cond.lexpop
1486
+ lexer.cmdarg.lexpop
1487
+
1488
+ case val[2]
1489
+ when Sexp then
1490
+ case val[2][0]
1491
+ when :str, :dstr, :evstr then
1492
+ result = val[2]
1493
+ else
1494
+ result = s(:evstr, val[2])
1495
+ end
1496
+ when nil then
1497
+ result = s(:evstr)
1498
+ else
1499
+ raise "unknown rescue body: #{val[2].inspect}"
1500
+ end
1501
+ }
1502
+
1503
+ string_dvar: tGVAR { result = s(:gvar, val[0].to_sym) }
1504
+ | tIVAR { result = s(:ivar, val[0].to_sym) }
1505
+ | tCVAR { result = s(:cvar, val[0].to_sym) }
1506
+ | backref
1507
+
1508
+
1509
+ symbol: tSYMBEG sym
1510
+ {
1511
+ lexer.lex_state = :expr_end
1512
+ result = val[1].to_sym
1513
+ }
1514
+ | tSYMBOL
1515
+ {
1516
+ result = val[0].to_sym
1517
+ }
1518
+
1519
+ sym: fname | tIVAR | tGVAR | tCVAR
1520
+
1521
+ dsym: tSYMBEG xstring_contents tSTRING_END
1522
+ {
1523
+ lexer.lex_state = :expr_end
1524
+ result = val[1]
1525
+
1526
+ yyerror "empty symbol literal" if
1527
+ result.nil? or result.empty?
1528
+
1529
+ case result[0]
1530
+ when :dstr then
1531
+ result[0] = :dsym
1532
+ when :str then
1533
+ result = s(:lit, result.last.intern)
1534
+ else
1535
+ result = s(:dsym, "", result)
1536
+ end
1537
+ }
1538
+
1539
+ numeric: tINTEGER
1540
+ | tFLOAT
1541
+ | tUMINUS_NUM tINTEGER =tLOWEST
1542
+ {
1543
+ result = -val[1] # TODO: pt_testcase
1544
+ }
1545
+ | tUMINUS_NUM tFLOAT =tLOWEST
1546
+ {
1547
+ result = -val[1] # TODO: pt_testcase
1548
+ }
1549
+
1550
+ variable: tIDENTIFIER
1551
+ | tIVAR
1552
+ | tGVAR
1553
+ | tCONSTANT
1554
+ | tCVAR
1555
+ | kNIL { result = :nil }
1556
+ | kSELF { result = :self }
1557
+ | kTRUE { result = :true }
1558
+ | kFALSE { result = :false }
1559
+ | k__FILE__ { result = :__FILE__ }
1560
+ | k__LINE__ { result = :__LINE__ }
1561
+
1562
+ var_ref: variable
1563
+ {
1564
+ result = self.gettable val[0]
1565
+ }
1566
+
1567
+ var_lhs: variable
1568
+ {
1569
+ result = self.assignable val[0]
1570
+ }
1571
+
1572
+ backref: tNTH_REF { result = s(:nth_ref, val[0]) }
1573
+ | tBACK_REF { result = s(:back_ref, val[0]) }
1574
+
1575
+ superclass: term
1576
+ {
1577
+ result = nil
1578
+ }
1579
+ | tLT
1580
+ {
1581
+ lexer.lex_state = :expr_beg
1582
+ }
1583
+ expr_value term
1584
+ {
1585
+ result = val[2]
1586
+ }
1587
+ | error term
1588
+ {
1589
+ yyerrok
1590
+ result = nil
1591
+ }
1592
+
1593
+ f_arglist: tLPAREN2 f_args opt_nl tRPAREN
1594
+ {
1595
+ result = val[1]
1596
+ lexer.lex_state = :expr_beg
1597
+ }
1598
+ | f_args term
1599
+ {
1600
+ result = val[0]
1601
+ }
1602
+
1603
+ f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg
1604
+ {
1605
+ result = args val[0], val[2], val[4], val[5]
1606
+ }
1607
+ | f_arg tCOMMA f_optarg opt_f_block_arg
1608
+ {
1609
+ result = args val[0], val[2], nil, val[3]
1610
+ }
1611
+ | f_arg tCOMMA f_rest_arg opt_f_block_arg
1612
+ {
1613
+ result = args val[0], nil, val[2], val[3]
1614
+ }
1615
+ | f_arg opt_f_block_arg
1616
+ {
1617
+ result = args val[0], nil, nil, val[1]
1618
+ }
1619
+ | f_optarg tCOMMA f_rest_arg opt_f_block_arg
1620
+ {
1621
+ result = args nil, val[0], val[2], val[3]
1622
+ }
1623
+ | f_optarg opt_f_block_arg
1624
+ {
1625
+ result = args nil, val[0], nil, val[1]
1626
+ }
1627
+ | f_rest_arg opt_f_block_arg
1628
+ {
1629
+ result = args nil, nil, val[0], val[1]
1630
+ }
1631
+ | f_block_arg
1632
+ {
1633
+ result = args nil, nil, nil, val[0]
1634
+ }
1635
+ |
1636
+ {
1637
+ result = args nil, nil, nil, nil
1638
+ }
1639
+
1640
+ f_norm_arg: tCONSTANT
1641
+ {
1642
+ yyerror "formal argument cannot be a constant: #{val[0]}"
1643
+ }
1644
+ | tIVAR
1645
+ {
1646
+ yyerror "formal argument cannot be an instance variable"
1647
+ }
1648
+ | tCVAR
1649
+ {
1650
+ yyerror "formal argument cannot be a class variable"
1651
+ }
1652
+ | tIDENTIFIER
1653
+ {
1654
+ identifier = val[0].to_sym
1655
+ self.env[identifier] = :lvar
1656
+
1657
+ result = val[0]
1658
+ }
1659
+
1660
+ f_arg: f_norm_arg
1661
+ {
1662
+ result = s(:args)
1663
+ result << val[0].to_sym
1664
+ }
1665
+ | f_arg tCOMMA f_norm_arg
1666
+ {
1667
+ val[0] << val[2].to_sym
1668
+ result = val[0]
1669
+ }
1670
+
1671
+ f_opt: tIDENTIFIER tEQL arg_value
1672
+ {
1673
+ result = self.assignable val[0], val[2]
1674
+ # TODO: detect duplicate names
1675
+ }
1676
+
1677
+ f_optarg: f_opt
1678
+ {
1679
+ result = s(:block, val[0])
1680
+ }
1681
+ | f_optarg tCOMMA f_opt
1682
+ {
1683
+ result = self.append_to_block val[0], val[2]
1684
+ }
1685
+
1686
+ restarg_mark: tSTAR2 | tSTAR
1687
+
1688
+ f_rest_arg: restarg_mark tIDENTIFIER
1689
+ {
1690
+ # TODO: differs from parse.y - needs tests
1691
+ name = val[1].to_sym
1692
+ self.assignable name
1693
+ result = :"*#{name}"
1694
+ }
1695
+ | restarg_mark
1696
+ {
1697
+ name = :"*"
1698
+ self.env[name] = :lvar
1699
+ result = name
1700
+ }
1701
+
1702
+ blkarg_mark: tAMPER2 | tAMPER
1703
+
1704
+ f_block_arg: blkarg_mark tIDENTIFIER
1705
+ {
1706
+ identifier = val[1].to_sym
1707
+
1708
+ self.env[identifier] = :lvar
1709
+ result = s(:block_arg, identifier.to_sym)
1710
+ }
1711
+
1712
+ opt_f_block_arg: tCOMMA f_block_arg
1713
+ {
1714
+ result = val[1]
1715
+ }
1716
+ |
1717
+ {
1718
+ result = nil
1719
+ }
1720
+
1721
+ singleton: var_ref
1722
+ | tLPAREN2
1723
+ {
1724
+ lexer.lex_state = :expr_beg
1725
+ }
1726
+ expr opt_nl tRPAREN
1727
+ {
1728
+ result = val[2]
1729
+ yyerror "Can't define single method for literals." if
1730
+ result[0] == :lit
1731
+ }
1732
+
1733
+ assoc_list: none # [!nil]
1734
+ {
1735
+ result = s(:array)
1736
+ }
1737
+ | assocs trailer # [!nil]
1738
+ {
1739
+ result = val[0]
1740
+ }
1741
+ | args trailer
1742
+ {
1743
+ size = val[0].size
1744
+ if (size % 2 != 1) then # != 1 because of leading :array
1745
+ yyerror "Odd number (#{size}) list for Hash. #{val[0].inspect}"
1746
+ end
1747
+ result = val[0]
1748
+ }
1749
+
1750
+ assocs: assoc
1751
+ | assocs tCOMMA assoc
1752
+ {
1753
+ list = val[0].dup
1754
+ more = val[2][1..-1]
1755
+ list.push(*more) unless more.empty?
1756
+ result = list
1757
+ }
1758
+
1759
+ assoc: arg_value tASSOC arg_value
1760
+ {
1761
+ result = s(:array, val[0], val[2])
1762
+ }
1763
+
1764
+ operation: tIDENTIFIER | tCONSTANT | tFID
1765
+ operation2: tIDENTIFIER | tCONSTANT | tFID | op
1766
+ operation3: tIDENTIFIER | tFID | op
1767
+ dot_or_colon: tDOT | tCOLON2
1768
+ opt_terms: | terms
1769
+ opt_nl: | tNL
1770
+ trailer: | tNL | tCOMMA
1771
+
1772
+ term: tSEMI { yyerrok }
1773
+ | tNL
1774
+
1775
+ terms: term
1776
+ | terms tSEMI { yyerrok }
1777
+
1778
+ none: { result = nil }
1779
+
1780
+ none_block_pass: { result = nil }
1781
+
1782
+ end
1783
+
1784
+ ---- inner
1785
+
1786
+ require "ruby_lexer"
1787
+
1788
+ # Local Variables: **
1789
+ # racc-token-length-max:14 **
1790
+ # End: **