ruby_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby_parser might be problematic. Click here for more details.

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