ruby_parser 3.0.0 → 3.19.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.autotest +36 -19
  4. data/History.rdoc +1297 -0
  5. data/Manifest.txt +35 -7
  6. data/{README.txt → README.rdoc} +44 -14
  7. data/Rakefile +308 -110
  8. data/bin/ruby_parse +3 -1
  9. data/bin/ruby_parse_extract_error +36 -16
  10. data/compare/normalize.rb +218 -0
  11. data/debugging.md +190 -0
  12. data/gauntlet.md +107 -0
  13. data/lib/.document +1 -0
  14. data/lib/rp_extensions.rb +53 -0
  15. data/lib/rp_stringscanner.rb +33 -0
  16. data/lib/ruby20_parser.rb +10973 -0
  17. data/lib/ruby20_parser.y +2683 -0
  18. data/lib/ruby21_parser.rb +10980 -0
  19. data/lib/ruby21_parser.y +2700 -0
  20. data/lib/ruby22_parser.rb +11123 -0
  21. data/lib/ruby22_parser.y +2711 -0
  22. data/lib/ruby23_parser.rb +11132 -0
  23. data/lib/ruby23_parser.y +2713 -0
  24. data/lib/ruby24_parser.rb +11231 -0
  25. data/lib/ruby24_parser.y +2721 -0
  26. data/lib/ruby25_parser.rb +11231 -0
  27. data/lib/ruby25_parser.y +2721 -0
  28. data/lib/ruby26_parser.rb +11253 -0
  29. data/lib/ruby26_parser.y +2736 -0
  30. data/lib/ruby27_parser.rb +12980 -0
  31. data/lib/ruby27_parser.y +3324 -0
  32. data/lib/ruby30_parser.rb +13242 -0
  33. data/lib/ruby30_parser.y +3447 -0
  34. data/lib/ruby31_parser.rb +13622 -0
  35. data/lib/ruby31_parser.y +3481 -0
  36. data/lib/ruby3_parser.yy +3536 -0
  37. data/lib/ruby_lexer.rb +933 -1232
  38. data/lib/ruby_lexer.rex +185 -0
  39. data/lib/ruby_lexer.rex.rb +399 -0
  40. data/lib/ruby_lexer_strings.rb +638 -0
  41. data/lib/ruby_parser.rb +97 -3
  42. data/lib/ruby_parser.yy +3465 -0
  43. data/lib/ruby_parser_extras.rb +1216 -687
  44. data/test/test_ruby_lexer.rb +2249 -1092
  45. data/test/test_ruby_parser.rb +5156 -975
  46. data/test/test_ruby_parser_extras.rb +47 -77
  47. data/tools/munge.rb +250 -0
  48. data/tools/ripper.rb +44 -0
  49. data.tar.gz.sig +1 -1
  50. metadata +200 -155
  51. metadata.gz.sig +0 -0
  52. data/.gemtest +0 -0
  53. data/History.txt +0 -482
  54. data/lib/gauntlet_rubyparser.rb +0 -120
  55. data/lib/ruby18_parser.rb +0 -5747
  56. data/lib/ruby18_parser.y +0 -1873
  57. data/lib/ruby19_parser.rb +0 -6110
  58. data/lib/ruby19_parser.y +0 -2078
