ruby_parser 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

data/lib/ruby_parser.y CHANGED
@@ -15,1634 +15,1776 @@ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
15
15
  tLBRACK tRBRACK tLBRACE tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2
16
16
  tTILDE tPERCENT tDIVIDE tPLUS tMINUS tLT tGT tPIPE tBANG tCARET
17
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
18
+ tWORDS_BEG tAWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tSTRING
19
+ tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAST_TOKEN
20
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
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
45
 
46
46
  rule
47
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 }
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(:splat, val[1])
720
+ result.paren = true
721
+ }
722
+
723
+ paren_args: tLPAREN2 none tRPAREN
724
+ {
725
+ result = val[1]
726
+ }
727
+ | tLPAREN2 call_args opt_nl tRPAREN
728
+ {
729
+ result = val[1]
730
+ }
731
+ | tLPAREN2 block_call opt_nl tRPAREN
732
+ {
733
+ warning "parenthesize argument(s) for future version"
734
+ result = s(:array, val[1])
735
+ }
736
+ | tLPAREN2 args tCOMMA block_call opt_nl tRPAREN
737
+ {
738
+ warning "parenthesize argument(s) for future version"
739
+ result = val[1].add val[3]
740
+ }
741
+
742
+ opt_paren_args: none
743
+ | paren_args
744
+
745
+ call_args: command
746
+ {
747
+ warning "parenthesize argument(s) for future version"
748
+ result = s(:array, val[0])
749
+ }
750
+ | args opt_block_arg
751
+ {
752
+ result = self.arg_blk_pass val[0], val[1]
753
+ }
754
+ | args tCOMMA tSTAR arg_value opt_block_arg
755
+ {
756
+ result = self.arg_concat val[0], val[3]
757
+ result = self.arg_blk_pass result, val[4]
758
+ }
759
+ | assocs opt_block_arg
760
+ {
761
+ result = s(:array, s(:hash, *val[0].values))
762
+ result = self.arg_blk_pass result, val[1]
763
+ }
764
+ | assocs tCOMMA tSTAR arg_value opt_block_arg
765
+ {
766
+ result = self.arg_concat s(:array, s(:hash, *val[0].values)), val[3]
767
+ result = self.arg_blk_pass result, val[4]
768
+ }
769
+ | args tCOMMA assocs opt_block_arg
770
+ {
771
+ result = val[0] << s(:hash, *val[2].values)
772
+ result = self.arg_blk_pass result, val[3]
773
+ }
774
+ | args tCOMMA assocs tCOMMA tSTAR arg opt_block_arg
775
+ {
776
+ val[0] << s(:hash, *val[2].values)
777
+ result = self.arg_concat val[0], val[5]
778
+ result = self.arg_blk_pass result, val[6]
779
+ }
780
+ | tSTAR arg_value opt_block_arg
781
+ {
782
+ result = self.arg_blk_pass s(:splat, val[1]), val[2]
783
+ }
784
+ | block_arg
785
+
786
+ call_args2: arg_value tCOMMA args opt_block_arg
787
+ {
788
+ args = self.list_prepend val[0], val[2]
789
+ result = self.arg_blk_pass args, val[3]
790
+ }
791
+ | arg_value tCOMMA block_arg
792
+ {
793
+ result = self.arg_blk_pass val[0], val[2]
794
+ }
795
+ | arg_value tCOMMA tSTAR arg_value opt_block_arg
796
+ {
797
+ result = self.arg_concat s(:array, val[0]), val[3]
798
+ result = self.arg_blk_pass result, val[4]
799
+ }
800
+ | arg_value tCOMMA args tCOMMA tSTAR arg_value opt_block_arg
801
+ {
802
+ result = self.arg_concat s(:array, val[0], s(:hash, *val[2].values)), val[5]
803
+ result = self.arg_blk_pass result, val[6]
804
+ }
805
+ | assocs opt_block_arg
806
+ {
807
+ result = s(:array, s(:hash, *val[0].values))
808
+ result = self.arg_blk_pass result, val[1]
809
+ }
810
+ | assocs tCOMMA tSTAR arg_value opt_block_arg
811
+ {
812
+ result = s(:array, s(:hash, *val[0].values), val[3])
813
+ result = self.arg_blk_pass result, val[4]
814
+ }
815
+ | arg_value tCOMMA assocs opt_block_arg
816
+ {
817
+ result = s(:array, val[0], s(:hash, *val[2].values))
818
+ result = self.arg_blk_pass result, val[3]
819
+ }
820
+ | arg_value tCOMMA args tCOMMA assocs opt_block_arg
821
+ {
822
+ result = s(:array, val[0]).add_all(val[2]).add(s(:hash, *val[4].values))
823
+ result = self.arg_blk_pass result, val[5]
824
+ }
825
+ | arg_value tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
826
+ {
827
+ result = self.arg_concat s(:array, val[0]).add(s(:hash, *val[2].values)), val[5]
828
+ result = self.arg_blk_pass result, val[6]
829
+ }
830
+ | arg_value tCOMMA args tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
831
+ {
832
+ result = self.arg_concat s(:array, val[0]).add_all(val[2]).add(s(:hash, *val[4].values)), val[7]
833
+ result = self.arg_blk_pass result, val[8]
834
+ }
835
+ | tSTAR arg_value opt_block_arg
836
+ {
837
+ result = self.arg_blk_pass s(:splat, val[1]), val[2]
838
+ }
839
+ | block_arg
840
+
841
+ command_args: {
842
+ result = lexer.cmdarg.stack.dup
843
+ lexer.cmdarg.push true
844
+ }
845
+ open_args
846
+ {
847
+ lexer.cmdarg.stack.replace val[0]
848
+ result = val[1]
849
+ }
850
+
851
+ open_args: call_args
852
+ | tLPAREN_ARG
853
+ {
854
+ lexer.lex_state = :expr_endarg
855
+ }
856
+ tRPAREN
857
+ {
858
+ warning "don't put space before argument parentheses"
859
+ result = nil
860
+ }
861
+ | tLPAREN_ARG call_args2
862
+ {
863
+ lexer.lex_state = :expr_endarg
864
+ }
865
+ tRPAREN
866
+ {
867
+ warning "don't put space before argument parentheses"
868
+ result = val[1]
869
+ }
870
+
871
+ block_arg: tAMPER arg_value
872
+ {
873
+ result = s(:block_pass, val[1])
874
+ }
875
+
876
+ opt_block_arg: tCOMMA block_arg
877
+ {
878
+ result = val[1]
879
+ }
880
+ | none_block_pass
881
+
882
+ args: arg_value
883
+ {
884
+ result = s(:array, val[0])
885
+ }
886
+ | args tCOMMA arg_value
887
+ {
888
+ result = self.list_append val[0], val[2]
889
+ }
890
+
891
+ mrhs: args tCOMMA arg_value
892
+ {
893
+ result = val[0] << val[2]
894
+ }
895
+ | args tCOMMA tSTAR arg_value
896
+ {
897
+ result = self.arg_concat val[0], val[3]
898
+ }
899
+ | tSTAR arg_value
900
+ {
901
+ result = s(:splat, val[1])
902
+ }
903
+
904
+ primary: literal
905
+ | strings
906
+ | xstring
907
+ | regexp
908
+ | words
909
+ | awords
910
+ | var_ref
911
+ | backref
912
+ | tFID
913
+ {
914
+ result = new_call nil, val[0].to_sym
915
+ }
916
+ | kBEGIN
917
+ {
918
+ result = self.lexer.lineno
919
+ }
920
+ bodystmt kEND
921
+ {
922
+ unless val[2] then
923
+ result = s(:nil)
924
+ else
925
+ result = s(:begin, val[2])
926
+ end
927
+
928
+ result.line = val[1]
929
+ }
930
+ | tLPAREN_ARG expr
931
+ {
932
+ lexer.lex_state = :expr_endarg
933
+ }
934
+ opt_nl tRPAREN
935
+ {
936
+ warning "(...) interpreted as grouped expression"
937
+ result = val[1]
938
+ }
939
+ | tLPAREN compstmt tRPAREN
940
+ {
941
+ result = val[1] || s(:nil)
942
+ result.paren = true
943
+ }
944
+ | primary_value tCOLON2 tCONSTANT
945
+ {
946
+ result = s(:colon2, val[0], val[2].to_sym)
947
+ }
948
+ | tCOLON3 tCONSTANT
949
+ {
950
+ result = s(:colon3, val[1].to_sym)
951
+ }
952
+ | primary_value "[" aref_args tRBRACK
953
+ {
954
+ result = new_aref val
955
+ }
956
+ | tLBRACK aref_args tRBRACK
957
+ {
958
+ result = val[1] || s(:array)
959
+ }
960
+ | tLBRACE assoc_list tRCURLY
961
+ {
962
+ result = s(:hash, *val[1].values)
963
+ }
964
+ | kRETURN
965
+ {
966
+ result = s(:return)
967
+ }
968
+ | kYIELD tLPAREN2 call_args tRPAREN
969
+ {
970
+ result = new_yield val[2]
971
+ }
972
+ | kYIELD tLPAREN2 tRPAREN
973
+ {
974
+ result = new_yield
975
+ }
976
+ | kYIELD
977
+ {
978
+ result = new_yield
979
+ }
980
+ | kDEFINED opt_nl tLPAREN2 expr tRPAREN
981
+ {
982
+ result = s(:defined, val[3])
983
+ }
984
+ | operation brace_block
985
+ {
986
+ oper, iter = val[0], val[1]
987
+ call = new_call(nil, oper.to_sym)
988
+ iter.insert 1, call
989
+ result = iter
990
+ call.line ||= iter.line
991
+ }
992
+ | method_call
993
+ | method_call brace_block
994
+ {
995
+ call, iter = val[0], val[1]
996
+ iter.insert 1, call
997
+ result = iter
998
+ }
999
+ | kIF expr_value then compstmt if_tail kEND
1000
+ {
1001
+ result = new_if val[1], val[3], val[4]
1002
+ }
1003
+ | kUNLESS expr_value then compstmt opt_else kEND
1004
+ {
1005
+ result = new_if val[1], val[4], val[3]
1006
+ }
1007
+ | kWHILE
1008
+ {
1009
+ lexer.cond.push true
1010
+ }
1011
+ expr_value do
1012
+ {
1013
+ lexer.cond.pop
1014
+ }
1015
+ compstmt kEND
1016
+ {
1017
+ result = new_while val[5], val[2], true
1018
+ }
1019
+ | kUNTIL
1020
+ {
1021
+ lexer.cond.push true
1022
+ }
1023
+ expr_value do
1024
+ {
1025
+ lexer.cond.pop
1026
+ }
1027
+ compstmt kEND
1028
+ {
1029
+ result = new_until val[5], val[2], true
1030
+ }
1031
+ | kCASE expr_value opt_terms case_body kEND
1032
+ {
1033
+ result = new_case val[1], val[3]
1034
+ }
1035
+ | kCASE opt_terms case_body kEND
1036
+ {
1037
+ result = new_case nil, val[2]
1038
+ }
1039
+ | kCASE opt_terms kELSE compstmt kEND # TODO: need a test
1040
+ {
1041
+ result = new_case nil, val[3]
1042
+ }
1043
+ | kFOR block_var kIN
1044
+ {
1045
+ lexer.cond.push true
1046
+ }
1047
+ expr_value do
1048
+ {
1049
+ lexer.cond.pop
1050
+ }
1051
+ compstmt kEND
1052
+ {
1053
+ result = new_for val[4], val[1], val[7]
1054
+ }
1055
+ | kCLASS
1056
+ {
1057
+ result = self.lexer.lineno
1058
+ }
1059
+ cpath superclass
1060
+ {
1061
+ self.comments.push self.lexer.comments
1062
+ if (self.in_def || self.in_single > 0) then
1063
+ yyerror "class definition in method body"
1064
+ end
1065
+ self.env.extend
1066
+ }
1067
+ bodystmt kEND
1068
+ {
1069
+ result = new_class val
1070
+ self.env.unextend
1071
+ }
1072
+ | kCLASS tLSHFT
1073
+ {
1074
+ result = self.lexer.lineno
1075
+ }
1076
+ expr
1077
+ {
1078
+ result = self.in_def
1079
+ self.in_def = false
1080
+ }
1081
+ term
1082
+ {
1083
+ result = self.in_single
1084
+ self.in_single = 0
1085
+ self.env.extend
1086
+ }
1087
+ bodystmt kEND
1088
+ {
1089
+ result = new_sclass val
1090
+ self.env.unextend
1091
+ }
1092
+ | kMODULE
1093
+ {
1094
+ result = self.lexer.lineno
1095
+ }
1096
+ cpath
1097
+ {
1098
+ self.comments.push self.lexer.comments
1099
+ yyerror "module definition in method body" if
1100
+ self.in_def or self.in_single > 0
1101
+
1102
+ self.env.extend
1103
+ }
1104
+ bodystmt kEND
1105
+ {
1106
+ result = new_module val
1107
+ self.env.unextend
1108
+ }
1109
+ | kDEF fname
1110
+ {
1111
+ self.comments.push self.lexer.comments
1112
+ self.in_def = true
1113
+ self.env.extend
1114
+ result = self.lexer.lineno
1115
+ }
1116
+ f_arglist bodystmt kEND
1117
+ {
1118
+ result = new_defn val
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 }
1643
1781
 
1644
1782
  end
1645
1783
 
1646
1784
  ---- inner
1647
1785
 
1648
- require 'ruby_lexer'
1786
+ require "ruby_lexer"
1787
+
1788
+ # Local Variables: **
1789
+ # racc-token-length-max:14 **
1790
+ # End: **