ruby_parser 3.0.0 → 3.19.1

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