@@ -0,0 +1,2711 @@
1
+ # -*- racc -*-
2
+
3
+ class Ruby22Parser
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 kDO_LAMBDA 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__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
11
+ tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
12
+ tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
13
+ tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
14
+ tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
15
+ tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
16
+ tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
17
+ tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
18
+ tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
19
+ tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
20
+ tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA
21
+ tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND
22
+ tRATIONAL tIMAGINARY
23
+ tLABEL_END
24
+
25
+ preclow
26
+ nonassoc tLOWEST
27
+ nonassoc tLBRACE_ARG
28
+ nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
29
+ left kOR kAND
30
+ right kNOT
31
+ nonassoc kDEFINED
32
+ right tEQL tOP_ASGN
33
+ left kRESCUE_MOD
34
+ right tEH tCOLON
35
+ nonassoc tDOT2 tDOT3 tBDOT2 tBDOT3
36
+ left tOROP
37
+ left tANDOP
38
+ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
39
+ left tGT tGEQ tLT tLEQ
40
+ left tPIPE tCARET
41
+ left tAMPER2
42
+ left tLSHFT tRSHFT
43
+ left tPLUS tMINUS
44
+ left tSTAR2 tDIVIDE tPERCENT # TODO: tSTAR2 -> tMULT
45
+ right tUMINUS_NUM tUMINUS
46
+ right tPOW
47
+ right tBANG tTILDE tUPLUS
48
+ prechigh
49
+
50
+ rule
51
+
52
+ program: {
53
+ self.lexer.lex_state = EXPR_BEG
54
+ }
55
+ top_compstmt
56
+ {
57
+ result = new_compstmt val
58
+
59
+ lexer.cond.pop # local_pop
60
+ lexer.cmdarg.pop
61
+ }
62
+
63
+ top_compstmt: top_stmts opt_terms
64
+ {
65
+ stmt, _ = val
66
+ result = stmt
67
+ }
68
+
69
+ top_stmts: none
70
+ | top_stmt
71
+ | top_stmts terms top_stmt
72
+ {
73
+ result = self.block_append val[0], val[2]
74
+ }
75
+ | error top_stmt
76
+
77
+ top_stmt: stmt
78
+ | klBEGIN
79
+ {
80
+ if (self.in_def || self.in_single > 0) then
81
+ debug 11
82
+ yyerror "BEGIN in method"
83
+ end
84
+ self.env.extend
85
+ }
86
+ begin_block
87
+ {
88
+ (_, lineno), _, iter = val
89
+ iter.line lineno
90
+
91
+ (_, preexe,) = iter
92
+ preexe.line lineno
93
+
94
+ result = iter
95
+ }
96
+
97
+ begin_block: tLCURLY { result = lexer.lineno } top_compstmt tRCURLY
98
+ {
99
+ _, line, stmt, _ = val
100
+ result = new_iter s(:preexe).line(line), 0, stmt
101
+ }
102
+
103
+ bodystmt: compstmt opt_rescue k_else
104
+ {
105
+ res = _values[-2]
106
+ # TODO: move down to main match so I can just use val
107
+
108
+ warn "else without rescue is useless" unless res
109
+ }
110
+ compstmt
111
+ opt_ensure
112
+ {
113
+ body, resc, _, _, els, ens = val
114
+
115
+ result = new_body [body, resc, els, ens]
116
+ }
117
+ | compstmt opt_rescue opt_ensure
118
+ {
119
+ body, resc, ens = val
120
+
121
+ result = new_body [body, resc, nil, ens]
122
+ }
123
+
124
+ compstmt: stmts opt_terms
125
+ {
126
+ result = new_compstmt val
127
+ }
128
+
129
+ stmts: none
130
+ | stmt_or_begin # TODO: newline_node ?
131
+ | stmts terms stmt_or_begin
132
+ {
133
+ result = self.block_append val[0], val[2]
134
+ }
135
+ | error stmt
136
+ {
137
+ result = val[1]
138
+ debug 12
139
+ }
140
+
141
+ stmt_or_begin: stmt
142
+ | klBEGIN
143
+ {
144
+ yyerror "BEGIN is permitted only at toplevel"
145
+ }
146
+ begin_block
147
+ {
148
+ result = val[2] # wtf?
149
+ }
150
+
151
+ stmt: kALIAS fitem
152
+ {
153
+ lexer.lex_state = EXPR_FNAME
154
+ }
155
+ fitem
156
+ {
157
+ (_, line), lhs, _, rhs = val
158
+ result = s(:alias, lhs, rhs).line(line).line line
159
+ }
160
+ | kALIAS tGVAR tGVAR
161
+ {
162
+ (_, line), (lhs, _), (rhs, _) = val
163
+ result = s(:valias, lhs.to_sym, rhs.to_sym).line line
164
+ }
165
+ | kALIAS tGVAR tBACK_REF
166
+ {
167
+ (_, line), (lhs, _), (rhs, _) = val
168
+ result = s(:valias, lhs.to_sym, :"$#{rhs}").line line
169
+ }
170
+ | kALIAS tGVAR tNTH_REF
171
+ {
172
+ yyerror "can't make alias for the number variables"
173
+ }
174
+ | kUNDEF undef_list
175
+ {
176
+ result = val[1]
177
+ }
178
+ | stmt kIF_MOD expr_value
179
+ {
180
+ t, _, c = val
181
+ result = new_if c, t, nil
182
+ }
183
+ | stmt kUNLESS_MOD expr_value
184
+ {
185
+ f, _, c = val
186
+ result = new_if c, nil, f
187
+ }
188
+ | stmt kWHILE_MOD expr_value
189
+ {
190
+ e, _, c = val
191
+ result = new_while e, c, true
192
+ }
193
+ | stmt kUNTIL_MOD expr_value
194
+ {
195
+ e, _, c = val
196
+ result = new_until e, c, true
197
+ }
198
+ | stmt kRESCUE_MOD stmt
199
+ {
200
+ body, _, resbody = val
201
+
202
+ resbody = new_resbody s(:array).line(resbody.line), resbody
203
+ result = new_rescue body, resbody
204
+ }
205
+ | klEND tLCURLY compstmt tRCURLY
206
+ {
207
+ (_, line), _, stmt, _ = val
208
+
209
+ if (self.in_def || self.in_single > 0) then
210
+ debug 13
211
+ yyerror "END in method; use at_exit"
212
+ end
213
+
214
+ result = new_iter s(:postexe).line(line), 0, stmt
215
+ }
216
+ | command_asgn
217
+ | mlhs tEQL command_call
218
+ {
219
+ result = new_masgn val[0], val[2], :wrap
220
+ }
221
+ | lhs tEQL mrhs
222
+ {
223
+ lhs, _, rhs = val
224
+ result = new_assign lhs, s(:svalue, rhs).line(rhs.line)
225
+ }
226
+ | mlhs tEQL mrhs_arg
227
+ {
228
+ result = new_masgn val[0], val[2]
229
+ }
230
+ | expr
231
+
232
+ command_asgn: lhs tEQL command_rhs
233
+ {
234
+ result = new_assign val[0], val[2]
235
+ }
236
+ # | lhs tEQL command_asgn
237
+ # {
238
+ # result = new_assign val[0], val[2]
239
+ # }
240
+ | var_lhs tOP_ASGN command_rhs
241
+ {
242
+ result = new_op_asgn val
243
+ }
244
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_rhs
245
+ {
246
+ result = new_op_asgn1 val
247
+ }
248
+ | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
249
+ {
250
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
251
+
252
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
253
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
254
+ result.line prim.line
255
+ }
256
+ | primary_value call_op tCONSTANT tOP_ASGN command_rhs
257
+ {
258
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
259
+
260
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
261
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
262
+ result.line prim.line
263
+ }
264
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
265
+ {
266
+ lhs1, _, (lhs2, line), (id, _), rhs = val
267
+
268
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
269
+ }
270
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
271
+ {
272
+ lhs1, _, (lhs2, line), (id, _), rhs = val
273
+
274
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
275
+ }
276
+ | backref tOP_ASGN command_rhs
277
+ {
278
+ self.backref_assign_error val[0]
279
+ }
280
+
281
+ command_rhs: command_call =tOP_ASGN
282
+ {
283
+ expr, = val
284
+ result = value_expr expr
285
+ }
286
+ | command_asgn
287
+
288
+ expr: command_call
289
+ | expr kAND expr
290
+ {
291
+ lhs, _, rhs = val
292
+ result = logical_op :and, lhs, rhs
293
+ }
294
+ | expr kOR expr
295
+ {
296
+ lhs, _, rhs = val
297
+ result = logical_op :or, lhs, rhs
298
+ }
299
+ | kNOT opt_nl expr
300
+ {
301
+ (_, line), _, expr = val
302
+ result = new_call(expr, :"!").line line
303
+ # REFACTOR: call_uni_op
304
+ }
305
+ | tBANG command_call
306
+ {
307
+ _, cmd = val
308
+ result = new_call(cmd, :"!").line cmd.line
309
+ # TODO: fix line number to tBANG... but causes BAD shift/reduce conflict
310
+ # REFACTOR: call_uni_op -- see parse26.y
311
+ }
312
+ | arg =tLBRACE_ARG
313
+
314
+ expr_value: expr
315
+ {
316
+ result = value_expr(val[0])
317
+ }
318
+
319
+ expr_value_do: {
320
+ lexer.cond.push true
321
+ }
322
+ expr_value do
323
+ {
324
+ lexer.cond.pop
325
+ }
326
+ {
327
+ _, expr, _, _ = val
328
+ result = expr
329
+ }
330
+
331
+ command_call: command
332
+ | block_command
333
+
334
+ block_command: block_call
335
+ | block_call call_op2 operation2 command_args
336
+ {
337
+ blk, _, (msg, _line), args = val
338
+ result = new_call(blk, msg.to_sym, args).line blk.line
339
+ }
340
+
341
+ cmd_brace_block: tLBRACE_ARG
342
+ {
343
+ # self.env.extend(:dynamic)
344
+ result = self.lexer.lineno
345
+ }
346
+ brace_body tRCURLY
347
+ {
348
+ _, line, body, _ = val
349
+
350
+ result = body
351
+ result.line line
352
+
353
+ # self.env.unextend
354
+ }
355
+
356
+ fcall: operation
357
+ {
358
+ (msg, line), = val
359
+ result = new_call(nil, msg.to_sym).line line
360
+ }
361
+
362
+ command: fcall command_args =tLOWEST
363
+ {
364
+ call, args = val
365
+ result = call.concat args.sexp_body
366
+ }
367
+ | fcall command_args cmd_brace_block
368
+ {
369
+ call, args, block = val
370
+
371
+ result = call.concat args.sexp_body
372
+
373
+ if block then
374
+ block_dup_check result, block
375
+
376
+ result, operation = block, result
377
+ result.insert 1, operation
378
+ end
379
+ }
380
+ | primary_value call_op operation2 command_args =tLOWEST
381
+ {
382
+ lhs, callop, (op, _), args = val
383
+
384
+ result = new_call lhs, op.to_sym, args, callop
385
+ result.line lhs.line
386
+ }
387
+ | primary_value call_op operation2 command_args cmd_brace_block
388
+ {
389
+ recv, _, (msg, _line), args, block = val
390
+ call = new_call recv, msg.to_sym, args, val[1]
391
+
392
+ block_dup_check call, block
393
+
394
+ block.insert 1, call
395
+ result = block
396
+ }
397
+ | primary_value tCOLON2 operation2 command_args =tLOWEST
398
+ {
399
+ lhs, _, (id, line), args = val
400
+
401
+ result = new_call lhs, id.to_sym, args
402
+ result.line line
403
+ }
404
+ | primary_value tCOLON2 operation2 command_args cmd_brace_block
405
+ {
406
+ recv, _, (msg, _line), args, block = val
407
+ call = new_call recv, msg.to_sym, args
408
+
409
+ block_dup_check call, block
410
+
411
+ block.insert 1, call
412
+ result = block
413
+ }
414
+ | kSUPER command_args
415
+ {
416
+ result = new_super val[1]
417
+ }
418
+ | kYIELD command_args
419
+ {
420
+ (_, line), args = val
421
+ result = new_yield args
422
+ result.line line # TODO: push to new_yield
423
+ }
424
+ | k_return call_args
425
+ {
426
+ line = val[0].last
427
+ result = s(:return, ret_args(val[1])).line(line)
428
+ }
429
+ | kBREAK call_args
430
+ {
431
+ (_, line), args = val
432
+ result = s(:break, ret_args(args)).line line
433
+ }
434
+ | kNEXT call_args
435
+ {
436
+ line = val[0].last
437
+ result = s(:next, ret_args(val[1])).line(line)
438
+ }
439
+
440
+ mlhs: mlhs_basic
441
+ | tLPAREN mlhs_inner rparen
442
+ {
443
+ result = val[1]
444
+ }
445
+
446
+ mlhs_inner: mlhs_basic
447
+ | tLPAREN mlhs_inner rparen
448
+ {
449
+ _, arg, _ = val
450
+ l = arg.line
451
+
452
+ result = s(:masgn, s(:array, arg).line(l)).line l
453
+ }
454
+
455
+ mlhs_basic: mlhs_head
456
+ {
457
+ head, = val
458
+ result = s(:masgn, head).line head.line
459
+ }
460
+ | mlhs_head mlhs_item
461
+ {
462
+ lhs, rhs = val
463
+ result = s(:masgn, lhs << rhs.compact).line lhs.line
464
+ }
465
+ | mlhs_head tSTAR mlhs_node
466
+ {
467
+ head, _, tail = val
468
+ head << s(:splat, tail).line(tail.line)
469
+ result = s(:masgn, head).line head.line
470
+ }
471
+ | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
472
+ {
473
+ ary1, _, splat, _, ary2 = val
474
+
475
+ result = list_append ary1, s(:splat, splat).line(splat.line)
476
+ result.concat ary2.sexp_body
477
+ result = s(:masgn, result).line result.line
478
+ }
479
+ | mlhs_head tSTAR
480
+ {
481
+ head, _ = val
482
+ l = head.line
483
+ result = s(:masgn, head << s(:splat).line(l)).line l
484
+ }
485
+ | mlhs_head tSTAR tCOMMA mlhs_post
486
+ {
487
+ head, _, _, post = val
488
+ ary = list_append head, s(:splat).line(head.line)
489
+ ary.concat post.sexp_body
490
+ result = s(:masgn, ary).line ary.line
491
+ }
492
+ | tSTAR mlhs_node
493
+ {
494
+ _, node = val
495
+ l = node.line
496
+ splat = s(:splat, node).line l
497
+ ary = s(:array, splat).line l
498
+ result = s(:masgn, ary).line l
499
+ }
500
+ | tSTAR mlhs_node tCOMMA mlhs_post
501
+ {
502
+ _, node, _, post = val
503
+
504
+ splat = s(:splat, node).line node.line
505
+ ary = s(:array, splat).line splat.line
506
+ ary.concat post.sexp_body
507
+ result = s(:masgn, ary).line ary.line
508
+ }
509
+ | tSTAR
510
+ {
511
+ l = lexer.lineno
512
+ result = s(:masgn, s(:array, s(:splat).line(l)).line(l)).line l
513
+ }
514
+ | tSTAR tCOMMA mlhs_post
515
+ {
516
+ _, _, post = val
517
+ l = post.line
518
+
519
+ splat = s(:splat).line l
520
+ ary = s(:array, splat, *post.sexp_body).line l
521
+ result = s(:masgn, ary).line l
522
+ }
523
+
524
+ mlhs_item: mlhs_node
525
+ | tLPAREN mlhs_inner rparen
526
+ {
527
+ result = val[1]
528
+ }
529
+
530
+ mlhs_head: mlhs_item tCOMMA
531
+ {
532
+ lhs, _ = val
533
+ result = s(:array, lhs).line lhs.line
534
+ }
535
+ | mlhs_head mlhs_item tCOMMA
536
+ {
537
+ result = val[0] << val[1].compact
538
+ }
539
+
540
+ mlhs_post: mlhs_item
541
+ {
542
+ item, = val
543
+ result = s(:array, item).line item.line
544
+ }
545
+ | mlhs_post tCOMMA mlhs_item
546
+ {
547
+ result = list_append val[0], val[2]
548
+ }
549
+
550
+ mlhs_node: user_variable
551
+ {
552
+ result = self.assignable val[0]
553
+ }
554
+ | keyword_variable
555
+ {
556
+ result = self.assignable val[0]
557
+ }
558
+ | primary_value tLBRACK2 opt_call_args rbracket
559
+ {
560
+ result = self.aryset val[0], val[2]
561
+ }
562
+ | primary_value call_op tIDENTIFIER
563
+ {
564
+ lhs, call_op, (id, _line) = val
565
+
566
+ result = new_attrasgn lhs, id, call_op
567
+ }
568
+ | primary_value tCOLON2 tIDENTIFIER
569
+ {
570
+ recv, _, (id, _line) = val
571
+ result = new_attrasgn recv, id
572
+ }
573
+ | primary_value call_op tCONSTANT
574
+ {
575
+ lhs, call_op, (id, _line) = val
576
+
577
+ result = new_attrasgn lhs, id, call_op
578
+ }
579
+ | primary_value tCOLON2 tCONSTANT
580
+ {
581
+ if (self.in_def || self.in_single > 0) then
582
+ debug 14
583
+ yyerror "dynamic constant assignment"
584
+ end
585
+
586
+ expr, _, (id, _line) = val
587
+ l = expr.line
588
+
589
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l), nil).line l
590
+ }
591
+ | tCOLON3 tCONSTANT
592
+ {
593
+ if (self.in_def || self.in_single > 0) then
594
+ debug 15
595
+ yyerror "dynamic constant assignment"
596
+ end
597
+
598
+ _, (id, l) = val
599
+
600
+ result = s(:const, nil, s(:colon3, id.to_sym).line(l)).line l
601
+ }
602
+ | backref
603
+ {
604
+ ref, = val
605
+
606
+ self.backref_assign_error ref
607
+ }
608
+
609
+ lhs: user_variable
610
+ {
611
+ var, = val
612
+
613
+ result = self.assignable var
614
+ }
615
+ | keyword_variable
616
+ {
617
+ var, = val
618
+
619
+ result = self.assignable var
620
+
621
+ debug 16
622
+ }
623
+ | primary_value tLBRACK2 opt_call_args rbracket
624
+ {
625
+ lhs, _, args, _ = val
626
+
627
+ result = self.aryset lhs, args
628
+ }
629
+ | primary_value call_op tIDENTIFIER # REFACTOR
630
+ {
631
+ lhs, op, (id, _line) = val
632
+
633
+ result = new_attrasgn lhs, id, op
634
+ }
635
+ | primary_value tCOLON2 tIDENTIFIER
636
+ {
637
+ lhs, _, (id, _line) = val
638
+
639
+ result = new_attrasgn lhs, id
640
+ }
641
+ | primary_value call_op tCONSTANT # REFACTOR?
642
+ {
643
+ lhs, call_op, (id, _line) = val
644
+
645
+ result = new_attrasgn lhs, id, call_op
646
+ }
647
+ | primary_value tCOLON2 tCONSTANT
648
+ {
649
+ expr, _, (id, _line) = val
650
+
651
+ if (self.in_def || self.in_single > 0) then
652
+ debug 17
653
+ yyerror "dynamic constant assignment"
654
+ end
655
+
656
+ l = expr.line
657
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l)).line l
658
+ }
659
+ | tCOLON3 tCONSTANT
660
+ {
661
+ _, (id, l) = val
662
+
663
+ if (self.in_def || self.in_single > 0) then
664
+ debug 18
665
+ yyerror "dynamic constant assignment"
666
+ end
667
+
668
+ result = s(:const, s(:colon3, id.to_sym).line(l)).line l
669
+ }
670
+ | backref
671
+ {
672
+ self.backref_assign_error val[0]
673
+ }
674
+
675
+ cname: tIDENTIFIER
676
+ {
677
+ yyerror "class/module name must be CONSTANT"
678
+ }
679
+ | tCONSTANT
680
+
681
+ cpath: tCOLON3 cname
682
+ {
683
+ result = wrap :colon3, val[1]
684
+ }
685
+ | cname
686
+ {
687
+ (id, line), = val
688
+ result = [id.to_sym, line] # TODO: sexp?
689
+ }
690
+ | primary_value tCOLON2 cname
691
+ {
692
+ pval, _, (name, _line) = val
693
+
694
+ result = s(:colon2, pval, name.to_sym)
695
+ result.line pval.line
696
+ }
697
+
698
+ fname: tIDENTIFIER | tCONSTANT | tFID
699
+ | op
700
+ {
701
+ lexer.lex_state = EXPR_END
702
+ }
703
+
704
+ | reswords
705
+
706
+ fitem: fname
707
+ {
708
+ result = wrap :lit, val[0]
709
+ }
710
+ | symbol
711
+
712
+ undef_list: fitem
713
+ {
714
+ result = new_undef val[0]
715
+ }
716
+ |
717
+ undef_list tCOMMA
718
+ {
719
+ lexer.lex_state = EXPR_FNAME
720
+ }
721
+ fitem
722
+ {
723
+ result = new_undef val[0], val[3]
724
+ }
725
+
726
+ op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
727
+ | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
728
+ | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
729
+ | tSTAR | tDIVIDE | tPERCENT | tPOW | tDSTAR | tBANG | tTILDE
730
+ | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
731
+
732
+ reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
733
+ | kALIAS | kAND | kBEGIN | kBREAK | kCASE
734
+ | kCLASS | kDEF | kDEFINED | kDO | kELSE
735
+ | kELSIF | kEND | kENSURE | kFALSE | kFOR
736
+ | kIN | kMODULE | kNEXT | kNIL | kNOT
737
+ | kOR | kREDO | kRESCUE | kRETRY | kRETURN
738
+ | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
739
+ | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
740
+ | kUNTIL
741
+
742
+ arg: lhs tEQL arg_rhs
743
+ {
744
+ result = new_assign val[0], val[2]
745
+ }
746
+ | var_lhs tOP_ASGN arg_rhs
747
+ {
748
+ result = new_op_asgn val
749
+ }
750
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg_rhs
751
+ {
752
+ result = new_op_asgn1 val
753
+ }
754
+ | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
755
+ {
756
+ result = new_op_asgn2 val
757
+ }
758
+ | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
759
+ {
760
+ result = new_op_asgn2 val
761
+ }
762
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
763
+ {
764
+ lhs, _, (id, _line), (op, _), rhs = val
765
+
766
+ result = s(:op_asgn, lhs, rhs, id.to_sym, op.to_sym).line lhs.line
767
+ }
768
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
769
+ {
770
+ lhs1, _, (lhs2, _line), op, rhs = val
771
+
772
+ lhs = s(:colon2, lhs1, lhs2.to_sym).line lhs1.line
773
+ result = new_const_op_asgn [lhs, op, rhs]
774
+ }
775
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
776
+ {
777
+ _, lhs, op, rhs = val
778
+
779
+ lhs = wrap :colon3, lhs
780
+ result = new_const_op_asgn [lhs, op, rhs]
781
+ }
782
+ | backref tOP_ASGN arg_rhs
783
+ {
784
+ # TODO: lhs = var_field val[0]
785
+ asgn = new_op_asgn val
786
+ result = self.backref_assign_error asgn
787
+ }
788
+ | arg tDOT2 arg
789
+ {
790
+ v1, v2 = val[0], val[2]
791
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
792
+ result = s(:lit, (v1.last)..(v2.last)).line v1.line
793
+ else
794
+ result = s(:dot2, v1, v2).line v1.line
795
+ end
796
+ }
797
+ | arg tDOT3 arg
798
+ {
799
+ v1, v2 = val[0], val[2]
800
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
801
+ result = s(:lit, (v1.last)...(v2.last)).line v1.line
802
+ else
803
+ result = s(:dot3, v1, v2).line v1.line
804
+ end
805
+ }
806
+
807
+
808
+ | arg tPLUS arg
809
+ {
810
+ result = new_call val[0], :+, argl(val[2])
811
+ }
812
+ | arg tMINUS arg
813
+ {
814
+ result = new_call val[0], :-, argl(val[2])
815
+ }
816
+ | arg tSTAR2 arg # TODO: rename
817
+ {
818
+ result = new_call val[0], :*, argl(val[2])
819
+ }
820
+ | arg tDIVIDE arg
821
+ {
822
+ result = new_call val[0], :"/", argl(val[2])
823
+ }
824
+ | arg tPERCENT arg
825
+ {
826
+ result = new_call val[0], :"%", argl(val[2])
827
+ }
828
+ | arg tPOW arg
829
+ {
830
+ result = new_call val[0], :**, argl(val[2])
831
+ }
832
+ | tUMINUS_NUM simple_numeric tPOW arg
833
+ {
834
+ _, (num, line), _, arg = val
835
+ lit = s(:lit, num).line line
836
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
837
+
838
+ }
839
+ | tUPLUS arg
840
+ {
841
+ result = new_call val[1], :"+@"
842
+ }
843
+ | tUMINUS arg
844
+ {
845
+ result = new_call val[1], :"-@"
846
+ }
847
+ | arg tPIPE arg
848
+ {
849
+ result = new_call val[0], :"|", argl(val[2])
850
+ }
851
+ | arg tCARET arg
852
+ {
853
+ result = new_call val[0], :"^", argl(val[2])
854
+ }
855
+ | arg tAMPER2 arg
856
+ {
857
+ result = new_call val[0], :"&", argl(val[2])
858
+ }
859
+ | arg tCMP arg
860
+ {
861
+ result = new_call val[0], :"<=>", argl(val[2])
862
+ }
863
+ | rel_expr =tCMP
864
+ | arg tEQ arg
865
+ {
866
+ result = new_call val[0], :"==", argl(val[2])
867
+ }
868
+ | arg tEQQ arg
869
+ {
870
+ result = new_call val[0], :"===", argl(val[2])
871
+ }
872
+ | arg tNEQ arg
873
+ {
874
+ result = new_call val[0], :"!=", argl(val[2])
875
+ }
876
+ | arg tMATCH arg
877
+ {
878
+ lhs, _, rhs = val
879
+ result = new_match lhs, rhs
880
+ }
881
+ | arg tNMATCH arg
882
+ {
883
+ lhs, _, rhs = val
884
+ result = s(:not, new_match(lhs, rhs)).line lhs.line
885
+ }
886
+ | tBANG arg
887
+ {
888
+ _, arg = val
889
+ result = new_call arg, :"!"
890
+ result.line arg.line
891
+ }
892
+ | tTILDE arg
893
+ {
894
+ result = new_call value_expr(val[1]), :"~"
895
+ }
896
+ | arg tLSHFT arg
897
+ {
898
+ val[0] = value_expr val[0]
899
+ val[2] = value_expr val[2]
900
+ result = new_call val[0], :"\<\<", argl(val[2])
901
+ }
902
+ | arg tRSHFT arg
903
+ {
904
+ val[0] = value_expr val[0]
905
+ val[2] = value_expr val[2]
906
+ result = new_call val[0], :">>", argl(val[2])
907
+ }
908
+ | arg tANDOP arg
909
+ {
910
+ result = logical_op :and, val[0], val[2]
911
+ }
912
+ | arg tOROP arg
913
+ {
914
+ result = logical_op :or, val[0], val[2]
915
+ }
916
+ | kDEFINED opt_nl arg
917
+ {
918
+ (_, line), _, arg = val
919
+ result = s(:defined, arg).line line
920
+ }
921
+ | arg tEH arg opt_nl tCOLON arg
922
+ {
923
+ c, _, t, _, _, f = val
924
+ result = s(:if, c, t, f).line c.line
925
+ }
926
+ | primary
927
+
928
+ relop: tGT
929
+ | tLT
930
+ | tGEQ
931
+ | tLEQ
932
+
933
+ rel_expr: arg relop arg =tGT
934
+ {
935
+ lhs, (op, _), rhs = val
936
+ result = new_call lhs, op.to_sym, argl(rhs)
937
+ }
938
+ | rel_expr relop arg =tGT
939
+ {
940
+ lhs, (op, _), rhs = val
941
+ warn "comparison '%s' after comparison", op
942
+ result = new_call lhs, op.to_sym, argl(rhs)
943
+ }
944
+
945
+ arg_value: arg
946
+ {
947
+ result = value_expr(val[0])
948
+ }
949
+
950
+ aref_args: none
951
+ | args trailer
952
+ {
953
+ result = args [val[0]]
954
+ }
955
+ | args tCOMMA assocs trailer
956
+ {
957
+ result = args [val[0], array_to_hash(val[2])]
958
+ }
959
+ | assocs trailer
960
+ {
961
+ result = args [array_to_hash(val[0])]
962
+ }
963
+
964
+ arg_rhs: arg =tOP_ASGN
965
+ | arg kRESCUE_MOD arg
966
+ {
967
+ body, (_, line), resbody = val
968
+ body = value_expr body
969
+ resbody = remove_begin resbody
970
+
971
+ ary = s(:array).line line
972
+ result = new_rescue(body, new_resbody(ary, resbody))
973
+ }
974
+
975
+ paren_args: tLPAREN2 opt_call_args rparen
976
+ {
977
+ _, args, _ = val
978
+ result = args
979
+ }
980
+
981
+ opt_paren_args: none
982
+ | paren_args
983
+
984
+ opt_call_args: none
985
+ | call_args
986
+ | args tCOMMA
987
+ {
988
+ result = args val
989
+ }
990
+ | args tCOMMA assocs tCOMMA
991
+ {
992
+ result = args [val[0], array_to_hash(val[2])]
993
+ }
994
+ | assocs tCOMMA
995
+ {
996
+ result = args [array_to_hash(val[0])]
997
+ }
998
+
999
+ call_args: command
1000
+ {
1001
+ warning "parenthesize argument(s) for future version"
1002
+ result = call_args val
1003
+ }
1004
+ | args opt_block_arg
1005
+ {
1006
+ result = call_args val
1007
+ }
1008
+ | assocs opt_block_arg
1009
+ {
1010
+ result = call_args [array_to_hash(val[0]), val[1]]
1011
+ }
1012
+ | args tCOMMA assocs opt_block_arg
1013
+ {
1014
+ result = call_args [val[0], array_to_hash(val[2]), val[3]]
1015
+ }
1016
+ | block_arg
1017
+ {
1018
+ result = call_args val
1019
+ }
1020
+
1021
+ command_args: {
1022
+ # parse26.y line 2200
1023
+
1024
+ # If call_args starts with a open paren '(' or
1025
+ # '[', look-ahead reading of the letters calls
1026
+ # CMDARG_PUSH(0), but the push must be done
1027
+ # after CMDARG_PUSH(1). So this code makes them
1028
+ # consistent by first cancelling the premature
1029
+ # CMDARG_PUSH(0), doing CMDARG_PUSH(1), and
1030
+ # finally redoing CMDARG_PUSH(0).
1031
+
1032
+ result = yychar = self.last_token_type.first
1033
+ lookahead = [:tLPAREN, :tLPAREN_ARG, :tLPAREN2, :tLBRACK, :tLBRACK2].include?(yychar)
1034
+ lexer.cmdarg.pop if lookahead
1035
+ lexer.cmdarg.push true
1036
+ lexer.cmdarg.push false if lookahead
1037
+ }
1038
+ call_args
1039
+ {
1040
+ yychar, args = val
1041
+
1042
+ # call_args can be followed by tLBRACE_ARG (that
1043
+ # does CMDARG_PUSH(0) in the lexer) but the push
1044
+ # must be done after CMDARG_POP() in the parser.
1045
+ # So this code does CMDARG_POP() to pop 0 pushed
1046
+ # by tLBRACE_ARG, CMDARG_POP() to pop 1 pushed
1047
+ # by command_args, and CMDARG_PUSH(0) to restore
1048
+ # back the flag set by tLBRACE_ARG.
1049
+
1050
+ lookahead = [:tLBRACE_ARG].include?(yychar)
1051
+ lexer.cmdarg.pop if lookahead
1052
+ lexer.cmdarg.pop
1053
+ lexer.cmdarg.push false if lookahead
1054
+ result = args
1055
+ }
1056
+
1057
+ block_arg: tAMPER arg_value
1058
+ {
1059
+ _, arg = val
1060
+ result = s(:block_pass, arg).line arg.line
1061
+ }
1062
+
1063
+ opt_block_arg: tCOMMA block_arg
1064
+ {
1065
+ result = val[1]
1066
+ }
1067
+ | none
1068
+
1069
+ args: arg_value
1070
+ {
1071
+ arg, = val
1072
+ lineno = arg.line || lexer.lineno # HACK
1073
+
1074
+ result = s(:array, arg).line lineno
1075
+ }
1076
+ | tSTAR arg_value
1077
+ {
1078
+ _, arg = val
1079
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
1080
+ }
1081
+ | args tCOMMA arg_value
1082
+ {
1083
+ args, _, id = val
1084
+ result = self.list_append args, id
1085
+ }
1086
+ | args tCOMMA tSTAR arg_value
1087
+ {
1088
+ # TODO: the line number from tSTAR has been dropped
1089
+ args, _, _, id = val
1090
+ line = lexer.lineno
1091
+ result = self.list_append args, s(:splat, id).line(line)
1092
+ }
1093
+
1094
+ mrhs_arg: mrhs
1095
+ {
1096
+ result = new_masgn_arg val[0]
1097
+ }
1098
+ | arg_value
1099
+ {
1100
+ result = new_masgn_arg val[0], :wrap
1101
+ }
1102
+
1103
+ mrhs: args tCOMMA arg_value
1104
+ {
1105
+ result = val[0] << val[2]
1106
+ }
1107
+ | args tCOMMA tSTAR arg_value
1108
+ {
1109
+ # TODO: make all tXXXX terminals include lexer.lineno
1110
+ arg, _, _, splat = val
1111
+ result = self.arg_concat arg, splat
1112
+ }
1113
+ | tSTAR arg_value
1114
+ {
1115
+ _, arg = val
1116
+ result = s(:splat, arg).line arg.line
1117
+ }
1118
+
1119
+ primary: literal
1120
+ | strings
1121
+ | xstring
1122
+ | regexp
1123
+ | words
1124
+ | qwords
1125
+ | symbols
1126
+ | qsymbols
1127
+ | var_ref
1128
+ | backref
1129
+ | tFID
1130
+ {
1131
+ (msg, line), = val
1132
+ result = new_call nil, msg.to_sym
1133
+ result.line line
1134
+ }
1135
+ | k_begin
1136
+ {
1137
+ lexer.cmdarg.push false
1138
+ result = self.lexer.lineno
1139
+ }
1140
+ bodystmt k_end
1141
+ {
1142
+ lexer.cmdarg.pop
1143
+ result = new_begin val
1144
+ }
1145
+ | tLPAREN_ARG
1146
+ {
1147
+ lexer.lex_state = EXPR_ENDARG
1148
+ result = lexer.lineno
1149
+ }
1150
+ rparen
1151
+ {
1152
+ _, line, _ = val
1153
+ result = s(:begin).line line
1154
+ }
1155
+ | tLPAREN_ARG
1156
+ stmt
1157
+ {
1158
+ lexer.lex_state = EXPR_ENDARG
1159
+ }
1160
+ rparen
1161
+ {
1162
+ _, stmt, _, _, = val
1163
+ # warning "(...) interpreted as grouped expression"
1164
+ result = stmt
1165
+ }
1166
+ | tLPAREN compstmt tRPAREN
1167
+ {
1168
+ _, stmt, _ = val
1169
+ result = stmt
1170
+ result ||= s(:nil).line lexer.lineno
1171
+ result.paren = true
1172
+ }
1173
+ | primary_value tCOLON2 tCONSTANT
1174
+ {
1175
+ expr, _, (id, _line) = val
1176
+
1177
+ result = s(:colon2, expr, id.to_sym).line expr.line
1178
+ }
1179
+ | tCOLON3 tCONSTANT
1180
+ {
1181
+ result = wrap :colon3, val[1]
1182
+ }
1183
+ | tLBRACK { result = lexer.lineno } aref_args tRBRACK
1184
+ {
1185
+ _, line, args, _ = val
1186
+ result = args || s(:array)
1187
+ result.sexp_type = :array # aref_args is :args
1188
+ result.line line
1189
+ }
1190
+ | tLBRACE
1191
+ {
1192
+ result = self.lexer.lineno
1193
+ }
1194
+ assoc_list tRCURLY
1195
+ {
1196
+ result = new_hash val
1197
+ }
1198
+ | k_return
1199
+ {
1200
+ (_, line), = val
1201
+ result = s(:return).line line
1202
+ }
1203
+ | kYIELD tLPAREN2 call_args rparen
1204
+ {
1205
+ (_, line), _, args, _ = val
1206
+
1207
+ result = new_yield(args).line line
1208
+ }
1209
+ | kYIELD tLPAREN2 rparen
1210
+ {
1211
+ (_, line), _, _ = val
1212
+
1213
+ result = new_yield.line line
1214
+ }
1215
+ | kYIELD
1216
+ {
1217
+ (_, line), = val
1218
+
1219
+ result = new_yield.line line
1220
+ }
1221
+ | kDEFINED opt_nl tLPAREN2 expr rparen
1222
+ {
1223
+ (_, line), _, _, arg, _ = val
1224
+
1225
+ result = s(:defined, arg).line line
1226
+ }
1227
+ | kNOT tLPAREN2 expr rparen
1228
+ {
1229
+ _, _, lhs, _ = val
1230
+ result = new_call lhs, :"!"
1231
+ }
1232
+ | kNOT tLPAREN2 rparen
1233
+ {
1234
+ debug 20
1235
+ }
1236
+ | fcall brace_block
1237
+ {
1238
+ call, iter = val
1239
+
1240
+ iter.insert 1, call
1241
+ result = iter
1242
+ # FIX: probably not: call.line = iter.line
1243
+ }
1244
+ | method_call
1245
+ | method_call brace_block
1246
+ {
1247
+ call, iter = val[0], val[1]
1248
+ block_dup_check call, iter
1249
+ iter.insert 1, call # FIX
1250
+ result = iter
1251
+ }
1252
+ | lambda
1253
+ {
1254
+ expr, = val
1255
+ result = expr
1256
+ }
1257
+ | k_if expr_value then compstmt if_tail k_end
1258
+ {
1259
+ _, c, _, t, f, _ = val
1260
+ result = new_if c, t, f
1261
+ }
1262
+ | k_unless expr_value then compstmt opt_else k_end
1263
+ {
1264
+ _, c, _, t, f, _ = val
1265
+ result = new_if c, f, t
1266
+ }
1267
+ | k_while expr_value_do compstmt k_end
1268
+ {
1269
+ _, cond, body, _ = val
1270
+ result = new_while body, cond, true
1271
+ }
1272
+ | k_until expr_value_do compstmt k_end
1273
+ {
1274
+ _, cond, body, _ = val
1275
+ result = new_until body, cond, true
1276
+ }
1277
+ | k_case expr_value opt_terms case_body k_end
1278
+ {
1279
+ (_, line), expr, _, body, _ = val
1280
+ result = new_case expr, body, line
1281
+ }
1282
+ | k_case opt_terms case_body k_end
1283
+ {
1284
+ (_, line), _, body, _ = val
1285
+ result = new_case nil, body, line
1286
+ }
1287
+ | k_for for_var kIN expr_value_do compstmt k_end
1288
+ {
1289
+ _, var, _, iter, body, _ = val
1290
+ result = new_for iter, var, body
1291
+ }
1292
+ | k_class
1293
+ {
1294
+ result = self.lexer.lineno
1295
+ }
1296
+ cpath superclass
1297
+ {
1298
+ if (self.in_def || self.in_single > 0) then
1299
+ yyerror "class definition in method body"
1300
+ end
1301
+ self.env.extend
1302
+ }
1303
+ bodystmt k_end
1304
+ {
1305
+ result = new_class val
1306
+ self.env.unextend
1307
+ self.lexer.ignore_body_comments
1308
+ }
1309
+ | k_class tLSHFT
1310
+ {
1311
+ result = self.lexer.lineno
1312
+ }
1313
+ expr
1314
+ {
1315
+ result = self.in_def
1316
+ self.in_def = false
1317
+ }
1318
+ term
1319
+ {
1320
+ result = self.in_single
1321
+ self.in_single = 0
1322
+ self.env.extend
1323
+ }
1324
+ bodystmt k_end
1325
+ {
1326
+ result = new_sclass val
1327
+ self.env.unextend
1328
+ self.lexer.ignore_body_comments
1329
+ }
1330
+ | k_module
1331
+ {
1332
+ result = self.lexer.lineno
1333
+ }
1334
+ cpath
1335
+ {
1336
+ yyerror "module definition in method body" if
1337
+ self.in_def or self.in_single > 0
1338
+
1339
+ self.env.extend
1340
+ }
1341
+ bodystmt k_end
1342
+ {
1343
+ result = new_module val
1344
+ self.env.unextend
1345
+ self.lexer.ignore_body_comments
1346
+ }
1347
+ | k_def fname
1348
+ {
1349
+ result = self.in_def
1350
+
1351
+ self.in_def = true # group = local_push
1352
+ self.env.extend
1353
+ lexer.cmdarg.push false
1354
+ lexer.cond.push false
1355
+ }
1356
+ f_arglist bodystmt k_end
1357
+ {
1358
+ result, in_def = new_defn val
1359
+
1360
+ lexer.cond.pop # group = local_pop
1361
+ lexer.cmdarg.pop
1362
+ self.env.unextend
1363
+ self.in_def = in_def
1364
+
1365
+ self.lexer.ignore_body_comments
1366
+ }
1367
+ | k_def singleton dot_or_colon
1368
+ {
1369
+ lexer.lex_state = EXPR_FNAME
1370
+ }
1371
+ fname
1372
+ {
1373
+ result = self.in_def
1374
+
1375
+ self.in_single += 1 # TODO: remove?
1376
+
1377
+ self.in_def = true # local_push
1378
+ self.env.extend
1379
+ lexer.cmdarg.push false
1380
+ lexer.cond.push false
1381
+
1382
+ lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
1383
+ }
1384
+ f_arglist bodystmt k_end
1385
+ {
1386
+
1387
+ # [kdef, recv, _, _, (name, line), in_def, args, body, kend]
1388
+ # =>
1389
+ # [kdef, recv, (name, line), in_def, args, body, kend]
1390
+
1391
+ val.delete_at 3
1392
+ val.delete_at 2
1393
+
1394
+ result, in_def = new_defs val
1395
+
1396
+ lexer.cond.pop # group = local_pop
1397
+ lexer.cmdarg.pop
1398
+ self.env.unextend
1399
+ self.in_def = in_def
1400
+
1401
+ self.in_single -= 1
1402
+
1403
+ # TODO: restore cur_arg ? what's cur_arg?
1404
+
1405
+ self.lexer.ignore_body_comments
1406
+ }
1407
+ | kBREAK
1408
+ {
1409
+ (_, line), = val
1410
+ result = s(:break).line line
1411
+ }
1412
+ | kNEXT
1413
+ {
1414
+ (_, line), = val
1415
+ result = s(:next).line line
1416
+ }
1417
+ | kREDO
1418
+ {
1419
+ (_, line), = val
1420
+ result = s(:redo).line line
1421
+ }
1422
+ | kRETRY
1423
+ {
1424
+ (_, line), = val
1425
+ result = s(:retry).line line
1426
+ }
1427
+
1428
+ primary_value: primary
1429
+ {
1430
+ result = value_expr(val[0])
1431
+ }
1432
+
1433
+ # These are really stupid
1434
+ k_begin: kBEGIN
1435
+ k_if: kIF
1436
+ k_unless: kUNLESS
1437
+ k_while: kWHILE
1438
+ k_until: kUNTIL
1439
+ k_case: kCASE
1440
+ k_for: kFOR
1441
+ k_class: kCLASS
1442
+ {
1443
+ self.comments.push self.lexer.comments
1444
+ }
1445
+ k_module: kMODULE
1446
+ {
1447
+ self.comments.push self.lexer.comments
1448
+ }
1449
+ k_def: kDEF
1450
+ {
1451
+ self.comments.push self.lexer.comments
1452
+ }
1453
+ k_do: kDO
1454
+ k_do_block: kDO_BLOCK
1455
+ k_rescue: kRESCUE
1456
+ k_ensure: kENSURE
1457
+ k_when: kWHEN
1458
+ k_else: kELSE
1459
+ k_elsif: kELSIF
1460
+ k_end: kEND
1461
+ k_return: kRETURN
1462
+
1463
+ then: term
1464
+ | kTHEN
1465
+ | term kTHEN
1466
+
1467
+ do: term
1468
+ | kDO_COND
1469
+
1470
+ if_tail: opt_else
1471
+ | k_elsif expr_value then compstmt if_tail
1472
+ {
1473
+ (_, line), c, _, t, rest = val
1474
+
1475
+ result = s(:if, c, t, rest).line line
1476
+ }
1477
+
1478
+ opt_else: none
1479
+ | kELSE compstmt
1480
+ {
1481
+ result = val[1]
1482
+ }
1483
+
1484
+ for_var: lhs
1485
+ | mlhs
1486
+ {
1487
+ val[0].delete_at 1 if val[0][1].nil? # HACK
1488
+ }
1489
+
1490
+ f_marg: f_norm_arg
1491
+ | tLPAREN f_margs rparen
1492
+ {
1493
+ result = val[1]
1494
+ }
1495
+
1496
+ f_marg_list: f_marg
1497
+ {
1498
+ sym, = val
1499
+
1500
+ result = s(:array, sym).line lexer.lineno
1501
+ }
1502
+ | f_marg_list tCOMMA f_marg
1503
+ {
1504
+ result = list_append val[0], val[2]
1505
+ }
1506
+
1507
+ f_margs: f_marg_list
1508
+ {
1509
+ args, = val
1510
+
1511
+ result = block_var args
1512
+ }
1513
+ | f_marg_list tCOMMA f_rest_marg
1514
+ {
1515
+ args, _, rest = val
1516
+
1517
+ result = block_var args, rest
1518
+ }
1519
+ | f_marg_list tCOMMA f_rest_marg tCOMMA f_marg_list
1520
+ {
1521
+ lhs, _, splat, _, rhs = val
1522
+
1523
+ result = block_var lhs, splat, rhs
1524
+ }
1525
+ | f_rest_marg
1526
+ {
1527
+ rest, = val
1528
+
1529
+ result = block_var rest
1530
+ }
1531
+ | f_rest_marg tCOMMA f_marg_list
1532
+ {
1533
+ splat, _, rest = val
1534
+
1535
+ result = block_var splat, rest
1536
+ }
1537
+
1538
+ f_rest_marg: tSTAR f_norm_arg
1539
+ {
1540
+ _, (id, line) = val
1541
+
1542
+ result = args ["*#{id}".to_sym]
1543
+ result.line line
1544
+ }
1545
+ | tSTAR
1546
+ {
1547
+ result = args [:*]
1548
+ result.line lexer.lineno # FIX: tSTAR -> line
1549
+ }
1550
+
1551
+ block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
1552
+ {
1553
+ result = call_args val
1554
+ }
1555
+ | f_block_kwarg opt_f_block_arg
1556
+ {
1557
+ result = call_args val
1558
+ }
1559
+ | f_kwrest opt_f_block_arg
1560
+ {
1561
+ result = call_args val
1562
+ }
1563
+ | f_block_arg
1564
+ {
1565
+ (id, line), = val
1566
+ result = call_args [id]
1567
+ result.line line
1568
+ }
1569
+
1570
+ opt_block_args_tail: tCOMMA block_args_tail
1571
+ {
1572
+ result = args val
1573
+ }
1574
+ | none
1575
+
1576
+ block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1577
+ {
1578
+ result = args val
1579
+ }
1580
+ | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1581
+ {
1582
+ result = args val
1583
+ }
1584
+ | f_arg tCOMMA f_block_optarg opt_block_args_tail
1585
+ {
1586
+ result = args val
1587
+ }
1588
+ | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_block_args_tail
1589
+ {
1590
+ result = args val
1591
+ }
1592
+ | f_arg tCOMMA f_rest_arg opt_block_args_tail
1593
+ {
1594
+ result = args val
1595
+ }
1596
+ | f_arg tCOMMA
1597
+ {
1598
+ result = args(val) << nil
1599
+ }
1600
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1601
+ {
1602
+ result = args val
1603
+ }
1604
+ | f_arg opt_block_args_tail
1605
+ {
1606
+ result = args val
1607
+ }
1608
+ | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1609
+ {
1610
+ result = args val
1611
+ }
1612
+ | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1613
+ {
1614
+ result = args val
1615
+ }
1616
+ | f_block_optarg opt_block_args_tail
1617
+ {
1618
+ result = args val
1619
+ }
1620
+ | f_block_optarg tCOMMA f_arg opt_block_args_tail
1621
+ {
1622
+ result = args val
1623
+ }
1624
+ | f_rest_arg opt_block_args_tail
1625
+ {
1626
+ result = args val
1627
+ }
1628
+ | f_rest_arg tCOMMA f_arg opt_block_args_tail
1629
+ {
1630
+ result = args val
1631
+ }
1632
+ | block_args_tail
1633
+ {
1634
+ result = args val
1635
+ }
1636
+
1637
+ opt_block_param: none { result = 0 }
1638
+ | block_param_def
1639
+ {
1640
+ self.lexer.command_start = true
1641
+ }
1642
+
1643
+ block_param_def: tPIPE opt_bv_decl tPIPE
1644
+ {
1645
+ # TODO: current_arg = 0
1646
+ result = args val
1647
+ }
1648
+ | tOROP
1649
+ {
1650
+ result = s(:args).line lexer.lineno
1651
+ }
1652
+ | tPIPE block_param opt_bv_decl tPIPE
1653
+ {
1654
+ # TODO: current_arg = 0
1655
+ result = args val
1656
+ }
1657
+
1658
+ opt_bv_decl: opt_nl
1659
+ | opt_nl tSEMI bv_decls opt_nl
1660
+ {
1661
+ result = args val
1662
+ }
1663
+
1664
+ bv_decls: bvar
1665
+ {
1666
+ result = args val
1667
+ }
1668
+ | bv_decls tCOMMA bvar
1669
+ {
1670
+ result = args val
1671
+ }
1672
+
1673
+ bvar: tIDENTIFIER
1674
+ {
1675
+ result = wrap :shadow, val[0]
1676
+ }
1677
+ | f_bad_arg
1678
+
1679
+ lambda: tLAMBDA
1680
+ {
1681
+ self.env.extend :dynamic
1682
+ result = [lexer.lineno, lexer.lpar_beg]
1683
+ lexer.paren_nest += 1
1684
+ lexer.lpar_beg = lexer.paren_nest
1685
+ }
1686
+ f_larglist
1687
+ {
1688
+ lexer.cmdarg.push false
1689
+ }
1690
+ lambda_body
1691
+ {
1692
+ _, (line, lpar), args, _cmdarg, body = val
1693
+ lexer.lpar_beg = lpar
1694
+
1695
+ lexer.cmdarg.pop
1696
+
1697
+ call = s(:lambda).line line
1698
+ result = new_iter call, args, body
1699
+ result.line line
1700
+ self.env.unextend # TODO: dynapush & dynapop
1701
+ }
1702
+
1703
+ f_larglist: tLPAREN2 f_args opt_bv_decl rparen
1704
+ {
1705
+ result = args val
1706
+ }
1707
+ | f_args
1708
+ {
1709
+ result = val[0]
1710
+ result = 0 if result == s(:args)
1711
+ }
1712
+
1713
+ lambda_body: tLAMBEG compstmt tRCURLY
1714
+ {
1715
+ result = val[1]
1716
+ }
1717
+ | kDO_LAMBDA bodystmt kEND
1718
+ {
1719
+ result = val[1]
1720
+ }
1721
+
1722
+ do_block: k_do_block do_body kEND
1723
+ {
1724
+ (_, line), iter, _ = val
1725
+ result = iter.line line
1726
+ }
1727
+
1728
+ block_call: command do_block
1729
+ {
1730
+ # TODO:
1731
+ ## if (nd_type($1) == NODE_YIELD) {
1732
+ ## compile_error(PARSER_ARG "block given to yield");
1733
+
1734
+ cmd, blk = val
1735
+
1736
+ syntax_error "Both block arg and actual block given." if
1737
+ cmd.block_pass?
1738
+
1739
+ if inverted? val then
1740
+ val = invert_block_call val
1741
+ cmd, blk = val
1742
+ end
1743
+
1744
+ result = blk
1745
+ result.insert 1, cmd
1746
+ }
1747
+ | block_call call_op2 operation2 opt_paren_args
1748
+ {
1749
+ lhs, _, (id, _line), args = val
1750
+
1751
+ result = new_call lhs, id.to_sym, args
1752
+ }
1753
+ | block_call call_op2 operation2 opt_paren_args brace_block
1754
+ {
1755
+ iter1, _, (name, _line), args, iter2 = val
1756
+
1757
+ call = new_call iter1, name.to_sym, args
1758
+ iter2.insert 1, call
1759
+
1760
+ result = iter2
1761
+ }
1762
+ | block_call call_op2 operation2 command_args do_block
1763
+ {
1764
+ iter1, _, (name, _line), args, iter2 = val
1765
+
1766
+ call = new_call iter1, name.to_sym, args
1767
+ iter2.insert 1, call
1768
+
1769
+ result = iter2
1770
+ }
1771
+
1772
+ method_call: fcall paren_args
1773
+ {
1774
+ call, args = val
1775
+
1776
+ result = call.concat args.sexp_body if args
1777
+ }
1778
+ | primary_value call_op operation2 opt_paren_args
1779
+ {
1780
+ recv, call_op, (op, _line), args = val
1781
+
1782
+ result = new_call recv, op.to_sym, args, call_op
1783
+ }
1784
+ | primary_value tCOLON2 operation2 paren_args
1785
+ {
1786
+ recv, _, (op, _line), args = val
1787
+
1788
+ result = new_call recv, op.to_sym, args
1789
+ }
1790
+ | primary_value tCOLON2 operation3
1791
+ {
1792
+ lhs, _, (id, _line) = val
1793
+
1794
+ result = new_call lhs, id.to_sym
1795
+ }
1796
+ | primary_value call_op paren_args
1797
+ {
1798
+ result = new_call val[0], :call, val[2], val[1]
1799
+ }
1800
+ | primary_value tCOLON2 paren_args
1801
+ {
1802
+ result = new_call val[0], :call, val[2]
1803
+ }
1804
+ | kSUPER paren_args
1805
+ {
1806
+ result = new_super val[1]
1807
+ }
1808
+ | kSUPER
1809
+ {
1810
+ result = s(:zsuper).line lexer.lineno
1811
+ }
1812
+ | primary_value tLBRACK2 opt_call_args rbracket
1813
+ {
1814
+ result = new_aref val
1815
+ }
1816
+
1817
+ brace_block: tLCURLY
1818
+ {
1819
+ self.env.extend :dynamic
1820
+ result = self.lexer.lineno
1821
+ }
1822
+ brace_body tRCURLY
1823
+ {
1824
+ _, line, body, _ = val
1825
+
1826
+ result = body
1827
+ result.line line
1828
+
1829
+ self.env.unextend
1830
+ }
1831
+ | k_do
1832
+ {
1833
+ self.env.extend :dynamic
1834
+ result = self.lexer.lineno
1835
+ }
1836
+ do_body kEND
1837
+ {
1838
+ _, line, body, _ = val
1839
+
1840
+ result = body
1841
+ result.line line
1842
+
1843
+ self.env.unextend
1844
+ }
1845
+
1846
+ brace_body: { self.env.extend :dynamic; result = self.lexer.lineno }
1847
+ { result = lexer.cmdarg.store(false) }
1848
+ opt_block_param compstmt
1849
+ {
1850
+ line, cmdarg, param, cmpstmt = val
1851
+
1852
+ result = new_brace_body param, cmpstmt, line
1853
+ self.env.unextend
1854
+ lexer.cmdarg.restore cmdarg
1855
+ lexer.cmdarg.pop # because of: cmdarg_stack >> 1 ?
1856
+ }
1857
+
1858
+ do_body: { self.env.extend :dynamic; result = self.lexer.lineno }
1859
+ { lexer.cmdarg.push false }
1860
+ opt_block_param
1861
+ compstmt
1862
+ {
1863
+ line, _cmdarg, param, cmpstmt = val
1864
+
1865
+ result = new_do_body param, cmpstmt, line
1866
+ lexer.cmdarg.pop
1867
+ self.env.unextend
1868
+ }
1869
+
1870
+ case_args: arg_value
1871
+ {
1872
+ arg, = val
1873
+
1874
+ result = s(:array, arg).line arg.line
1875
+ }
1876
+ | tSTAR arg_value
1877
+ {
1878
+ _, arg = val
1879
+
1880
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
1881
+ }
1882
+ | case_args tCOMMA arg_value
1883
+ {
1884
+ args, _, id = val
1885
+
1886
+ result = self.list_append args, id
1887
+ }
1888
+ | case_args tCOMMA tSTAR arg_value
1889
+ {
1890
+ args, _, _, id = val
1891
+
1892
+ result = self.list_append args, s(:splat, id).line(id.line)
1893
+ }
1894
+
1895
+ case_body: k_when
1896
+ {
1897
+ result = self.lexer.lineno
1898
+ }
1899
+ case_args then compstmt cases
1900
+ {
1901
+ result = new_when(val[2], val[4])
1902
+ result.line val[1]
1903
+ result << val[5] if val[5]
1904
+ }
1905
+
1906
+ cases: opt_else | case_body
1907
+
1908
+ opt_rescue: k_rescue exc_list exc_var then compstmt opt_rescue
1909
+ {
1910
+ (_, line), klasses, var, _, body, rest = val
1911
+
1912
+ klasses ||= s(:array)
1913
+ klasses << new_assign(var, s(:gvar, :"$!").line(var.line)) if var
1914
+ klasses.line line
1915
+
1916
+ result = new_resbody(klasses, body)
1917
+ result << rest if rest # UGH, rewritten above
1918
+ }
1919
+ |
1920
+ {
1921
+ result = nil
1922
+ }
1923
+
1924
+ exc_list: arg_value
1925
+ {
1926
+ arg, = val
1927
+ result = s(:array, arg).line arg.line
1928
+ }
1929
+ | mrhs
1930
+ | none
1931
+
1932
+ exc_var: tASSOC lhs
1933
+ {
1934
+ result = val[1]
1935
+ }
1936
+ | none
1937
+
1938
+ opt_ensure: k_ensure compstmt
1939
+ {
1940
+ (_, line), body = val
1941
+
1942
+ result = body || s(:nil).line(line)
1943
+ }
1944
+ | none
1945
+
1946
+ literal: numeric
1947
+ {
1948
+ (lit, line), = val
1949
+ result = s(:lit, lit).line line
1950
+ }
1951
+ | symbol
1952
+
1953
+ strings: string
1954
+ {
1955
+ str, = val
1956
+ str = s(:dstr, str.value) if str.sexp_type == :evstr
1957
+ result = str
1958
+ }
1959
+
1960
+ string: tCHAR
1961
+ {
1962
+ debug 37
1963
+ }
1964
+ | string1
1965
+ | string string1
1966
+ {
1967
+ result = self.literal_concat val[0], val[1]
1968
+ }
1969
+
1970
+ string1: tSTRING_BEG string_contents tSTRING_END
1971
+ {
1972
+ (_, line), str, (_, func) = val
1973
+
1974
+ str = dedent str if func =~ RubyLexer::STR_FUNC_DEDENT
1975
+
1976
+ result = str.line line
1977
+ }
1978
+ | tSTRING
1979
+ {
1980
+ result = new_string val
1981
+ }
1982
+
1983
+ xstring: tXSTRING_BEG xstring_contents tSTRING_END
1984
+ {
1985
+ result = new_xstring val
1986
+ # TODO: dedent?!?! SERIOUSLY?!?
1987
+ }
1988
+
1989
+ regexp: tREGEXP_BEG regexp_contents tREGEXP_END
1990
+ {
1991
+ result = new_regexp val
1992
+ }
1993
+
1994
+ words: tWORDS_BEG tSPACE tSTRING_END
1995
+ {
1996
+ (_, line), _, _ = val
1997
+
1998
+ result = s(:array).line line
1999
+ }
2000
+ | tWORDS_BEG word_list tSTRING_END
2001
+ {
2002
+ (_, line), list, _ = val
2003
+
2004
+ result = list.line line
2005
+ }
2006
+
2007
+ word_list: none
2008
+ {
2009
+ result = new_word_list
2010
+ }
2011
+ | word_list word tSPACE
2012
+ {
2013
+ result = val[0].dup << new_word_list_entry(val)
2014
+ }
2015
+
2016
+ word: string_content
2017
+ | word string_content
2018
+ {
2019
+ result = self.literal_concat val[0], val[1]
2020
+ }
2021
+
2022
+ symbols: tSYMBOLS_BEG tSPACE tSTRING_END
2023
+ {
2024
+ (_, line), _, _ = val
2025
+
2026
+ result = s(:array).line line
2027
+ }
2028
+ | tSYMBOLS_BEG symbol_list tSTRING_END
2029
+ {
2030
+ (_, line), list, _, = val
2031
+ list.line line
2032
+ result = list
2033
+ }
2034
+
2035
+ symbol_list: none
2036
+ {
2037
+ result = new_symbol_list
2038
+ }
2039
+ | symbol_list word tSPACE
2040
+ {
2041
+ list, * = val
2042
+ result = list.dup << new_symbol_list_entry(val)
2043
+ }
2044
+
2045
+ qwords: tQWORDS_BEG tSPACE tSTRING_END
2046
+ {
2047
+ (_, line), _, _ = val
2048
+
2049
+ result = s(:array).line line
2050
+ }
2051
+ | tQWORDS_BEG qword_list tSTRING_END
2052
+ {
2053
+ (_, line), list, _ = val
2054
+
2055
+ result = list.line line
2056
+ }
2057
+
2058
+ qsymbols: tQSYMBOLS_BEG tSPACE tSTRING_END
2059
+ {
2060
+ (_, line), _, _ = val
2061
+
2062
+ result = s(:array).line line
2063
+ }
2064
+ | tQSYMBOLS_BEG qsym_list tSTRING_END
2065
+ {
2066
+ (_, line), list, _ = val
2067
+
2068
+ result = list.line line
2069
+ }
2070
+
2071
+ qword_list: none
2072
+ {
2073
+ result = new_qword_list
2074
+ }
2075
+ | qword_list tSTRING_CONTENT tSPACE
2076
+ {
2077
+ result = val[0].dup << new_qword_list_entry(val)
2078
+ }
2079
+
2080
+ qsym_list: none
2081
+ {
2082
+ result = new_qsym_list
2083
+ }
2084
+ | qsym_list tSTRING_CONTENT tSPACE
2085
+ {
2086
+ result = val[0].dup << new_qsym_list_entry(val)
2087
+ }
2088
+
2089
+ string_contents: none
2090
+ {
2091
+ line = prev_value_to_lineno _values.last
2092
+ result = s(:str, +"").line line
2093
+ }
2094
+ | string_contents string_content
2095
+ {
2096
+ v1, v2 = val
2097
+ result = literal_concat v1, v2
2098
+ }
2099
+
2100
+ xstring_contents: none
2101
+ {
2102
+ result = nil
2103
+ }
2104
+ | xstring_contents string_content
2105
+ {
2106
+ v1, v2 = val
2107
+ result = literal_concat v1, v2
2108
+ }
2109
+
2110
+ regexp_contents: none
2111
+ {
2112
+ result = nil
2113
+ }
2114
+ | regexp_contents string_content
2115
+ {
2116
+ v1, v2 = val
2117
+ result = literal_concat v1, v2
2118
+ }
2119
+
2120
+ string_content: tSTRING_CONTENT
2121
+ {
2122
+ result = new_string val
2123
+ }
2124
+ | tSTRING_DVAR
2125
+ {
2126
+ result = lexer.lex_strterm
2127
+
2128
+ lexer.lex_strterm = nil
2129
+ lexer.lex_state = EXPR_BEG
2130
+ }
2131
+ string_dvar
2132
+ {
2133
+ _, strterm, str = val
2134
+ lexer.lex_strterm = strterm
2135
+ result = s(:evstr, str).line str.line
2136
+ }
2137
+ | tSTRING_DBEG
2138
+ {
2139
+ result = [lexer.lex_strterm,
2140
+ lexer.brace_nest,
2141
+ lexer.string_nest, # TODO: remove
2142
+ lexer.lex_state,
2143
+ lexer.lineno,
2144
+ ]
2145
+
2146
+ lexer.cmdarg.push false
2147
+ lexer.cond.push false
2148
+
2149
+ lexer.lex_strterm = nil
2150
+ lexer.brace_nest = 0
2151
+ lexer.string_nest = 0
2152
+
2153
+ lexer.lex_state = EXPR_BEG
2154
+ }
2155
+ compstmt
2156
+ tSTRING_DEND
2157
+ {
2158
+ _, memo, stmt, _ = val
2159
+
2160
+ lex_strterm, brace_nest, string_nest, oldlex_state, line = memo
2161
+ # TODO: heredoc_indent
2162
+
2163
+ lexer.lex_strterm = lex_strterm
2164
+ lexer.brace_nest = brace_nest
2165
+ lexer.string_nest = string_nest
2166
+
2167
+ lexer.cond.pop
2168
+ lexer.cmdarg.pop
2169
+
2170
+ lexer.lex_state = oldlex_state
2171
+
2172
+ case stmt
2173
+ when Sexp then
2174
+ case stmt.sexp_type
2175
+ when :str, :dstr, :evstr then
2176
+ result = stmt
2177
+ else
2178
+ result = s(:evstr, stmt).line line
2179
+ end
2180
+ when nil then
2181
+ result = s(:evstr).line line
2182
+ else
2183
+ debug 38
2184
+ raise "unknown string body: #{stmt.inspect}"
2185
+ end
2186
+ }
2187
+
2188
+ string_dvar: tGVAR
2189
+ {
2190
+ result = wrap :gvar, val[0]
2191
+ }
2192
+ | tIVAR
2193
+ {
2194
+ result = wrap :ivar, val[0]
2195
+ }
2196
+ | tCVAR
2197
+ {
2198
+ result = wrap :cvar, val[0]
2199
+ }
2200
+ | backref
2201
+
2202
+ symbol: ssym
2203
+ | dsym
2204
+
2205
+ ssym: tSYMBEG sym
2206
+ {
2207
+ lexer.lex_state = EXPR_END
2208
+ result = wrap :lit, val[1]
2209
+ }
2210
+ | tSYMBOL
2211
+ {
2212
+ lexer.lex_state = EXPR_END
2213
+ result = wrap :lit, val[0]
2214
+ }
2215
+
2216
+ sym: fname | tIVAR | tGVAR | tCVAR
2217
+
2218
+ dsym: tSYMBEG string_contents tSTRING_END
2219
+ {
2220
+ _, result, _ = val
2221
+
2222
+ lexer.lex_state = EXPR_END
2223
+
2224
+ result ||= s(:str, "").line lexer.lineno
2225
+
2226
+ case result.sexp_type
2227
+ when :dstr then
2228
+ result.sexp_type = :dsym
2229
+ when :str then
2230
+ result = s(:lit, result.last.to_sym).line result.line
2231
+ when :evstr then
2232
+ result = s(:dsym, "", result).line result.line
2233
+ else
2234
+ debug 39
2235
+ end
2236
+ }
2237
+
2238
+ numeric: simple_numeric
2239
+ | tUMINUS_NUM simple_numeric =tLOWEST
2240
+ {
2241
+ _, (num, line) = val
2242
+ result = [-num, line]
2243
+ }
2244
+
2245
+ simple_numeric: tINTEGER
2246
+ | tFLOAT
2247
+ | tRATIONAL
2248
+ | tIMAGINARY
2249
+
2250
+ user_variable: tIDENTIFIER
2251
+ | tIVAR
2252
+ | tGVAR
2253
+ | tCONSTANT
2254
+ | tCVAR
2255
+
2256
+ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
2257
+ | kSELF { result = s(:self).line lexer.lineno }
2258
+ | kTRUE { result = s(:true).line lexer.lineno }
2259
+ | kFALSE { result = s(:false).line lexer.lineno }
2260
+ | k__FILE__ { result = s(:str, self.file).line lexer.lineno }
2261
+ | k__LINE__ { result = s(:lit, lexer.lineno).line lexer.lineno }
2262
+ | k__ENCODING__
2263
+ {
2264
+ l = lexer.lineno
2265
+ result =
2266
+ if defined? Encoding then
2267
+ s(:colon2, s(:const, :Encoding).line(l), :UTF_8).line l
2268
+ else
2269
+ s(:str, "Unsupported!").line l
2270
+ end
2271
+ }
2272
+
2273
+ var_ref: user_variable
2274
+ {
2275
+ raise "NO: #{val.inspect}" if Sexp === val.first
2276
+ (var, line), = val
2277
+ result = Sexp === var ? var : self.gettable(var)
2278
+ result.line line
2279
+ }
2280
+ | keyword_variable
2281
+ {
2282
+ var = val[0]
2283
+ result = Sexp === var ? var : self.gettable(var)
2284
+ }
2285
+
2286
+ var_lhs: user_variable
2287
+ {
2288
+ result = self.assignable val[0]
2289
+ }
2290
+ | keyword_variable
2291
+ {
2292
+ result = self.assignable val[0]
2293
+ debug 40
2294
+ }
2295
+
2296
+ backref: tNTH_REF
2297
+ {
2298
+ (ref, line), = val
2299
+ result = s(:nth_ref, ref).line line
2300
+ }
2301
+ | tBACK_REF
2302
+ {
2303
+ (ref, line), = val
2304
+ result = s(:back_ref, ref).line line
2305
+ }
2306
+
2307
+ superclass: tLT
2308
+ {
2309
+ lexer.lex_state = EXPR_BEG
2310
+ lexer.command_start = true
2311
+ }
2312
+ expr_value term
2313
+ {
2314
+ result = val[2]
2315
+ }
2316
+ | none
2317
+ {
2318
+ result = nil
2319
+ }
2320
+
2321
+ f_arglist: tLPAREN2 f_args rparen
2322
+ {
2323
+ result = end_args val
2324
+ }
2325
+ | {
2326
+ result = self.in_kwarg
2327
+ self.in_kwarg = true
2328
+ self.lexer.lex_state |= EXPR_LABEL
2329
+ }
2330
+ f_args term
2331
+ {
2332
+ result = end_args val
2333
+ }
2334
+
2335
+ args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
2336
+ {
2337
+ result = args val
2338
+ }
2339
+ | f_kwarg opt_f_block_arg
2340
+ {
2341
+ result = args val
2342
+ }
2343
+ | f_kwrest opt_f_block_arg
2344
+ {
2345
+ result = args val
2346
+ }
2347
+ | f_block_arg
2348
+
2349
+ opt_args_tail: tCOMMA args_tail
2350
+ {
2351
+ result = val[1]
2352
+ }
2353
+ |
2354
+ {
2355
+ result = nil
2356
+ }
2357
+
2358
+ f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
2359
+ {
2360
+ result = args val
2361
+ }
2362
+ | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
2363
+ {
2364
+ result = args val
2365
+ }
2366
+ | f_arg tCOMMA f_optarg opt_args_tail
2367
+ {
2368
+ result = args val
2369
+ }
2370
+ | f_arg tCOMMA f_optarg tCOMMA f_arg opt_args_tail
2371
+ {
2372
+ result = args val
2373
+ }
2374
+ | f_arg tCOMMA f_rest_arg opt_args_tail
2375
+ {
2376
+ result = args val
2377
+ }
2378
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
2379
+ {
2380
+ result = args val
2381
+ }
2382
+ | f_arg opt_args_tail
2383
+ {
2384
+ result = args val
2385
+ }
2386
+ | f_optarg tCOMMA f_rest_arg opt_args_tail
2387
+ {
2388
+ result = args val
2389
+ }
2390
+ | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
2391
+ {
2392
+ result = args val
2393
+ }
2394
+ | f_optarg opt_args_tail
2395
+ {
2396
+ result = args val
2397
+ }
2398
+ | f_optarg tCOMMA f_arg opt_args_tail
2399
+ {
2400
+ result = args val
2401
+ }
2402
+ | f_rest_arg opt_args_tail
2403
+ {
2404
+ result = args val
2405
+ }
2406
+ | f_rest_arg tCOMMA f_arg opt_args_tail
2407
+ {
2408
+ result = args val
2409
+ }
2410
+ | args_tail
2411
+ {
2412
+ result = args val
2413
+ }
2414
+ |
2415
+ {
2416
+ result = args val
2417
+ # result.line lexer.lineno
2418
+ }
2419
+
2420
+
2421
+ f_bad_arg: tCONSTANT
2422
+ {
2423
+ yyerror "formal argument cannot be a constant"
2424
+ }
2425
+ | tIVAR
2426
+ {
2427
+ yyerror "formal argument cannot be an instance variable"
2428
+ }
2429
+ | tGVAR
2430
+ {
2431
+ yyerror "formal argument cannot be a global variable"
2432
+ }
2433
+ | tCVAR
2434
+ {
2435
+ yyerror "formal argument cannot be a class variable"
2436
+ }
2437
+
2438
+ f_norm_arg: f_bad_arg
2439
+ | tIDENTIFIER
2440
+ {
2441
+ (id, line), = val
2442
+ identifier = id.to_sym
2443
+ self.env[identifier] = :lvar
2444
+
2445
+ result = [identifier, line]
2446
+ }
2447
+
2448
+ f_arg_asgn: f_norm_arg
2449
+
2450
+ f_arg_item: f_arg_asgn
2451
+ | tLPAREN f_margs rparen
2452
+ {
2453
+ _, margs, _ = val
2454
+
2455
+ result = margs
2456
+ }
2457
+
2458
+ f_arg: f_arg_item
2459
+ {
2460
+ result = new_arg val
2461
+ }
2462
+ | f_arg tCOMMA f_arg_item
2463
+ {
2464
+ list, _, item = val
2465
+
2466
+ if list.sexp_type == :args then
2467
+ result = list
2468
+ else
2469
+ result = s(:args, list).line list.line
2470
+ end
2471
+
2472
+ result << (Sexp === item ? item : item.first)
2473
+ }
2474
+
2475
+ f_label: tLABEL
2476
+
2477
+ f_kw: f_label arg_value
2478
+ {
2479
+ # TODO: new_kw_arg
2480
+ (label, line), arg = val
2481
+
2482
+ identifier = label.to_sym
2483
+ self.env[identifier] = :lvar
2484
+
2485
+ kwarg = s(:kwarg, identifier, arg).line line
2486
+ result = s(:array, kwarg).line line
2487
+ }
2488
+ | f_label
2489
+ {
2490
+ (label, line), = val
2491
+
2492
+ id = label.to_sym
2493
+ self.env[id] = :lvar
2494
+
2495
+ result = s(:array, s(:kwarg, id).line(line)).line line
2496
+ }
2497
+
2498
+ f_block_kw: f_label primary_value
2499
+ {
2500
+ # TODO: new_kw_arg
2501
+ (label, line), expr = val
2502
+ id = label.to_sym
2503
+ self.env[id] = :lvar
2504
+
2505
+ result = s(:array, s(:kwarg, id, expr).line(line)).line line
2506
+ }
2507
+ | f_label
2508
+ {
2509
+ # TODO: new_kw_arg
2510
+ (label, line), = val
2511
+ id = label.to_sym
2512
+ self.env[id] = :lvar
2513
+
2514
+ result = s(:array, s(:kwarg, id).line(line)).line line
2515
+ }
2516
+
2517
+ f_block_kwarg: f_block_kw
2518
+ | f_block_kwarg tCOMMA f_block_kw
2519
+ {
2520
+ list, _, item = val
2521
+ result = list << item.last
2522
+ }
2523
+
2524
+ f_kwarg: f_kw
2525
+ | f_kwarg tCOMMA f_kw
2526
+ {
2527
+ result = args val
2528
+ }
2529
+
2530
+ kwrest_mark: tPOW
2531
+ | tDSTAR
2532
+
2533
+
2534
+ f_kwrest: kwrest_mark tIDENTIFIER
2535
+ {
2536
+ _, (id, line) = val
2537
+
2538
+ name = id.to_sym
2539
+ self.assignable [name, line]
2540
+ result = [:"**#{name}", line]
2541
+ }
2542
+ | kwrest_mark
2543
+ {
2544
+ id = :"**"
2545
+ self.env[id] = :lvar # TODO: needed?!?
2546
+ result = [id, lexer.lineno] # TODO: tPOW/tDSTAR include lineno
2547
+ }
2548
+
2549
+ f_opt: f_arg_asgn tEQL arg_value
2550
+ {
2551
+ lhs, _, rhs = val
2552
+ result = self.assignable lhs, rhs
2553
+ # TODO: detect duplicate names
2554
+ }
2555
+
2556
+ f_block_opt: f_arg_asgn tEQL primary_value
2557
+ {
2558
+ lhs, _, rhs = val
2559
+ result = self.assignable lhs, rhs
2560
+ }
2561
+
2562
+ f_block_optarg: f_block_opt
2563
+ {
2564
+ optblk, = val
2565
+ result = s(:block, optblk).line optblk.line
2566
+ }
2567
+ | f_block_optarg tCOMMA f_block_opt
2568
+ {
2569
+ optarg, _, optblk = val
2570
+ result = optarg
2571
+ result << optblk
2572
+ }
2573
+
2574
+ f_optarg: f_opt
2575
+ {
2576
+ opt, = val
2577
+ result = s(:block, opt).line opt.line
2578
+ }
2579
+ | f_optarg tCOMMA f_opt
2580
+ {
2581
+ result = self.block_append val[0], val[2]
2582
+ }
2583
+
2584
+ restarg_mark: tSTAR2 | tSTAR
2585
+
2586
+ f_rest_arg: restarg_mark tIDENTIFIER
2587
+ {
2588
+ # TODO: differs from parse.y - needs tests
2589
+ _, (id, line) = val
2590
+ name = id.to_sym
2591
+ self.assignable [name, line]
2592
+ result = [:"*#{name}", line]
2593
+ }
2594
+ | restarg_mark
2595
+ {
2596
+ name = :"*"
2597
+ self.env[name] = :lvar
2598
+ result = [name, lexer.lineno] # FIX: tSTAR to include lineno
2599
+ }
2600
+
2601
+ blkarg_mark: tAMPER2 | tAMPER
2602
+
2603
+ f_block_arg: blkarg_mark tIDENTIFIER
2604
+ {
2605
+ _, (id, line) = val
2606
+ identifier = id.to_sym
2607
+
2608
+ self.env[identifier] = :lvar
2609
+ result = ["&#{identifier}".to_sym, line]
2610
+ }
2611
+
2612
+ opt_f_block_arg: tCOMMA f_block_arg
2613
+ {
2614
+ _, arg = val
2615
+ result = arg
2616
+ }
2617
+ |
2618
+ {
2619
+ result = nil
2620
+ }
2621
+
2622
+ singleton: var_ref
2623
+ | tLPAREN2
2624
+ {
2625
+ lexer.lex_state = EXPR_BEG
2626
+ }
2627
+ expr rparen
2628
+ {
2629
+ result = val[2]
2630
+ yyerror "Can't define single method for literals." if
2631
+ result.sexp_type == :lit
2632
+ }
2633
+
2634
+ assoc_list: none
2635
+ {
2636
+ result = s(:array).line lexer.lineno
2637
+ }
2638
+ | assocs trailer
2639
+
2640
+ assocs: assoc
2641
+ | assocs tCOMMA assoc
2642
+ {
2643
+ list = val[0].dup
2644
+ more = val[2].sexp_body
2645
+ list.push(*more) unless more.empty?
2646
+ result = list
2647
+ result.sexp_type = :hash
2648
+ }
2649
+
2650
+ assoc: arg_value tASSOC arg_value
2651
+ {
2652
+ v1, _, v2 = val
2653
+ result = s(:array, v1, v2).line v1.line
2654
+ }
2655
+ | tLABEL arg_value
2656
+ {
2657
+ label, arg = val
2658
+
2659
+ lit = wrap :lit, label
2660
+ result = s(:array, lit, arg).line lit.line
2661
+ }
2662
+ | tSTRING_BEG string_contents tLABEL_END arg_value
2663
+ {
2664
+ (_, line), sym, _, value = val
2665
+
2666
+ sym.sexp_type = :dsym
2667
+
2668
+ result = s(:array, sym, value).line line
2669
+ }
2670
+ | tDSTAR arg_value
2671
+ {
2672
+ _, arg = val
2673
+ line = arg.line
2674
+ result = s(:array, s(:kwsplat, arg).line(line)).line line
2675
+ }
2676
+
2677
+ operation: tIDENTIFIER | tCONSTANT | tFID
2678
+ operation2: tIDENTIFIER | tCONSTANT | tFID | op
2679
+ operation3: tIDENTIFIER | tFID | op
2680
+ dot_or_colon: tDOT | tCOLON2
2681
+ call_op: tDOT
2682
+
2683
+ call_op2: call_op
2684
+ | tCOLON2
2685
+
2686
+ opt_terms: | terms
2687
+ opt_nl: | tNL
2688
+ rparen: opt_nl tRPAREN
2689
+ rbracket: opt_nl tRBRACK
2690
+ trailer: | tNL | tCOMMA
2691
+
2692
+ term: tSEMI { yyerrok }
2693
+ | tNL
2694
+
2695
+ terms: term
2696
+ | terms tSEMI { yyerrok }
2697
+
2698
+ none: { result = nil; }
2699
+ end
2700
+
2701
+ ---- inner
2702
+
2703
+ require "ruby_lexer"
2704
+ require "ruby_parser_extras"
2705
+ include RubyLexer::State::Values
2706
+
2707
+ # :stopdoc:
2708
+
2709
+ # Local Variables: **
2710
+ # racc-token-length-max:14 **
2711
+ # End: **