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