rogue_parser 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,1656 @@
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
19
+ 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 '?' ':'
36
+ left kRESCUE_MOD
37
+ right '=' 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
+ } 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.lex_state = :expr_fname } fitem {
84
+ result = s(:alias, val[1], val[3])
85
+ }
86
+ | kALIAS tGVAR tGVAR {
87
+ result = s(:valias, val[1].to_sym, val[2].to_sym)
88
+ }
89
+ | kALIAS tGVAR tBACK_REF {
90
+ result = s(:valias, val[1].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].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].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], val[4])
262
+ self.env.unextend;
263
+ }
264
+
265
+ command : operation command_args =tLOWEST {
266
+ result = new_fcall(val[0].to_sym, val[1])
267
+ }
268
+ | operation command_args cmd_brace_block {
269
+ result = new_fcall(val[0].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].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].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].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.lex_state = :expr_end
430
+ result = val[0];
431
+ }
432
+
433
+ | reswords {
434
+ lexer.lex_state = :expr_end
435
+ result = val[0];
436
+ }
437
+
438
+ fitem : fname { result = s(:lit, val[0].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.lex_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].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].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].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].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.node_type == :lit and v2.node_type == :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.node_type == :lit and v2.node_type == :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.lex_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.lex_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
+ | awords
803
+ | var_ref
804
+ | backref
805
+ | tFID {
806
+ result = s(:fcall, val[0].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.lex_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].to_sym)
827
+ }
828
+ | tCOLON3 tCONSTANT {
829
+ result = s(:colon3, val[1].to_sym)
830
+ }
831
+ | primary_value '[' aref_args tRBRACK {
832
+ if val[0].node_type == :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].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.node_type == :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
+ self.comments.push self.lexer.comments
964
+ if (self.in_def || self.in_single > 0) then
965
+ yyerror("class definition in method body");
966
+ end
967
+ self.env.extend
968
+ } bodystmt kEND {
969
+ scope = s(:scope, val[4]).compact
970
+ result = s(:class, val[1].last.to_sym, val[2], scope)
971
+ result.comments = self.comments.pop
972
+ self.env.unextend
973
+ }
974
+ | kCLASS tLSHFT expr {
975
+ result = self.in_def
976
+ self.in_def = false
977
+ } term {
978
+ result = self.in_single
979
+ self.in_single = 0
980
+ self.env.extend;
981
+ } bodystmt kEND {
982
+ scope = s(:scope, val[6]).compact
983
+ result = s(:sclass, val[2], scope)
984
+ self.env.unextend;
985
+ self.in_def = val[3]
986
+ self.in_single = val[5]
987
+ }
988
+ | kMODULE cpath {
989
+ self.comments.push self.lexer.comments
990
+ yyerror("module definition in method body") if
991
+ self.in_def or self.in_single > 0
992
+
993
+ self.env.extend;
994
+ } bodystmt kEND {
995
+ body = val[3] ? s(:scope, val[3]) : s(:scope)
996
+ result = s(:module, val[1].last.to_sym, body)
997
+ result.comments = self.comments.pop
998
+ self.env.unextend;
999
+ }
1000
+ | kDEF fname {
1001
+ self.comments.push self.lexer.comments
1002
+ self.in_def = true
1003
+ self.env.extend
1004
+ } f_arglist bodystmt kEND {
1005
+ name, args, body = val[1], val[3], val[4] # TODO: refactor
1006
+ name = name.to_sym
1007
+ body ||= s(:nil)
1008
+
1009
+ block_arg = args.block_arg(:remove)
1010
+ body = self.block_append(args, body, body && body[0] == :block)
1011
+ body.insert 2, block_arg if block_arg
1012
+ result = s(:defn, name, s(:scope, body))
1013
+ result.comments = self.comments.pop
1014
+
1015
+ self.env.unextend
1016
+ self.in_def = false
1017
+ }
1018
+ | kDEF singleton dot_or_colon { # 0-2, 3
1019
+ self.comments.push self.lexer.comments
1020
+ lexer.lex_state = :expr_fname
1021
+ } fname { # 4, 5
1022
+ self.in_single += 1
1023
+ self.env.extend;
1024
+ lexer.lex_state = :expr_end # force for args
1025
+ } f_arglist bodystmt kEND { # 6-8
1026
+ recv, name, args, body = val[1], val[4], val[6], val[7]
1027
+
1028
+ block_arg = args.block_arg(:remove)
1029
+ body = self.block_append(args, body, body && body[0] == :block)
1030
+ body.insert 2, block_arg if block_arg
1031
+
1032
+ result = s(:defs, recv, name.to_sym, s(:scope, body))
1033
+ result.comments = self.comments.pop
1034
+
1035
+ self.env.unextend;
1036
+ self.in_single -= 1
1037
+ }
1038
+ | kBREAK {
1039
+ result = s(:break)
1040
+ }
1041
+ | kNEXT {
1042
+ result = s(:next)
1043
+ }
1044
+ | kREDO {
1045
+ result = s(:redo)
1046
+ }
1047
+ | kRETRY {
1048
+ result = s(:retry)
1049
+ }
1050
+
1051
+ primary_value : primary {
1052
+ result = value_expr(val[0])
1053
+ }
1054
+
1055
+ then : term
1056
+ | ":"
1057
+ | kTHEN
1058
+ | term kTHEN
1059
+
1060
+ do : term
1061
+ | ":"
1062
+ | kDO_COND
1063
+
1064
+ if_tail : opt_else
1065
+ | kELSIF expr_value then compstmt if_tail {
1066
+ result = s(:if, val[1], val[3], val[4]);
1067
+ }
1068
+
1069
+ opt_else : none
1070
+ | kELSE compstmt {
1071
+ result = val[1];
1072
+ }
1073
+
1074
+ block_var : lhs
1075
+ | mlhs { val[0].delete_at 1 if val[0][1].nil? } # HACK
1076
+
1077
+ opt_block_var : none
1078
+ | tPIPE tPIPE {
1079
+ result = 0
1080
+ }
1081
+ | tOROP {
1082
+ result = 0
1083
+ }
1084
+ | tPIPE block_var tPIPE {
1085
+ result = val[1];
1086
+ }
1087
+
1088
+ do_block : kDO_BLOCK {
1089
+ self.env.extend :dynamic
1090
+ } opt_block_var { result = self.env.dynamic.keys }
1091
+ compstmt kEND {
1092
+
1093
+ vars = val[2]
1094
+ body = val[4]
1095
+
1096
+ result = s(:iter)
1097
+ result << vars
1098
+ result << val[1] if val[1]
1099
+ result << body if body
1100
+
1101
+ self.env.unextend;
1102
+ }
1103
+
1104
+ block_call : command do_block {
1105
+ raise SyntaxError, "Both block arg and actual block given." if
1106
+ val[0] && val[0][0] == :blockpass
1107
+
1108
+ result = val[1]
1109
+ result.insert 1, val[0]
1110
+ }
1111
+ | block_call tDOT operation2 opt_paren_args {
1112
+ result = s(:call, val[0], val[2]);
1113
+ result << val[3] if val[3]
1114
+ }
1115
+ | block_call tCOLON2 operation2 opt_paren_args {
1116
+ result = s(:call, val[0], val[2]);
1117
+ result << val[3] if val[3]
1118
+ }
1119
+
1120
+ method_call : operation paren_args {
1121
+ result = new_fcall(val[0].to_sym, val[1])
1122
+ }
1123
+ | primary_value tDOT operation2 opt_paren_args {
1124
+ result = new_call(val[0], val[2].to_sym, val[3])
1125
+ }
1126
+ | primary_value tCOLON2 operation2 paren_args {
1127
+ result = new_call(val[0], val[2].to_sym, val[3])
1128
+ }
1129
+ | primary_value tCOLON2 operation3 {
1130
+ result = new_call(val[0], val[2].to_sym)
1131
+ }
1132
+ | kSUPER paren_args {
1133
+ result = self.new_super(val[1]);
1134
+ }
1135
+ | kSUPER {
1136
+ result = s(:zsuper)
1137
+ }
1138
+
1139
+ brace_block : tLCURLY {
1140
+ self.env.extend :dynamic
1141
+ } opt_block_var { result = self.env.dynamic.keys }
1142
+ compstmt tRCURLY { # REFACTOR
1143
+ args = val[2]
1144
+ body = val[4]
1145
+ result = s(:iter)
1146
+ result << args
1147
+ result << body if body
1148
+ self.env.unextend
1149
+ }
1150
+ | kDO {
1151
+ self.env.extend :dynamic
1152
+ } opt_block_var { result = self.env.dynamic.keys }
1153
+ compstmt kEND {
1154
+ args = val[2]
1155
+ body = val[4]
1156
+ result = s(:iter)
1157
+ result << args
1158
+ result << body if body
1159
+ self.env.unextend
1160
+ }
1161
+
1162
+ case_body : kWHEN when_args then compstmt cases {
1163
+ result = s(:when, val[1], val[3])
1164
+ result << val[4] if val[4]
1165
+ }
1166
+
1167
+ when_args : args
1168
+ | args ',' tSTAR arg_value {
1169
+ result = self.list_append(val[0], s(:when, val[3], nil))
1170
+ }
1171
+ | tSTAR arg_value {
1172
+ result = s(:array, s(:when, val[1], nil));
1173
+ }
1174
+
1175
+ cases : opt_else | case_body
1176
+
1177
+ opt_rescue : kRESCUE exc_list exc_var then compstmt opt_rescue {
1178
+ result = s(:resbody, val[1])
1179
+ if val[2] then
1180
+ val[2] = node_assign(val[2], s(:gvar, :"$!"))
1181
+
1182
+ strip = val[4] && val[4][0] == :block
1183
+ val[4] = block_append(val[2], val[4])
1184
+ val[4].push(*val[4].pop[1..-1]) if strip # HACK removes nested block from block_append
1185
+ end
1186
+
1187
+ result << val[4] if val[4]
1188
+ result << val[5] if val[5]
1189
+ }
1190
+ | {result = nil;}
1191
+
1192
+ exc_list : arg_value {
1193
+ result = s(:array, val[0]);
1194
+ }
1195
+ | mrhs
1196
+ | none
1197
+
1198
+ exc_var : tASSOC lhs {
1199
+ result = val[1];
1200
+ }
1201
+ | none
1202
+
1203
+ opt_ensure : kENSURE compstmt {
1204
+ if (val[1] != nil) then
1205
+ result = val[1];
1206
+ else
1207
+ result = s(:nil)
1208
+ end
1209
+ }
1210
+ | none
1211
+
1212
+ literal : numeric { result = s(:lit, val[0]) }
1213
+ | symbol { result = s(:lit, val[0]) }
1214
+ | dsym
1215
+
1216
+ strings : string {
1217
+ val[0] = s(:dstr, val[0].value) if val[0][0] == :evstr
1218
+ result = val[0];
1219
+ }
1220
+
1221
+ string : string1
1222
+ | string string1 {
1223
+ result = self.literal_concat(val[0], val[1]);
1224
+ }
1225
+
1226
+ string1 : tSTRING_BEG string_contents tSTRING_END {
1227
+ result = val[1];
1228
+ }
1229
+
1230
+ xstring : tXSTRING_BEG xstring_contents tSTRING_END {
1231
+ node = val[1]
1232
+
1233
+ unless node then
1234
+ node = s(:xstr, '')
1235
+ else
1236
+ case node[0]
1237
+ when :str
1238
+ node[0] = :xstr
1239
+ when :dstr
1240
+ node[0] = :dxstr
1241
+ else
1242
+ node = s(:dxstr, '', node)
1243
+ end
1244
+ end
1245
+
1246
+ result = node
1247
+ }
1248
+
1249
+ regexp : tREGEXP_BEG xstring_contents tREGEXP_END {
1250
+ node = val[1] || s(:str, '')
1251
+ options = val[2]
1252
+
1253
+ o, k = 0, nil
1254
+ options.split(//).each do |c| # FIX: this has a better home
1255
+ v = {
1256
+ 'x' => Regexp::EXTENDED,
1257
+ 'i' => Regexp::IGNORECASE,
1258
+ 'm' => Regexp::MULTILINE,
1259
+ 'o' => Regexp::ONCE,
1260
+ 'n' => Regexp::ENC_NONE,
1261
+ 'e' => Regexp::ENC_EUC,
1262
+ 's' => Regexp::ENC_SJIS,
1263
+ 'u' => Regexp::ENC_UTF8,
1264
+ }[c]
1265
+ raise "unknown regexp option: #{c}" unless v
1266
+ o += v
1267
+ k = c if c =~ /[esu]/
1268
+ end
1269
+
1270
+ case node[0]
1271
+ when :str then
1272
+ node[0] = :lit
1273
+ node[1] = if k then
1274
+ Regexp.new(node[1], o, k)
1275
+ else
1276
+ Regexp.new(node[1], o)
1277
+ end
1278
+ when :dstr then
1279
+ if options =~ /o/ then
1280
+ node[0] = :dregx_once
1281
+ else
1282
+ node[0] = :dregx
1283
+ end
1284
+ node << o if o and o != 0
1285
+ else
1286
+ node = s(:dregx, '', node);
1287
+ node[0] = :dregx_once if options =~ /o/
1288
+ node << o if o and o != 0
1289
+ end
1290
+
1291
+ result = node
1292
+ }
1293
+
1294
+ words : tWORDS_BEG ' ' tSTRING_END {
1295
+ result = s(:zarray);
1296
+ }
1297
+ | tWORDS_BEG word_list tSTRING_END {
1298
+ result = val[1];
1299
+ }
1300
+
1301
+ word_list : {
1302
+ result = s(:array)
1303
+ }
1304
+ | word_list word ' ' {
1305
+ word = val[1][0] == :evstr ? s(:dstr, '', val[1]) : val[1]
1306
+ result = val[0] << word
1307
+ }
1308
+
1309
+ word : string_content
1310
+ | word string_content {
1311
+ result = self.literal_concat(val[0], val[1]);
1312
+ }
1313
+
1314
+ awords : tAWORDS_BEG ' ' tSTRING_END {
1315
+ result = s(:zarray)
1316
+ }
1317
+ | tAWORDS_BEG qword_list tSTRING_END {
1318
+ result = val[1]
1319
+ }
1320
+
1321
+ qword_list : {
1322
+ result = s(:array)
1323
+ }
1324
+ | qword_list tSTRING_CONTENT ' ' {
1325
+ result = val[0] << val[1]
1326
+ }
1327
+
1328
+ string_contents: { result = s(:str, "") }
1329
+ | string_contents string_content {
1330
+ result = literal_concat(val[0], val[1])
1331
+ }
1332
+
1333
+ xstring_contents: { result = nil }
1334
+ | xstring_contents string_content {
1335
+ result = literal_concat(val[0], val[1])
1336
+ }
1337
+
1338
+ string_content : tSTRING_CONTENT
1339
+ | tSTRING_DVAR {
1340
+ result = lexer.lex_strterm;
1341
+ lexer.lex_strterm = nil
1342
+ lexer.lex_state = :expr_beg
1343
+ } string_dvar {
1344
+ lexer.lex_strterm = val[1]
1345
+ result = s(:evstr, val[2]);
1346
+ }
1347
+ | tSTRING_DBEG {
1348
+ result = lexer.lex_strterm;
1349
+ lexer.lex_strterm = nil
1350
+ lexer.lex_state = :expr_beg
1351
+ lexer.cond.push false
1352
+ lexer.cmdarg.push false
1353
+ } compstmt tRCURLY {
1354
+ lexer.lex_strterm = val[1]
1355
+ lexer.cond.lexpop
1356
+ lexer.cmdarg.lexpop
1357
+ case val[2][0]
1358
+ when :str, :dstr, :evstr then
1359
+ result = val[2]
1360
+ else
1361
+ result = s(:evstr, val[2])
1362
+ end
1363
+ }
1364
+
1365
+ string_dvar : tGVAR {
1366
+ result = s(:gvar, val[0].to_sym);
1367
+ }
1368
+ | tIVAR {
1369
+ result = s(:ivar, val[0].to_sym);
1370
+ }
1371
+ | tCVAR {
1372
+ result = s(:cvar, val[0].to_sym);
1373
+ }
1374
+ | backref
1375
+
1376
+
1377
+ symbol : tSYMBEG sym {
1378
+ lexer.lex_state = :expr_end
1379
+ result = val[1].to_sym
1380
+ }
1381
+
1382
+ sym : fname | tIVAR | tGVAR | tCVAR
1383
+
1384
+ dsym : tSYMBEG xstring_contents tSTRING_END {
1385
+ lexer.lex_state = :expr_end
1386
+ result = val[1]
1387
+
1388
+ yyerror("empty symbol literal") if result.nil? or result.empty?
1389
+
1390
+ case result[0]
1391
+ when :dstr then
1392
+ result[0] = :dsym
1393
+ when :str then
1394
+ result = s(:lit, result.last.intern)
1395
+ else
1396
+ result = s(:dsym, '', result)
1397
+ end
1398
+
1399
+ }
1400
+
1401
+ numeric : tINTEGER
1402
+ | tFLOAT
1403
+ | tUMINUS_NUM tINTEGER =tLOWEST {
1404
+ result = -val[1] # TODO: pt_testcase
1405
+ }
1406
+ | tUMINUS_NUM tFLOAT =tLOWEST {
1407
+ result = -val[1] # TODO: pt_testcase
1408
+ }
1409
+
1410
+ variable : tIDENTIFIER
1411
+ | tIVAR
1412
+ | tGVAR
1413
+ | tCONSTANT
1414
+ | tCVAR
1415
+ | kNIL {
1416
+ result = s(:nil)
1417
+ }
1418
+ | kSELF {
1419
+ result = s(:self)
1420
+ }
1421
+ | kTRUE {
1422
+ result = s(:true)
1423
+ }
1424
+ | kFALSE {
1425
+ result = s(:false)
1426
+ }
1427
+ | k__FILE__ {
1428
+ result = :"__FILE__"
1429
+ }
1430
+ | k__LINE__ {
1431
+ result = :"__LINE__"
1432
+ }
1433
+
1434
+ var_ref : variable {
1435
+ result = self.gettable(val[0])
1436
+ }
1437
+
1438
+ var_lhs : variable {
1439
+ result = self.assignable(val[0]);
1440
+ }
1441
+
1442
+ backref : tNTH_REF | tBACK_REF
1443
+
1444
+ superclass : term {
1445
+ result = nil;
1446
+ }
1447
+ | tLT {
1448
+ lexer.lex_state = :expr_beg
1449
+ } expr_value term {
1450
+ result = val[2];
1451
+ }
1452
+ | error term {
1453
+ yyerrok;
1454
+ result = nil;
1455
+ }
1456
+
1457
+ f_arglist : tLPAREN2 f_args opt_nl tRPAREN {
1458
+ result = val[1];
1459
+ lexer.lex_state = :expr_beg
1460
+ }
1461
+ | f_args term {
1462
+ result = val[0];
1463
+ }
1464
+
1465
+ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg {
1466
+ result = val[0]
1467
+ if val[2] then
1468
+ val[2][1..-1].each do |lasgn| # FIX clean sexp iter
1469
+ raise "wtf? #{lasgn.inspect}" unless lasgn[0] == :lasgn
1470
+ result << lasgn[1]
1471
+ end
1472
+ end
1473
+ result << val[4] if val[4]
1474
+ result << val[2] if val[2]
1475
+ result << val[5] if val[5]
1476
+ }
1477
+ | f_arg ',' f_optarg opt_f_block_arg {
1478
+ result = val[0]
1479
+ if val[2] then
1480
+ val[2][1..-1].each do |lasgn| # FIX clean sexp iter
1481
+ raise "wtf? #{lasgn.inspect}" unless lasgn[0] == :lasgn
1482
+ result << lasgn[1]
1483
+ end
1484
+ end
1485
+ result << val[2] if val[2]
1486
+ result << val[3] if val[3]
1487
+ }
1488
+ | f_arg ',' f_rest_arg opt_f_block_arg {
1489
+ result = val[0]
1490
+ result << val[2] if val[2]
1491
+ result << val[3] if val[3]
1492
+ }
1493
+ | f_arg opt_f_block_arg {
1494
+ result = val[0]
1495
+ result << val[1] if val[1]
1496
+ }
1497
+ | f_optarg ',' f_rest_arg opt_f_block_arg {
1498
+ result = s(:args)
1499
+ if val[0] then
1500
+ val[0][1..-1].each do |lasgn| # FIX clean sexp iter
1501
+ raise "wtf? #{lasgn.inspect}" unless lasgn[0] == :lasgn
1502
+ result << lasgn[1]
1503
+ end
1504
+ end
1505
+
1506
+ result << val[2] if val[2]
1507
+ result << val[0] if val[0]
1508
+ result << val[3] if val[3]
1509
+ }
1510
+ | f_optarg opt_f_block_arg {
1511
+ result = s(:args)
1512
+ if val[0] then
1513
+ val[0][1..-1].each do |lasgn| # FIX clean sexp iter
1514
+ raise "wtf? #{lasgn.inspect}" unless lasgn[0] == :lasgn
1515
+ result << lasgn[1]
1516
+ end
1517
+ end
1518
+
1519
+ result << val[0] if val[0]
1520
+ result << val[1] if val[1]
1521
+ }
1522
+ | f_rest_arg opt_f_block_arg {
1523
+ result = s(:args, val[0], val[1]).compact
1524
+ }
1525
+ | f_block_arg {
1526
+ result = s(:args, val[0]).compact
1527
+ }
1528
+ | {
1529
+ result = s(:args)
1530
+ }
1531
+
1532
+ f_norm_arg : tCONSTANT {
1533
+ yyerror("formal argument cannot be a constant");
1534
+ }
1535
+ | tIVAR {
1536
+ yyerror("formal argument cannot be an instance variable");
1537
+ }
1538
+ | tCVAR {
1539
+ yyerror("formal argument cannot be a class variable");
1540
+ }
1541
+ | tIDENTIFIER {
1542
+ identifier = val[0].to_sym
1543
+ self.env[identifier] = :lvar
1544
+
1545
+ result = val[0];
1546
+ }
1547
+
1548
+ f_arg : f_norm_arg {
1549
+ result = s(:args)
1550
+ result << val[0].to_sym
1551
+ }
1552
+ | f_arg ',' f_norm_arg {
1553
+ val[0] << val[2].to_sym
1554
+ result = val[0]
1555
+ }
1556
+
1557
+ f_opt : tIDENTIFIER '=' arg_value {
1558
+ result = self.assignable(val[0], val[2]);
1559
+ # TODO: detect duplicate names
1560
+ }
1561
+
1562
+ f_optarg : f_opt {
1563
+ result = s(:block, val[0])
1564
+ }
1565
+ | f_optarg ',' f_opt {
1566
+ result = self.append_to_block(val[0], val[2]);
1567
+ }
1568
+
1569
+ restarg_mark : tSTAR2 | tSTAR
1570
+
1571
+ f_rest_arg : restarg_mark tIDENTIFIER { # TODO: differs from parse.y - needs tests
1572
+ name = val[1].to_sym
1573
+ self.assignable(name)
1574
+ result = :"*#{name}"
1575
+ }
1576
+ | restarg_mark {
1577
+ name = :"*"
1578
+ self.env[name] = self.env.dynamic? ? :dvar : :lvar # FIX
1579
+ result = name
1580
+ }
1581
+
1582
+ blkarg_mark : tAMPER2 | tAMPER
1583
+
1584
+ f_block_arg : blkarg_mark tIDENTIFIER {
1585
+ identifier = val[1].to_sym
1586
+
1587
+ self.env[identifier] = self.env.dynamic? ? :dvar : :lvar
1588
+ result = s(:block_arg, identifier.to_sym)
1589
+ }
1590
+
1591
+ opt_f_block_arg: ',' f_block_arg {
1592
+ result = val[1];
1593
+ }
1594
+ | {
1595
+ result = nil;
1596
+ }
1597
+
1598
+ singleton : var_ref
1599
+ | tLPAREN2 {
1600
+ lexer.lex_state = :expr_beg
1601
+ } expr opt_nl tRPAREN {
1602
+ if (val[2].instanceof ILiteralNode) then
1603
+ yyerror("Can't define single method for literals.");
1604
+ end
1605
+ result = val[2];
1606
+ }
1607
+
1608
+ assoc_list : none { # [!nil]
1609
+ result = s(:array)
1610
+ }
1611
+ | assocs trailer { # [!nil]
1612
+ result = val[0];
1613
+ }
1614
+ | args trailer {
1615
+ size = val[0].size
1616
+ if (size % 2 != 1) then # != 1 because of leading :array
1617
+ yyerror("Odd number (#{size}) list for Hash. #{val[0].inspect}");
1618
+ end
1619
+ result = val[0];
1620
+ }
1621
+
1622
+ assocs : assoc
1623
+ | assocs ',' assoc {
1624
+ list = val[0].dup
1625
+ more = val[2][1..-1]
1626
+ list.push(*more) unless more.empty?
1627
+ result = list
1628
+ }
1629
+
1630
+ assoc : arg_value tASSOC arg_value {
1631
+ result = s(:array, val[0], val[2])
1632
+ }
1633
+
1634
+ operation : tIDENTIFIER | tCONSTANT | tFID
1635
+ operation2 : tIDENTIFIER | tCONSTANT | tFID | op
1636
+ operation3 : tIDENTIFIER | tFID | op
1637
+ dot_or_colon : tDOT | tCOLON2
1638
+ opt_terms : | terms
1639
+ opt_nl : | "\n"
1640
+ trailer : | "\n" | ','
1641
+
1642
+ term : ';' { yyerrok }
1643
+ | "\n"
1644
+
1645
+ terms : term
1646
+ | terms ';' { yyerrok }
1647
+
1648
+ none : { result = nil }
1649
+
1650
+ none_block_pass: { result = nil }
1651
+
1652
+ end
1653
+
1654
+ ---- inner
1655
+
1656
+ require 'ruby_lexer'