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,3536 @@
1
+ # -*- racc -*-
2
+
3
+ #if V == 30
4
+ class Ruby30Parser
5
+ #elif V == 31
6
+ class Ruby31Parser
7
+ #else
8
+ fail "version not specified or supported on code generation"
9
+ #endif
10
+
11
+ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
12
+ kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
13
+ kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
14
+ kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
15
+ kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
16
+ k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
17
+ tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
18
+ tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
19
+ tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
20
+ tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
21
+ tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
22
+ tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
23
+ tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
24
+ tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
25
+ tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
26
+ tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA
27
+ tLAMBEG tDSTAR tCHAR tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DEND
28
+ tRATIONAL tIMAGINARY
29
+ tLABEL_END
30
+ tLONELY
31
+ tBDOT2 tBDOT3
32
+
33
+ preclow
34
+ nonassoc tLOWEST
35
+ nonassoc tLBRACE_ARG
36
+ nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
37
+ left kOR kAND
38
+ right kNOT
39
+ nonassoc kDEFINED
40
+ right tEQL tOP_ASGN
41
+ left kRESCUE_MOD
42
+ right tEH tCOLON
43
+ nonassoc tDOT2 tDOT3 tBDOT2 tBDOT3
44
+ left tOROP
45
+ left tANDOP
46
+ nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
47
+ left tGT tGEQ tLT tLEQ
48
+ left tPIPE tCARET
49
+ left tAMPER2
50
+ left tLSHFT tRSHFT
51
+ left tPLUS tMINUS
52
+ left tSTAR2 tDIVIDE tPERCENT # TODO: tSTAR2 -> tMULT
53
+ right tUMINUS_NUM tUMINUS
54
+ right tPOW
55
+ right tBANG tTILDE tUPLUS
56
+ prechigh
57
+
58
+ rule
59
+
60
+ program: {
61
+ self.lexer.lex_state = EXPR_BEG
62
+ }
63
+ top_compstmt
64
+ {
65
+ result = new_compstmt val
66
+
67
+ lexer.cond.pop # local_pop
68
+ lexer.cmdarg.pop
69
+ }
70
+
71
+ top_compstmt: top_stmts opt_terms
72
+ {
73
+ stmt, _ = val
74
+ result = stmt
75
+ }
76
+
77
+ top_stmts: none
78
+ | top_stmt
79
+ | top_stmts terms top_stmt
80
+ {
81
+ result = self.block_append val[0], val[2]
82
+ }
83
+ | error top_stmt
84
+
85
+ top_stmt: stmt
86
+ | klBEGIN
87
+ {
88
+ if (self.in_def || self.in_single > 0) then
89
+ debug 1
90
+ yyerror "BEGIN in method"
91
+ end
92
+ self.env.extend
93
+ }
94
+ begin_block
95
+ {
96
+ (_, lineno), _, iter = val
97
+ iter.line lineno
98
+
99
+ (_, preexe,) = iter
100
+ preexe.line lineno
101
+
102
+ result = iter
103
+ }
104
+
105
+ begin_block: tLCURLY { result = lexer.lineno } top_compstmt tRCURLY
106
+ {
107
+ _, line, stmt, _ = val
108
+ result = new_iter s(:preexe).line(line), 0, stmt
109
+ }
110
+
111
+ bodystmt: compstmt opt_rescue k_else
112
+ {
113
+ res = _values[-2]
114
+ yyerror "else without rescue is useless" unless res
115
+ }
116
+ compstmt
117
+ opt_ensure
118
+ {
119
+ body, resc, _, _, els, ens = val
120
+
121
+ result = new_body [body, resc, els, ens]
122
+ }
123
+ | compstmt opt_rescue opt_ensure
124
+ {
125
+ body, resc, ens = val
126
+
127
+ result = new_body [body, resc, nil, ens]
128
+ }
129
+
130
+ compstmt: stmts opt_terms
131
+ {
132
+ result = new_compstmt val
133
+ }
134
+
135
+ stmts: none
136
+ | stmt_or_begin # TODO: newline_node ?
137
+ | stmts terms stmt_or_begin
138
+ {
139
+ result = self.block_append val[0], val[2]
140
+ }
141
+ | error stmt
142
+ {
143
+ result = val[1]
144
+ debug 2
145
+ }
146
+
147
+ stmt_or_begin: stmt
148
+ | klBEGIN
149
+ {
150
+ yyerror "BEGIN is permitted only at toplevel"
151
+ }
152
+ begin_block
153
+ {
154
+ result = val[2] # wtf?
155
+ }
156
+
157
+ stmt: kALIAS fitem
158
+ {
159
+ lexer.lex_state = EXPR_FNAME
160
+ }
161
+ fitem
162
+ {
163
+ (_, line), lhs, _, rhs = val
164
+ result = s(:alias, lhs, rhs).line(line).line line
165
+ }
166
+ | kALIAS tGVAR tGVAR
167
+ {
168
+ (_, line), (lhs, _), (rhs, _) = val
169
+ result = s(:valias, lhs.to_sym, rhs.to_sym).line line
170
+ }
171
+ | kALIAS tGVAR tBACK_REF
172
+ {
173
+ (_, line), (lhs, _), (rhs, _) = val
174
+ result = s(:valias, lhs.to_sym, :"$#{rhs}").line line
175
+ }
176
+ | kALIAS tGVAR tNTH_REF
177
+ {
178
+ yyerror "can't make alias for the number variables"
179
+ }
180
+ | kUNDEF undef_list
181
+ {
182
+ result = val[1]
183
+ }
184
+ | stmt kIF_MOD expr_value
185
+ {
186
+ t, _, c = val
187
+ result = new_if c, t, nil
188
+ }
189
+ | stmt kUNLESS_MOD expr_value
190
+ {
191
+ f, _, c = val
192
+ result = new_if c, nil, f
193
+ }
194
+ | stmt kWHILE_MOD expr_value
195
+ {
196
+ e, _, c = val
197
+ result = new_while e, c, true
198
+ }
199
+ | stmt kUNTIL_MOD expr_value
200
+ {
201
+ e, _, c = val
202
+ result = new_until e, c, true
203
+ }
204
+ | stmt kRESCUE_MOD stmt
205
+ {
206
+ body, _, resbody = val
207
+
208
+ resbody = new_resbody s(:array).line(resbody.line), resbody
209
+ result = new_rescue body, resbody
210
+ }
211
+ | klEND tLCURLY compstmt tRCURLY
212
+ {
213
+ (_, line), _, stmt, _ = val
214
+
215
+ if (self.in_def || self.in_single > 0) then
216
+ debug 3
217
+ yyerror "END in method; use at_exit"
218
+ end
219
+
220
+ result = new_iter s(:postexe).line(line), 0, stmt
221
+ }
222
+ | command_asgn
223
+ | mlhs tEQL command_call
224
+ {
225
+ result = new_masgn val[0], val[2], :wrap
226
+ }
227
+ | lhs tEQL mrhs
228
+ {
229
+ lhs, _, rhs = val
230
+ result = new_assign lhs, s(:svalue, rhs).line(rhs.line)
231
+ }
232
+ | mlhs tEQL mrhs_arg kRESCUE_MOD stmt
233
+ {
234
+ # unwraps s(:to_ary, rhs)
235
+ lhs, _, (_, rhs), _, resbody = val
236
+
237
+ resbody = new_resbody s(:array).line(resbody.line), resbody
238
+
239
+ result = new_masgn lhs, new_rescue(rhs, resbody), :wrap
240
+ }
241
+ | mlhs tEQL mrhs_arg
242
+ {
243
+ result = new_masgn val[0], val[2]
244
+ }
245
+ | expr
246
+
247
+ command_asgn: lhs tEQL command_rhs
248
+ {
249
+ result = new_assign val[0], val[2]
250
+ }
251
+ # | lhs tEQL command_asgn
252
+ # {
253
+ # result = new_assign val[0], val[2]
254
+ # }
255
+ | var_lhs tOP_ASGN command_rhs
256
+ {
257
+ result = new_op_asgn val
258
+ }
259
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_rhs
260
+ {
261
+ result = new_op_asgn1 val
262
+ }
263
+ | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
264
+ {
265
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
266
+
267
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
268
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
269
+ result.line prim.line
270
+ }
271
+ | primary_value call_op tCONSTANT tOP_ASGN command_rhs
272
+ {
273
+ prim, (call_op, _), (id, _), (op_asgn, _), rhs = val
274
+
275
+ result = s(:op_asgn, prim, rhs, id.to_sym, op_asgn.to_sym)
276
+ result.sexp_type = :safe_op_asgn if call_op == '&.'
277
+ result.line prim.line
278
+ }
279
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
280
+ {
281
+ lhs1, _, (lhs2, line), (id, _), rhs = val
282
+
283
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
284
+ }
285
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
286
+ {
287
+ lhs1, _, (lhs2, line), (id, _), rhs = val
288
+
289
+ result = s(:op_asgn, lhs1, rhs, lhs2.to_sym, id.to_sym).line line
290
+ }
291
+ #if V > 30
292
+ | defn_head f_opt_paren_args tEQL command
293
+ {
294
+ result = new_endless_defn val
295
+ }
296
+ | defn_head f_opt_paren_args tEQL command kRESCUE_MOD arg
297
+ {
298
+ result = new_endless_defn val
299
+ }
300
+ | defs_head f_opt_paren_args tEQL command
301
+ {
302
+ result = new_endless_defs val
303
+ }
304
+ | defs_head f_opt_paren_args tEQL command kRESCUE_MOD arg
305
+ {
306
+ result = new_endless_defs val
307
+ }
308
+ #endif
309
+ | backref tOP_ASGN command_rhs
310
+ {
311
+ self.backref_assign_error val[0]
312
+ }
313
+
314
+ command_rhs: command_call =tOP_ASGN
315
+ {
316
+ expr, = val
317
+ result = value_expr expr
318
+ }
319
+ | command_call kRESCUE_MOD stmt
320
+ {
321
+ expr, (_, line), resbody = val
322
+
323
+ expr = value_expr expr
324
+ ary = s(:array).line line
325
+ result = new_rescue(expr, new_resbody(ary, resbody))
326
+ }
327
+ | command_asgn
328
+
329
+ expr: command_call
330
+ | expr kAND expr
331
+ {
332
+ lhs, _, rhs = val
333
+ result = logical_op :and, lhs, rhs
334
+ }
335
+ | expr kOR expr
336
+ {
337
+ lhs, _, rhs = val
338
+ result = logical_op :or, lhs, rhs
339
+ }
340
+ | kNOT opt_nl expr
341
+ {
342
+ (_, line), _, expr = val
343
+ result = new_call(expr, :"!").line line
344
+ # REFACTOR: call_uni_op
345
+ }
346
+ | tBANG command_call
347
+ {
348
+ _, cmd = val
349
+ result = new_call(cmd, :"!").line cmd.line
350
+ # TODO: fix line number to tBANG... but causes BAD shift/reduce conflict
351
+ # REFACTOR: call_uni_op -- see parse26.y
352
+ }
353
+ | arg tASSOC
354
+ {
355
+ # value_expr($1);
356
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
357
+ self.lexer.command_start = false
358
+ result = self.in_kwarg
359
+ self.in_kwarg = true
360
+ self.env.extend
361
+ }
362
+ #if V == 30
363
+ p_expr
364
+ #else
365
+ p_top_expr_body
366
+ #endif
367
+ {
368
+ lhs, _, in_kwarg, rhs = val
369
+
370
+ self.env.unextend
371
+ self.in_kwarg = in_kwarg
372
+
373
+ rhs = new_in rhs, nil, nil, rhs.line
374
+ result = new_case lhs, rhs, rhs.line
375
+ }
376
+ | arg
377
+ kIN
378
+ {
379
+ # TODO? value_expr($1);
380
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
381
+ self.lexer.command_start = false
382
+ result = self.in_kwarg
383
+ self.in_kwarg = true
384
+ self.env.extend
385
+ }
386
+ #if V == 30
387
+ p_expr
388
+ #else
389
+ p_top_expr_body
390
+ #endif
391
+ {
392
+ self.env.unextend
393
+
394
+ expr, _, old_kwarg, pat = val
395
+
396
+ expr = value_expr expr
397
+
398
+ self.in_kwarg = old_kwarg
399
+ pat_in = new_in pat, nil, nil, expr.line
400
+ result = new_case expr, pat_in, expr.line
401
+ }
402
+ | arg =tLBRACE_ARG
403
+
404
+ def_name: fname
405
+ {
406
+ # TODO: numparam_name(p, fname);
407
+
408
+ (id, line), = val
409
+ old_in_def = self.in_def
410
+
411
+ self.in_def = true # group = local_push
412
+ self.env.extend
413
+ lexer.cmdarg.push false
414
+ lexer.cond.push false
415
+
416
+ result = [id.to_sym, line, old_in_def]
417
+ }
418
+ defn_head: k_def def_name
419
+ {
420
+ _, name = val
421
+ result = name
422
+ }
423
+ defs_head: k_def singleton dot_or_colon
424
+ {
425
+ lexer.lex_state = EXPR_FNAME
426
+ }
427
+ def_name
428
+ {
429
+ lexer.lex_state = EXPR_ENDFN|EXPR_LABEL
430
+ self.in_single += 1 # TODO: remove?
431
+
432
+ # self.in_def = true # local_push
433
+ # self.env.extend
434
+ # lexer.cmdarg.push false
435
+ # lexer.cond.push false
436
+
437
+ _, recv, _, _, name = val
438
+
439
+ result = [recv, name]
440
+ }
441
+
442
+ expr_value: expr
443
+ {
444
+ result = value_expr(val[0])
445
+ }
446
+
447
+ expr_value_do: {
448
+ lexer.cond.push true
449
+ }
450
+ expr_value do
451
+ {
452
+ lexer.cond.pop
453
+ }
454
+ {
455
+ _, expr, _, _ = val
456
+ result = expr
457
+ }
458
+
459
+ command_call: command
460
+ | block_command
461
+
462
+ block_command: block_call
463
+ | block_call call_op2 operation2 command_args
464
+ {
465
+ blk, _, (msg, _line), args = val
466
+ result = new_call(blk, msg.to_sym, args).line blk.line
467
+ }
468
+
469
+ cmd_brace_block: tLBRACE_ARG
470
+ {
471
+ # self.env.extend(:dynamic)
472
+ result = self.lexer.lineno
473
+ }
474
+ brace_body tRCURLY
475
+ {
476
+ _, line, body, _ = val
477
+
478
+ result = body
479
+ result.line line
480
+
481
+ # self.env.unextend
482
+ }
483
+
484
+ fcall: operation
485
+ {
486
+ (msg, line), = val
487
+ result = new_call(nil, msg.to_sym).line line
488
+ }
489
+
490
+ command: fcall command_args =tLOWEST
491
+ {
492
+ call, args = val
493
+ result = call.concat args.sexp_body
494
+ }
495
+ | fcall command_args cmd_brace_block
496
+ {
497
+ call, args, block = val
498
+
499
+ result = call.concat args.sexp_body
500
+
501
+ if block then
502
+ block_dup_check result, block
503
+
504
+ result, operation = block, result
505
+ result.insert 1, operation
506
+ end
507
+ }
508
+ | primary_value call_op operation2 command_args =tLOWEST
509
+ {
510
+ lhs, callop, (op, _), args = val
511
+
512
+ result = new_call lhs, op.to_sym, args, callop
513
+ result.line lhs.line
514
+ }
515
+ | primary_value call_op operation2 command_args cmd_brace_block
516
+ {
517
+ recv, _, (msg, _line), args, block = val
518
+ call = new_call recv, msg.to_sym, args, val[1]
519
+
520
+ block_dup_check call, block
521
+
522
+ block.insert 1, call
523
+ result = block
524
+ }
525
+ | primary_value tCOLON2 operation2 command_args =tLOWEST
526
+ {
527
+ lhs, _, (id, line), args = val
528
+
529
+ result = new_call lhs, id.to_sym, args
530
+ result.line line
531
+ }
532
+ | primary_value tCOLON2 operation2 command_args cmd_brace_block
533
+ {
534
+ recv, _, (msg, _line), args, block = val
535
+ call = new_call recv, msg.to_sym, args
536
+
537
+ block_dup_check call, block
538
+
539
+ block.insert 1, call
540
+ result = block
541
+ }
542
+ | kSUPER command_args
543
+ {
544
+ result = new_super val[1]
545
+ }
546
+ | kYIELD command_args
547
+ {
548
+ (_, line), args = val
549
+ result = new_yield args
550
+ result.line line # TODO: push to new_yield
551
+ }
552
+ | k_return call_args
553
+ {
554
+ line = val[0].last
555
+ result = s(:return, ret_args(val[1])).line(line)
556
+ }
557
+ | kBREAK call_args
558
+ {
559
+ (_, line), args = val
560
+ result = s(:break, ret_args(args)).line line
561
+ }
562
+ | kNEXT call_args
563
+ {
564
+ line = val[0].last
565
+ result = s(:next, ret_args(val[1])).line(line)
566
+ }
567
+
568
+ mlhs: mlhs_basic
569
+ | tLPAREN mlhs_inner rparen
570
+ {
571
+ result = val[1]
572
+ }
573
+
574
+ mlhs_inner: mlhs_basic
575
+ | tLPAREN mlhs_inner rparen
576
+ {
577
+ _, arg, _ = val
578
+ l = arg.line
579
+
580
+ result = s(:masgn, s(:array, arg).line(l)).line l
581
+ }
582
+
583
+ mlhs_basic: mlhs_head
584
+ {
585
+ head, = val
586
+ result = s(:masgn, head).line head.line
587
+ }
588
+ | mlhs_head mlhs_item
589
+ {
590
+ lhs, rhs = val
591
+ result = s(:masgn, lhs << rhs.compact).line lhs.line
592
+ }
593
+ | mlhs_head tSTAR mlhs_node
594
+ {
595
+ head, _, tail = val
596
+ head << s(:splat, tail).line(tail.line)
597
+ result = s(:masgn, head).line head.line
598
+ }
599
+ | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
600
+ {
601
+ ary1, _, splat, _, ary2 = val
602
+
603
+ result = list_append ary1, s(:splat, splat).line(splat.line)
604
+ result.concat ary2.sexp_body
605
+ result = s(:masgn, result).line result.line
606
+ }
607
+ | mlhs_head tSTAR
608
+ {
609
+ head, _ = val
610
+ l = head.line
611
+ result = s(:masgn, head << s(:splat).line(l)).line l
612
+ }
613
+ | mlhs_head tSTAR tCOMMA mlhs_post
614
+ {
615
+ head, _, _, post = val
616
+ ary = list_append head, s(:splat).line(head.line)
617
+ ary.concat post.sexp_body
618
+ result = s(:masgn, ary).line ary.line
619
+ }
620
+ | tSTAR mlhs_node
621
+ {
622
+ _, node = val
623
+ l = node.line
624
+ splat = s(:splat, node).line l
625
+ ary = s(:array, splat).line l
626
+ result = s(:masgn, ary).line l
627
+ }
628
+ | tSTAR mlhs_node tCOMMA mlhs_post
629
+ {
630
+ _, node, _, post = val
631
+
632
+ splat = s(:splat, node).line node.line
633
+ ary = s(:array, splat).line splat.line
634
+ ary.concat post.sexp_body
635
+ result = s(:masgn, ary).line ary.line
636
+ }
637
+ | tSTAR
638
+ {
639
+ l = lexer.lineno
640
+ result = s(:masgn, s(:array, s(:splat).line(l)).line(l)).line l
641
+ }
642
+ | tSTAR tCOMMA mlhs_post
643
+ {
644
+ _, _, post = val
645
+ l = post.line
646
+
647
+ splat = s(:splat).line l
648
+ ary = s(:array, splat, *post.sexp_body).line l
649
+ result = s(:masgn, ary).line l
650
+ }
651
+
652
+ mlhs_item: mlhs_node
653
+ | tLPAREN mlhs_inner rparen
654
+ {
655
+ result = val[1]
656
+ }
657
+
658
+ mlhs_head: mlhs_item tCOMMA
659
+ {
660
+ lhs, _ = val
661
+ result = s(:array, lhs).line lhs.line
662
+ }
663
+ | mlhs_head mlhs_item tCOMMA
664
+ {
665
+ result = val[0] << val[1].compact
666
+ }
667
+
668
+ mlhs_post: mlhs_item
669
+ {
670
+ item, = val
671
+ result = s(:array, item).line item.line
672
+ }
673
+ | mlhs_post tCOMMA mlhs_item
674
+ {
675
+ result = list_append val[0], val[2]
676
+ }
677
+
678
+ mlhs_node: user_variable
679
+ {
680
+ result = self.assignable val[0]
681
+ }
682
+ | keyword_variable
683
+ {
684
+ result = self.assignable val[0]
685
+ }
686
+ | primary_value tLBRACK2 opt_call_args rbracket
687
+ {
688
+ result = self.aryset val[0], val[2]
689
+ }
690
+ | primary_value call_op tIDENTIFIER
691
+ {
692
+ lhs, call_op, (id, _line) = val
693
+
694
+ result = new_attrasgn lhs, id, call_op
695
+ }
696
+ | primary_value tCOLON2 tIDENTIFIER
697
+ {
698
+ recv, _, (id, _line) = val
699
+ result = new_attrasgn recv, id
700
+ }
701
+ | primary_value call_op tCONSTANT
702
+ {
703
+ lhs, call_op, (id, _line) = val
704
+
705
+ result = new_attrasgn lhs, id, call_op
706
+ }
707
+ | primary_value tCOLON2 tCONSTANT
708
+ {
709
+ if (self.in_def || self.in_single > 0) then
710
+ debug 4
711
+ yyerror "dynamic constant assignment"
712
+ end
713
+
714
+ expr, _, (id, _line) = val
715
+ l = expr.line
716
+
717
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l), nil).line l
718
+ }
719
+ | tCOLON3 tCONSTANT
720
+ {
721
+ if (self.in_def || self.in_single > 0) then
722
+ debug 5
723
+ yyerror "dynamic constant assignment"
724
+ end
725
+
726
+ _, (id, l) = val
727
+
728
+ result = s(:const, nil, s(:colon3, id.to_sym).line(l)).line l
729
+ }
730
+ | backref
731
+ {
732
+ ref, = val
733
+
734
+ self.backref_assign_error ref
735
+ }
736
+
737
+ lhs: user_variable
738
+ {
739
+ var, = val
740
+
741
+ result = self.assignable var
742
+ }
743
+ | keyword_variable
744
+ {
745
+ var, = val
746
+
747
+ result = self.assignable var
748
+
749
+ debug 6
750
+ }
751
+ | primary_value tLBRACK2 opt_call_args rbracket
752
+ {
753
+ lhs, _, args, _ = val
754
+
755
+ result = self.aryset lhs, args
756
+ }
757
+ | primary_value call_op tIDENTIFIER # REFACTOR
758
+ {
759
+ lhs, op, (id, _line) = val
760
+
761
+ result = new_attrasgn lhs, id, op
762
+ }
763
+ | primary_value tCOLON2 tIDENTIFIER
764
+ {
765
+ lhs, _, (id, _line) = val
766
+
767
+ result = new_attrasgn lhs, id
768
+ }
769
+ | primary_value call_op tCONSTANT # REFACTOR?
770
+ {
771
+ lhs, call_op, (id, _line) = val
772
+
773
+ result = new_attrasgn lhs, id, call_op
774
+ }
775
+ | primary_value tCOLON2 tCONSTANT
776
+ {
777
+ expr, _, (id, _line) = val
778
+
779
+ if (self.in_def || self.in_single > 0) then
780
+ debug 7
781
+ yyerror "dynamic constant assignment"
782
+ end
783
+
784
+ l = expr.line
785
+ result = s(:const, s(:colon2, expr, id.to_sym).line(l)).line l
786
+ }
787
+ | tCOLON3 tCONSTANT
788
+ {
789
+ _, (id, l) = val
790
+
791
+ if (self.in_def || self.in_single > 0) then
792
+ debug 8
793
+ yyerror "dynamic constant assignment"
794
+ end
795
+
796
+ result = s(:const, s(:colon3, id.to_sym).line(l)).line l
797
+ }
798
+ | backref
799
+ {
800
+ self.backref_assign_error val[0]
801
+ }
802
+
803
+ cname: tIDENTIFIER
804
+ {
805
+ yyerror "class/module name must be CONSTANT"
806
+ }
807
+ | tCONSTANT
808
+
809
+ cpath: tCOLON3 cname
810
+ {
811
+ result = wrap :colon3, val[1]
812
+ }
813
+ | cname
814
+ {
815
+ (id, line), = val
816
+ result = [id.to_sym, line] # TODO: sexp?
817
+ }
818
+ | primary_value tCOLON2 cname
819
+ {
820
+ pval, _, (name, _line) = val
821
+
822
+ result = s(:colon2, pval, name.to_sym)
823
+ result.line pval.line
824
+ }
825
+
826
+ fname: tIDENTIFIER | tCONSTANT | tFID
827
+ | op
828
+ {
829
+ lexer.lex_state = EXPR_END
830
+ }
831
+
832
+ | reswords
833
+
834
+ fitem: fname
835
+ {
836
+ result = wrap :lit, val[0]
837
+ }
838
+ | symbol
839
+
840
+ undef_list: fitem
841
+ {
842
+ result = new_undef val[0]
843
+ }
844
+ |
845
+ undef_list tCOMMA
846
+ {
847
+ lexer.lex_state = EXPR_FNAME
848
+ }
849
+ fitem
850
+ {
851
+ result = new_undef val[0], val[3]
852
+ }
853
+
854
+ op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
855
+ | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
856
+ | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
857
+ | tSTAR | tDIVIDE | tPERCENT | tPOW | tDSTAR | tBANG | tTILDE
858
+ | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
859
+
860
+ reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
861
+ | kALIAS | kAND | kBEGIN | kBREAK | kCASE
862
+ | kCLASS | kDEF | kDEFINED | kDO | kELSE
863
+ | kELSIF | kEND | kENSURE | kFALSE | kFOR
864
+ | kIN | kMODULE | kNEXT | kNIL | kNOT
865
+ | kOR | kREDO | kRESCUE | kRETRY | kRETURN
866
+ | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
867
+ | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
868
+ | kUNTIL
869
+
870
+ arg: lhs tEQL arg_rhs
871
+ {
872
+ result = new_assign val[0], val[2]
873
+ }
874
+ | var_lhs tOP_ASGN arg_rhs
875
+ {
876
+ result = new_op_asgn val
877
+ }
878
+ | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg_rhs
879
+ {
880
+ result = new_op_asgn1 val
881
+ }
882
+ | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
883
+ {
884
+ result = new_op_asgn2 val
885
+ }
886
+ | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
887
+ {
888
+ result = new_op_asgn2 val
889
+ }
890
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
891
+ {
892
+ lhs, _, (id, _line), (op, _), rhs = val
893
+
894
+ result = s(:op_asgn, lhs, rhs, id.to_sym, op.to_sym).line lhs.line
895
+ }
896
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
897
+ {
898
+ lhs1, _, (lhs2, _line), op, rhs = val
899
+
900
+ lhs = s(:colon2, lhs1, lhs2.to_sym).line lhs1.line
901
+ result = new_const_op_asgn [lhs, op, rhs]
902
+ }
903
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
904
+ {
905
+ _, lhs, op, rhs = val
906
+
907
+ lhs = wrap :colon3, lhs
908
+ result = new_const_op_asgn [lhs, op, rhs]
909
+ }
910
+ | backref tOP_ASGN arg_rhs
911
+ {
912
+ # TODO: lhs = var_field val[0]
913
+ asgn = new_op_asgn val
914
+ result = self.backref_assign_error asgn
915
+ }
916
+ | arg tDOT2 arg
917
+ {
918
+ v1, v2 = val[0], val[2]
919
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
920
+ result = s(:lit, (v1.last)..(v2.last)).line v1.line
921
+ else
922
+ result = s(:dot2, v1, v2).line v1.line
923
+ end
924
+ }
925
+ | arg tDOT3 arg
926
+ {
927
+ v1, v2 = val[0], val[2]
928
+ if v1.sexp_type == :lit and v2.sexp_type == :lit and Integer === v1.last and Integer === v2.last then
929
+ result = s(:lit, (v1.last)...(v2.last)).line v1.line
930
+ else
931
+ result = s(:dot3, v1, v2).line v1.line
932
+ end
933
+ }
934
+ | arg tDOT2
935
+ {
936
+ v1, _ = val
937
+ v2 = nil
938
+
939
+ result = s(:dot2, v1, v2).line v1.line
940
+ }
941
+ | arg tDOT3
942
+ {
943
+ v1, _ = val
944
+ v2 = nil
945
+
946
+ result = s(:dot3, v1, v2).line v1.line
947
+ }
948
+
949
+ | tBDOT2 arg
950
+ {
951
+ _, v2, = val
952
+ v1 = nil
953
+
954
+ result = s(:dot2, v1, v2).line v2.line
955
+ }
956
+ | tBDOT3 arg
957
+ {
958
+ _, v2 = val
959
+ v1 = nil
960
+
961
+ result = s(:dot3, v1, v2).line v2.line
962
+ }
963
+
964
+ | arg tPLUS arg
965
+ {
966
+ result = new_call val[0], :+, argl(val[2])
967
+ }
968
+ | arg tMINUS arg
969
+ {
970
+ result = new_call val[0], :-, argl(val[2])
971
+ }
972
+ | arg tSTAR2 arg # TODO: rename
973
+ {
974
+ result = new_call val[0], :*, argl(val[2])
975
+ }
976
+ | arg tDIVIDE arg
977
+ {
978
+ result = new_call val[0], :"/", argl(val[2])
979
+ }
980
+ | arg tPERCENT arg
981
+ {
982
+ result = new_call val[0], :"%", argl(val[2])
983
+ }
984
+ | arg tPOW arg
985
+ {
986
+ result = new_call val[0], :**, argl(val[2])
987
+ }
988
+ | tUMINUS_NUM simple_numeric tPOW arg
989
+ {
990
+ _, num, _, arg = val
991
+ lit = wrap :lit, num
992
+ result = new_call(new_call(lit, :"**", argl(arg)), :"-@")
993
+
994
+ }
995
+ | tUPLUS arg
996
+ {
997
+ result = new_call val[1], :"+@"
998
+ }
999
+ | tUMINUS arg
1000
+ {
1001
+ result = new_call val[1], :"-@"
1002
+ }
1003
+ | arg tPIPE arg
1004
+ {
1005
+ result = new_call val[0], :"|", argl(val[2])
1006
+ }
1007
+ | arg tCARET arg
1008
+ {
1009
+ result = new_call val[0], :"^", argl(val[2])
1010
+ }
1011
+ | arg tAMPER2 arg
1012
+ {
1013
+ result = new_call val[0], :"&", argl(val[2])
1014
+ }
1015
+ | arg tCMP arg
1016
+ {
1017
+ result = new_call val[0], :"<=>", argl(val[2])
1018
+ }
1019
+ | rel_expr =tCMP
1020
+ | arg tEQ arg
1021
+ {
1022
+ result = new_call val[0], :"==", argl(val[2])
1023
+ }
1024
+ | arg tEQQ arg
1025
+ {
1026
+ result = new_call val[0], :"===", argl(val[2])
1027
+ }
1028
+ | arg tNEQ arg
1029
+ {
1030
+ result = new_call val[0], :"!=", argl(val[2])
1031
+ }
1032
+ | arg tMATCH arg
1033
+ {
1034
+ lhs, _, rhs = val
1035
+ result = new_match lhs, rhs
1036
+ }
1037
+ | arg tNMATCH arg
1038
+ {
1039
+ lhs, _, rhs = val
1040
+ result = s(:not, new_match(lhs, rhs)).line lhs.line
1041
+ }
1042
+ | tBANG arg
1043
+ {
1044
+ _, arg = val
1045
+ result = new_call arg, :"!"
1046
+ result.line arg.line
1047
+ }
1048
+ | tTILDE arg
1049
+ {
1050
+ result = new_call value_expr(val[1]), :"~"
1051
+ }
1052
+ | arg tLSHFT arg
1053
+ {
1054
+ val[0] = value_expr val[0]
1055
+ val[2] = value_expr val[2]
1056
+ result = new_call val[0], :"\<\<", argl(val[2])
1057
+ }
1058
+ | arg tRSHFT arg
1059
+ {
1060
+ val[0] = value_expr val[0]
1061
+ val[2] = value_expr val[2]
1062
+ result = new_call val[0], :">>", argl(val[2])
1063
+ }
1064
+ | arg tANDOP arg
1065
+ {
1066
+ result = logical_op :and, val[0], val[2]
1067
+ }
1068
+ | arg tOROP arg
1069
+ {
1070
+ result = logical_op :or, val[0], val[2]
1071
+ }
1072
+ | kDEFINED opt_nl arg
1073
+ {
1074
+ (_, line), _, arg = val
1075
+ result = s(:defined, arg).line line
1076
+ }
1077
+ | arg tEH arg opt_nl tCOLON arg
1078
+ {
1079
+ c, _, t, _, _, f = val
1080
+ result = s(:if, c, t, f).line c.line
1081
+ }
1082
+ | defn_head f_opt_paren_args tEQL arg
1083
+ {
1084
+ result = new_endless_defn val
1085
+ }
1086
+ | defn_head f_opt_paren_args tEQL arg kRESCUE_MOD arg
1087
+ {
1088
+ result = new_endless_defn val
1089
+ }
1090
+ | defs_head f_opt_paren_args tEQL arg
1091
+ {
1092
+ result = new_endless_defs val
1093
+ }
1094
+ | defs_head f_opt_paren_args tEQL arg kRESCUE_MOD arg
1095
+ {
1096
+ result = new_endless_defs val
1097
+ }
1098
+ | primary
1099
+
1100
+ relop: tGT
1101
+ | tLT
1102
+ | tGEQ
1103
+ | tLEQ
1104
+
1105
+ rel_expr: arg relop arg =tGT
1106
+ {
1107
+ lhs, (op, _), rhs = val
1108
+ result = new_call lhs, op.to_sym, argl(rhs)
1109
+ }
1110
+ | rel_expr relop arg =tGT
1111
+ {
1112
+ lhs, (op, _), rhs = val
1113
+ warn "comparison '%s' after comparison", op
1114
+ result = new_call lhs, op.to_sym, argl(rhs)
1115
+ }
1116
+
1117
+ arg_value: arg
1118
+ {
1119
+ result = value_expr(val[0])
1120
+ }
1121
+
1122
+ aref_args: none
1123
+ | args trailer
1124
+ {
1125
+ result = args [val[0]]
1126
+ }
1127
+ | args tCOMMA assocs trailer
1128
+ {
1129
+ result = args [val[0], array_to_hash(val[2])]
1130
+ }
1131
+ | assocs trailer
1132
+ {
1133
+ result = args [array_to_hash(val[0])]
1134
+ }
1135
+
1136
+ arg_rhs: arg =tOP_ASGN
1137
+ | arg kRESCUE_MOD arg
1138
+ {
1139
+ body, (_, line), resbody = val
1140
+ body = value_expr body
1141
+ resbody = remove_begin resbody
1142
+
1143
+ ary = s(:array).line line
1144
+ result = new_rescue(body, new_resbody(ary, resbody))
1145
+ }
1146
+
1147
+ paren_args: tLPAREN2 opt_call_args rparen
1148
+ {
1149
+ _, args, _ = val
1150
+ result = args
1151
+ }
1152
+ | tLPAREN2 args tCOMMA args_forward rparen
1153
+ {
1154
+ yyerror "Unexpected ..." unless
1155
+ self.lexer.is_local_id(:"*") &&
1156
+ self.lexer.is_local_id(:"**") &&
1157
+ self.lexer.is_local_id(:"&")
1158
+
1159
+ result = call_args val
1160
+ }
1161
+ | tLPAREN2 args_forward rparen
1162
+ {
1163
+ yyerror "Unexpected ..." unless
1164
+ self.lexer.is_local_id(:"*") &&
1165
+ self.lexer.is_local_id(:"**") &&
1166
+ self.lexer.is_local_id(:"&")
1167
+
1168
+ result = call_args val
1169
+ }
1170
+
1171
+ opt_paren_args: none
1172
+ | paren_args
1173
+
1174
+ opt_call_args: none
1175
+ | call_args
1176
+ | args tCOMMA
1177
+ {
1178
+ result = args val
1179
+ }
1180
+ | args tCOMMA assocs tCOMMA
1181
+ {
1182
+ result = args [val[0], array_to_hash(val[2])]
1183
+ }
1184
+ | assocs tCOMMA
1185
+ {
1186
+ result = args [array_to_hash(val[0])]
1187
+ }
1188
+
1189
+ call_args: command
1190
+ {
1191
+ warning "parenthesize argument(s) for future version"
1192
+ result = call_args val
1193
+ }
1194
+ | args opt_block_arg
1195
+ {
1196
+ result = call_args val
1197
+ }
1198
+ | assocs opt_block_arg
1199
+ {
1200
+ result = call_args [array_to_hash(val[0]), val[1]]
1201
+ }
1202
+ | args tCOMMA assocs opt_block_arg
1203
+ {
1204
+ result = call_args [val[0], array_to_hash(val[2]), val[3]]
1205
+ }
1206
+ | block_arg
1207
+ {
1208
+ result = call_args val
1209
+ }
1210
+
1211
+ command_args: {
1212
+ # parse26.y line 2200
1213
+
1214
+ # If call_args starts with a open paren '(' or
1215
+ # '[', look-ahead reading of the letters calls
1216
+ # CMDARG_PUSH(0), but the push must be done
1217
+ # after CMDARG_PUSH(1). So this code makes them
1218
+ # consistent by first cancelling the premature
1219
+ # CMDARG_PUSH(0), doing CMDARG_PUSH(1), and
1220
+ # finally redoing CMDARG_PUSH(0).
1221
+
1222
+ result = yychar = self.last_token_type.first
1223
+ lookahead = [:tLPAREN, :tLPAREN_ARG, :tLPAREN2, :tLBRACK, :tLBRACK2].include?(yychar)
1224
+ lexer.cmdarg.pop if lookahead
1225
+ lexer.cmdarg.push true
1226
+ lexer.cmdarg.push false if lookahead
1227
+ }
1228
+ call_args
1229
+ {
1230
+ yychar, args = val
1231
+
1232
+ # call_args can be followed by tLBRACE_ARG (that
1233
+ # does CMDARG_PUSH(0) in the lexer) but the push
1234
+ # must be done after CMDARG_POP() in the parser.
1235
+ # So this code does CMDARG_POP() to pop 0 pushed
1236
+ # by tLBRACE_ARG, CMDARG_POP() to pop 1 pushed
1237
+ # by command_args, and CMDARG_PUSH(0) to restore
1238
+ # back the flag set by tLBRACE_ARG.
1239
+
1240
+ lookahead = [:tLBRACE_ARG].include?(yychar)
1241
+ lexer.cmdarg.pop if lookahead
1242
+ lexer.cmdarg.pop
1243
+ lexer.cmdarg.push false if lookahead
1244
+ result = args
1245
+ }
1246
+
1247
+ block_arg: tAMPER arg_value
1248
+ {
1249
+ _, arg = val
1250
+ result = s(:block_pass, arg).line arg.line
1251
+ }
1252
+ #if V > 30
1253
+ | tAMPER
1254
+ {
1255
+ (_, line), = val
1256
+ result = s(:block_pass).line line
1257
+ }
1258
+ #endif
1259
+
1260
+ opt_block_arg: tCOMMA block_arg
1261
+ {
1262
+ result = val[1]
1263
+ }
1264
+ | none
1265
+
1266
+ args: arg_value
1267
+ {
1268
+ arg, = val
1269
+ lineno = arg.line || lexer.lineno # HACK
1270
+
1271
+ result = s(:array, arg).line lineno
1272
+ }
1273
+ | tSTAR arg_value
1274
+ {
1275
+ _, arg = val
1276
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
1277
+ }
1278
+ | args tCOMMA arg_value
1279
+ {
1280
+ args, _, id = val
1281
+ result = self.list_append args, id
1282
+ }
1283
+ | args tCOMMA tSTAR arg_value
1284
+ {
1285
+ # TODO: the line number from tSTAR has been dropped
1286
+ args, _, _, id = val
1287
+ line = lexer.lineno
1288
+ result = self.list_append args, s(:splat, id).line(line)
1289
+ }
1290
+
1291
+ mrhs_arg: mrhs
1292
+ {
1293
+ result = new_masgn_arg val[0]
1294
+ }
1295
+ | arg_value
1296
+ {
1297
+ result = new_masgn_arg val[0], :wrap
1298
+ }
1299
+
1300
+ mrhs: args tCOMMA arg_value
1301
+ {
1302
+ result = val[0] << val[2]
1303
+ }
1304
+ | args tCOMMA tSTAR arg_value
1305
+ {
1306
+ # TODO: make all tXXXX terminals include lexer.lineno
1307
+ arg, _, _, splat = val
1308
+ result = self.arg_concat arg, splat
1309
+ }
1310
+ | tSTAR arg_value
1311
+ {
1312
+ _, arg = val
1313
+ result = s(:splat, arg).line arg.line
1314
+ }
1315
+
1316
+ primary: literal
1317
+ | strings
1318
+ | xstring
1319
+ | regexp
1320
+ | words
1321
+ | qwords
1322
+ | symbols
1323
+ | qsymbols
1324
+ | var_ref
1325
+ | backref
1326
+ | tFID
1327
+ {
1328
+ (msg, line), = val
1329
+ result = new_call nil, msg.to_sym
1330
+ result.line line
1331
+ }
1332
+ | k_begin
1333
+ {
1334
+ lexer.cmdarg.push false
1335
+ result = self.lexer.lineno
1336
+ }
1337
+ bodystmt k_end
1338
+ {
1339
+ lexer.cmdarg.pop
1340
+ result = new_begin val
1341
+ }
1342
+ | tLPAREN_ARG
1343
+ {
1344
+ lexer.lex_state = EXPR_ENDARG
1345
+ result = lexer.lineno
1346
+ }
1347
+ rparen
1348
+ {
1349
+ _, line, _ = val
1350
+ result = s(:begin).line line
1351
+ }
1352
+ | tLPAREN_ARG
1353
+ stmt
1354
+ {
1355
+ lexer.lex_state = EXPR_ENDARG
1356
+ }
1357
+ rparen
1358
+ {
1359
+ _, stmt, _, _, = val
1360
+ # warning "(...) interpreted as grouped expression"
1361
+ result = stmt
1362
+ }
1363
+ | tLPAREN compstmt tRPAREN
1364
+ {
1365
+ _, stmt, _ = val
1366
+ result = stmt
1367
+ result ||= s(:nil).line lexer.lineno
1368
+ result.paren = true
1369
+ }
1370
+ | primary_value tCOLON2 tCONSTANT
1371
+ {
1372
+ expr, _, (id, _line) = val
1373
+
1374
+ result = s(:colon2, expr, id.to_sym).line expr.line
1375
+ }
1376
+ | tCOLON3 tCONSTANT
1377
+ {
1378
+ result = wrap :colon3, val[1]
1379
+ }
1380
+ | tLBRACK { result = lexer.lineno } aref_args tRBRACK
1381
+ {
1382
+ _, line, args, _ = val
1383
+ result = args || s(:array)
1384
+ result.sexp_type = :array # aref_args is :args
1385
+ result.line line
1386
+ }
1387
+ | tLBRACE
1388
+ {
1389
+ result = self.lexer.lineno
1390
+ }
1391
+ assoc_list tRCURLY
1392
+ {
1393
+ result = new_hash val
1394
+ }
1395
+ | k_return
1396
+ {
1397
+ (_, line), = val
1398
+ result = s(:return).line line
1399
+ }
1400
+ | kYIELD tLPAREN2 call_args rparen
1401
+ {
1402
+ (_, line), _, args, _ = val
1403
+
1404
+ result = new_yield(args).line line
1405
+ }
1406
+ | kYIELD tLPAREN2 rparen
1407
+ {
1408
+ (_, line), _, _ = val
1409
+
1410
+ result = new_yield.line line
1411
+ }
1412
+ | kYIELD
1413
+ {
1414
+ (_, line), = val
1415
+
1416
+ result = new_yield.line line
1417
+ }
1418
+ | kDEFINED opt_nl tLPAREN2 expr rparen
1419
+ {
1420
+ (_, line), _, _, arg, _ = val
1421
+
1422
+ result = s(:defined, arg).line line
1423
+ }
1424
+ | kNOT tLPAREN2 expr rparen
1425
+ {
1426
+ _, _, lhs, _ = val
1427
+ result = new_call lhs, :"!"
1428
+ }
1429
+ | kNOT tLPAREN2 rparen
1430
+ {
1431
+ debug 9
1432
+ }
1433
+ | fcall brace_block
1434
+ {
1435
+ call, iter = val
1436
+
1437
+ iter.insert 1, call
1438
+ result = iter
1439
+ # FIX: probably not: call.line = iter.line
1440
+ }
1441
+ | method_call
1442
+ | method_call brace_block
1443
+ {
1444
+ call, iter = val[0], val[1]
1445
+ block_dup_check call, iter
1446
+ iter.insert 1, call # FIX
1447
+ result = iter
1448
+ }
1449
+ | lambda
1450
+ {
1451
+ expr, = val
1452
+ result = expr
1453
+ }
1454
+ | k_if expr_value then compstmt if_tail k_end
1455
+ {
1456
+ _, c, _, t, f, _ = val
1457
+ result = new_if c, t, f
1458
+ }
1459
+ | k_unless expr_value then compstmt opt_else k_end
1460
+ {
1461
+ _, c, _, t, f, _ = val
1462
+ result = new_if c, f, t
1463
+ }
1464
+ | k_while expr_value_do compstmt k_end
1465
+ {
1466
+ _, cond, body, _ = val
1467
+ result = new_while body, cond, true
1468
+ }
1469
+ | k_until expr_value_do compstmt k_end
1470
+ {
1471
+ _, cond, body, _ = val
1472
+ result = new_until body, cond, true
1473
+ }
1474
+ | k_case expr_value opt_terms case_body k_end
1475
+ {
1476
+ (_, line), expr, _, body, _ = val
1477
+ result = new_case expr, body, line
1478
+ }
1479
+ | k_case opt_terms case_body k_end
1480
+ {
1481
+ (_, line), _, body, _ = val
1482
+ result = new_case nil, body, line
1483
+ }
1484
+ | k_case expr_value opt_terms p_case_body k_end
1485
+ {
1486
+ (_, line), expr, _, body, _ = val
1487
+
1488
+ result = new_case expr, body, line
1489
+ }
1490
+ | k_for for_var kIN expr_value_do compstmt k_end
1491
+ {
1492
+ _, var, _, iter, body, _ = val
1493
+ result = new_for iter, var, body
1494
+ }
1495
+ | k_class
1496
+ {
1497
+ result = self.lexer.lineno
1498
+ }
1499
+ cpath superclass
1500
+ {
1501
+ if (self.in_def || self.in_single > 0) then
1502
+ yyerror "class definition in method body"
1503
+ end
1504
+ self.env.extend
1505
+ }
1506
+ bodystmt k_end
1507
+ {
1508
+ result = new_class val
1509
+ self.env.unextend
1510
+ self.lexer.ignore_body_comments
1511
+ }
1512
+ | k_class tLSHFT
1513
+ {
1514
+ result = self.lexer.lineno
1515
+ }
1516
+ expr
1517
+ {
1518
+ result = self.in_def
1519
+ self.in_def = false
1520
+ }
1521
+ term
1522
+ {
1523
+ result = self.in_single
1524
+ self.in_single = 0
1525
+ self.env.extend
1526
+ }
1527
+ bodystmt k_end
1528
+ {
1529
+ result = new_sclass val
1530
+ self.env.unextend
1531
+ self.lexer.ignore_body_comments
1532
+ }
1533
+ | k_module
1534
+ {
1535
+ result = self.lexer.lineno
1536
+ }
1537
+ cpath
1538
+ {
1539
+ yyerror "module definition in method body" if
1540
+ self.in_def or self.in_single > 0
1541
+
1542
+ self.env.extend
1543
+ }
1544
+ bodystmt k_end
1545
+ {
1546
+ result = new_module val
1547
+ self.env.unextend
1548
+ self.lexer.ignore_body_comments
1549
+ }
1550
+ | defn_head f_arglist bodystmt k_end
1551
+ {
1552
+ # [ [:f, 1, false], s(:args)...]
1553
+ # =>
1554
+ # [[:k_def, 666], [:f, 1], false, s(:args)...]
1555
+ val.insert 1, val.first.pop
1556
+ val.insert 0, [:k_def, 666]
1557
+
1558
+ result, in_def = new_defn val
1559
+
1560
+ lexer.cond.pop # group = local_pop
1561
+ lexer.cmdarg.pop
1562
+ self.env.unextend
1563
+ self.in_def = in_def
1564
+
1565
+ self.lexer.ignore_body_comments
1566
+ }
1567
+ | defs_head f_arglist bodystmt k_end
1568
+ {
1569
+ # [ [recv, [:name, 1, false]], s(:args...]
1570
+ # =>
1571
+ # [ recv, [:name, 1, false], s(:args...]
1572
+ # =>
1573
+ # [ recv, [:name, 1], false, s(:args...]
1574
+ # =>
1575
+ # [ :k_def, recv, [:name, 1], false, s(:args...]
1576
+
1577
+ val.prepend(*val.shift)
1578
+ val.insert 2, val[1].pop
1579
+ val.insert 0, [:k_def, 666]
1580
+
1581
+ result, in_def = new_defs val
1582
+
1583
+ lexer.cond.pop # group = local_pop
1584
+ lexer.cmdarg.pop
1585
+ self.env.unextend
1586
+ self.in_def = in_def
1587
+
1588
+ self.in_single -= 1
1589
+
1590
+ # TODO: restore cur_arg ? what's cur_arg?
1591
+
1592
+ self.lexer.ignore_body_comments
1593
+ }
1594
+ | kBREAK
1595
+ {
1596
+ (_, line), = val
1597
+ result = s(:break).line line
1598
+ }
1599
+ | kNEXT
1600
+ {
1601
+ (_, line), = val
1602
+ result = s(:next).line line
1603
+ }
1604
+ | kREDO
1605
+ {
1606
+ (_, line), = val
1607
+ result = s(:redo).line line
1608
+ }
1609
+ | kRETRY
1610
+ {
1611
+ (_, line), = val
1612
+ result = s(:retry).line line
1613
+ }
1614
+
1615
+ primary_value: primary
1616
+ {
1617
+ result = value_expr(val[0])
1618
+ }
1619
+
1620
+ # These are really stupid
1621
+ k_begin: kBEGIN
1622
+ k_if: kIF
1623
+ k_unless: kUNLESS
1624
+ k_while: kWHILE
1625
+ k_until: kUNTIL
1626
+ k_case: kCASE
1627
+ k_for: kFOR
1628
+ k_class: kCLASS
1629
+ {
1630
+ self.comments.push self.lexer.comments
1631
+ }
1632
+ k_module: kMODULE
1633
+ {
1634
+ self.comments.push self.lexer.comments
1635
+ }
1636
+ k_def: kDEF
1637
+ {
1638
+ self.comments.push self.lexer.comments
1639
+ }
1640
+ k_do: kDO
1641
+ k_do_block: kDO_BLOCK
1642
+ k_rescue: kRESCUE
1643
+ k_ensure: kENSURE
1644
+ k_when: kWHEN
1645
+ k_else: kELSE
1646
+ k_elsif: kELSIF
1647
+ k_end: kEND
1648
+ k_return: kRETURN
1649
+
1650
+ then: term
1651
+ | kTHEN
1652
+ | term kTHEN
1653
+
1654
+ do: term
1655
+ | kDO_COND
1656
+
1657
+ if_tail: opt_else
1658
+ | k_elsif expr_value then compstmt if_tail
1659
+ {
1660
+ (_, line), c, _, t, rest = val
1661
+
1662
+ result = s(:if, c, t, rest).line line
1663
+ }
1664
+
1665
+ opt_else: none
1666
+ | kELSE compstmt
1667
+ {
1668
+ result = val[1]
1669
+ }
1670
+
1671
+ for_var: lhs
1672
+ | mlhs
1673
+ {
1674
+ val[0].delete_at 1 if val[0][1].nil? # HACK
1675
+ }
1676
+
1677
+ f_marg: f_norm_arg
1678
+ | tLPAREN f_margs rparen
1679
+ {
1680
+ result = val[1]
1681
+ }
1682
+
1683
+ f_marg_list: f_marg
1684
+ {
1685
+ sym, = val
1686
+
1687
+ result = s(:array, sym).line lexer.lineno
1688
+ }
1689
+ | f_marg_list tCOMMA f_marg
1690
+ {
1691
+ result = list_append val[0], val[2]
1692
+ }
1693
+
1694
+ f_margs: f_marg_list
1695
+ {
1696
+ args, = val
1697
+
1698
+ result = block_var args
1699
+ }
1700
+ | f_marg_list tCOMMA f_rest_marg
1701
+ {
1702
+ args, _, rest = val
1703
+
1704
+ result = block_var args, rest
1705
+ }
1706
+ | f_marg_list tCOMMA f_rest_marg tCOMMA f_marg_list
1707
+ {
1708
+ lhs, _, splat, _, rhs = val
1709
+
1710
+ result = block_var lhs, splat, rhs
1711
+ }
1712
+ | f_rest_marg
1713
+ {
1714
+ rest, = val
1715
+
1716
+ result = block_var rest
1717
+ }
1718
+ | f_rest_marg tCOMMA f_marg_list
1719
+ {
1720
+ splat, _, rest = val
1721
+
1722
+ result = block_var splat, rest
1723
+ }
1724
+
1725
+ f_rest_marg: tSTAR f_norm_arg
1726
+ {
1727
+ _, (id, line) = val
1728
+
1729
+ result = args ["*#{id}".to_sym]
1730
+ result.line line
1731
+ }
1732
+ | tSTAR
1733
+ {
1734
+ result = args [:*]
1735
+ result.line lexer.lineno # FIX: tSTAR -> line
1736
+ }
1737
+
1738
+ f_any_kwrest: f_kwrest
1739
+ | f_no_kwarg
1740
+
1741
+ #if V > 30
1742
+ f_eq: tEQL # TODO: self.in_argdef = false
1743
+ #endif
1744
+
1745
+ block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
1746
+ {
1747
+ result = call_args val
1748
+ }
1749
+ | f_block_kwarg opt_f_block_arg
1750
+ {
1751
+ result = call_args val
1752
+ }
1753
+ | f_any_kwrest opt_f_block_arg
1754
+ {
1755
+ result = call_args val
1756
+ }
1757
+ | f_block_arg
1758
+ {
1759
+ (id, line), = val
1760
+ result = call_args [id]
1761
+ result.line line
1762
+ }
1763
+
1764
+ opt_block_args_tail: tCOMMA block_args_tail
1765
+ {
1766
+ result = args val
1767
+ }
1768
+ | none
1769
+
1770
+ excessed_comma: tCOMMA
1771
+ {
1772
+ result = s(:WTF_COMMA!)
1773
+ }
1774
+
1775
+ block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1776
+ {
1777
+ result = args val
1778
+ }
1779
+ | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1780
+ {
1781
+ result = args val
1782
+ }
1783
+ | f_arg tCOMMA f_block_optarg opt_block_args_tail
1784
+ {
1785
+ result = args val
1786
+ }
1787
+ | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_block_args_tail
1788
+ {
1789
+ result = args val
1790
+ }
1791
+ | f_arg tCOMMA f_rest_arg opt_block_args_tail
1792
+ {
1793
+ result = args val
1794
+ }
1795
+ | f_arg excessed_comma
1796
+ {
1797
+ arg, _ = val
1798
+ result = arg << nil
1799
+ }
1800
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1801
+ {
1802
+ result = args val
1803
+ }
1804
+ | f_arg opt_block_args_tail
1805
+ {
1806
+ result = args val
1807
+ }
1808
+ | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
1809
+ {
1810
+ result = args val
1811
+ }
1812
+ | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
1813
+ {
1814
+ result = args val
1815
+ }
1816
+ | f_block_optarg opt_block_args_tail
1817
+ {
1818
+ result = args val
1819
+ }
1820
+ | f_block_optarg tCOMMA f_arg opt_block_args_tail
1821
+ {
1822
+ result = args val
1823
+ }
1824
+ | f_rest_arg opt_block_args_tail
1825
+ {
1826
+ result = args val
1827
+ }
1828
+ | f_rest_arg tCOMMA f_arg opt_block_args_tail
1829
+ {
1830
+ result = args val
1831
+ }
1832
+ | block_args_tail
1833
+ {
1834
+ result = args val
1835
+ }
1836
+
1837
+ opt_block_param: none { result = 0 }
1838
+ | block_param_def
1839
+ {
1840
+ self.lexer.command_start = true
1841
+ }
1842
+
1843
+ block_param_def: tPIPE opt_bv_decl tPIPE
1844
+ {
1845
+ # TODO: current_arg = 0
1846
+ result = args val
1847
+ }
1848
+ | tOROP
1849
+ {
1850
+ result = s(:args).line lexer.lineno
1851
+ }
1852
+ | tPIPE block_param opt_bv_decl tPIPE
1853
+ {
1854
+ # TODO: current_arg = 0
1855
+ result = args val
1856
+ }
1857
+
1858
+ opt_bv_decl: opt_nl
1859
+ | opt_nl tSEMI bv_decls opt_nl
1860
+ {
1861
+ result = args val
1862
+ }
1863
+
1864
+ bv_decls: bvar
1865
+ {
1866
+ result = args val
1867
+ }
1868
+ | bv_decls tCOMMA bvar
1869
+ {
1870
+ result = args val
1871
+ }
1872
+
1873
+ bvar: tIDENTIFIER
1874
+ {
1875
+ result = wrap :shadow, val[0]
1876
+ }
1877
+ | f_bad_arg
1878
+
1879
+ lambda: tLAMBDA
1880
+ {
1881
+ self.env.extend :dynamic
1882
+ result = [lexer.lineno, lexer.lpar_beg]
1883
+ lexer.paren_nest += 1
1884
+ lexer.lpar_beg = lexer.paren_nest
1885
+ }
1886
+ f_larglist
1887
+ {
1888
+ lexer.cmdarg.push false
1889
+ }
1890
+ lambda_body
1891
+ {
1892
+ _, (line, lpar), args, _cmdarg, body = val
1893
+ lexer.lpar_beg = lpar
1894
+
1895
+ lexer.cmdarg.pop
1896
+
1897
+ call = s(:lambda).line line
1898
+ result = new_iter call, args, body
1899
+ result.line line
1900
+ self.env.unextend # TODO: dynapush & dynapop
1901
+ }
1902
+
1903
+ f_larglist: tLPAREN2 f_args opt_bv_decl rparen
1904
+ {
1905
+ result = args val
1906
+ }
1907
+ | f_args
1908
+ {
1909
+ result = val[0]
1910
+ result = 0 if result == s(:args)
1911
+ }
1912
+
1913
+ lambda_body: tLAMBEG compstmt tRCURLY
1914
+ {
1915
+ result = val[1]
1916
+ }
1917
+ | kDO_LAMBDA bodystmt kEND
1918
+ {
1919
+ result = val[1]
1920
+ }
1921
+
1922
+ do_block: k_do_block do_body kEND
1923
+ {
1924
+ (_, line), iter, _ = val
1925
+ result = iter.line line
1926
+ }
1927
+
1928
+ block_call: command do_block
1929
+ {
1930
+ # TODO:
1931
+ ## if (nd_type($1) == NODE_YIELD) {
1932
+ ## compile_error(PARSER_ARG "block given to yield");
1933
+
1934
+ cmd, blk = val
1935
+
1936
+ syntax_error "Both block arg and actual block given." if
1937
+ cmd.block_pass?
1938
+
1939
+ if inverted? val then
1940
+ val = invert_block_call val
1941
+ cmd, blk = val
1942
+ end
1943
+
1944
+ result = blk
1945
+ result.insert 1, cmd
1946
+ }
1947
+ | block_call call_op2 operation2 opt_paren_args
1948
+ {
1949
+ lhs, _, (id, _line), args = val
1950
+
1951
+ result = new_call lhs, id.to_sym, args
1952
+ }
1953
+ | block_call call_op2 operation2 opt_paren_args brace_block
1954
+ {
1955
+ iter1, _, (name, _line), args, iter2 = val
1956
+
1957
+ call = new_call iter1, name.to_sym, args
1958
+ iter2.insert 1, call
1959
+
1960
+ result = iter2
1961
+ }
1962
+ | block_call call_op2 operation2 command_args do_block
1963
+ {
1964
+ iter1, _, (name, _line), args, iter2 = val
1965
+
1966
+ call = new_call iter1, name.to_sym, args
1967
+ iter2.insert 1, call
1968
+
1969
+ result = iter2
1970
+ }
1971
+
1972
+ method_call: fcall paren_args
1973
+ {
1974
+ call, args = val
1975
+
1976
+ result = call.concat args.sexp_body if args
1977
+ }
1978
+ | primary_value call_op operation2 opt_paren_args
1979
+ {
1980
+ recv, call_op, (op, _line), args = val
1981
+
1982
+ result = new_call recv, op.to_sym, args, call_op
1983
+ }
1984
+ | primary_value tCOLON2 operation2 paren_args
1985
+ {
1986
+ recv, _, (op, _line), args = val
1987
+
1988
+ result = new_call recv, op.to_sym, args
1989
+ }
1990
+ | primary_value tCOLON2 operation3
1991
+ {
1992
+ lhs, _, (id, _line) = val
1993
+
1994
+ result = new_call lhs, id.to_sym
1995
+ }
1996
+ | primary_value call_op paren_args
1997
+ {
1998
+ result = new_call val[0], :call, val[2], val[1]
1999
+ }
2000
+ | primary_value tCOLON2 paren_args
2001
+ {
2002
+ result = new_call val[0], :call, val[2]
2003
+ }
2004
+ | kSUPER paren_args
2005
+ {
2006
+ result = new_super val[1]
2007
+ }
2008
+ | kSUPER
2009
+ {
2010
+ result = s(:zsuper).line lexer.lineno
2011
+ }
2012
+ | primary_value tLBRACK2 opt_call_args rbracket
2013
+ {
2014
+ result = new_aref val
2015
+ }
2016
+
2017
+ brace_block: tLCURLY
2018
+ {
2019
+ self.env.extend :dynamic
2020
+ result = self.lexer.lineno
2021
+ }
2022
+ brace_body tRCURLY
2023
+ {
2024
+ _, line, body, _ = val
2025
+
2026
+ result = body
2027
+ result.line line
2028
+
2029
+ self.env.unextend
2030
+ }
2031
+ | k_do
2032
+ {
2033
+ self.env.extend :dynamic
2034
+ result = self.lexer.lineno
2035
+ }
2036
+ do_body kEND
2037
+ {
2038
+ _, line, body, _ = val
2039
+
2040
+ result = body
2041
+ result.line line
2042
+
2043
+ self.env.unextend
2044
+ }
2045
+
2046
+ brace_body: { self.env.extend :dynamic; result = self.lexer.lineno }
2047
+ { result = lexer.cmdarg.store(false) }
2048
+ opt_block_param compstmt
2049
+ {
2050
+ line, cmdarg, param, cmpstmt = val
2051
+
2052
+ result = new_brace_body param, cmpstmt, line
2053
+ self.env.unextend
2054
+ lexer.cmdarg.restore cmdarg
2055
+ lexer.cmdarg.pop # because of: cmdarg_stack >> 1 ?
2056
+ }
2057
+
2058
+ do_body: { self.env.extend :dynamic; result = self.lexer.lineno }
2059
+ { lexer.cmdarg.push false }
2060
+ opt_block_param
2061
+ bodystmt
2062
+ {
2063
+ line, _cmdarg, param, cmpstmt = val
2064
+
2065
+ result = new_do_body param, cmpstmt, line
2066
+ lexer.cmdarg.pop
2067
+ self.env.unextend
2068
+ }
2069
+
2070
+ case_args: arg_value
2071
+ {
2072
+ arg, = val
2073
+
2074
+ result = s(:array, arg).line arg.line
2075
+ }
2076
+ | tSTAR arg_value
2077
+ {
2078
+ _, arg = val
2079
+
2080
+ result = s(:array, s(:splat, arg).line(arg.line)).line arg.line
2081
+ }
2082
+ | case_args tCOMMA arg_value
2083
+ {
2084
+ args, _, id = val
2085
+
2086
+ result = self.list_append args, id
2087
+ }
2088
+ | case_args tCOMMA tSTAR arg_value
2089
+ {
2090
+ args, _, _, id = val
2091
+
2092
+ result = self.list_append args, s(:splat, id).line(id.line)
2093
+ }
2094
+
2095
+ case_body: k_when
2096
+ {
2097
+ result = self.lexer.lineno
2098
+ }
2099
+ case_args then compstmt cases
2100
+ {
2101
+ result = new_when(val[2], val[4])
2102
+ result.line val[1]
2103
+ result << val[5] if val[5]
2104
+ }
2105
+
2106
+ cases: opt_else | case_body
2107
+ ######################################################################
2108
+
2109
+ p_case_body: kIN
2110
+ {
2111
+ self.lexer.lex_state = EXPR_BEG|EXPR_LABEL
2112
+ self.lexer.command_start = false
2113
+ result = self.in_kwarg
2114
+ self.in_kwarg = true
2115
+ push_pvtbl
2116
+ push_pktbl
2117
+ }
2118
+ p_top_expr then
2119
+ {
2120
+ pop_pktbl
2121
+ pop_pvtbl
2122
+ old_kwargs = _values[-3]
2123
+ self.in_kwarg = old_kwargs
2124
+ }
2125
+ compstmt
2126
+ p_cases
2127
+ {
2128
+ (_, line), _, pat, _, _, body, cases = val
2129
+
2130
+ result = new_in pat, body, cases, line
2131
+ }
2132
+
2133
+ p_cases: opt_else
2134
+ | p_case_body
2135
+
2136
+ p_top_expr: p_top_expr_body
2137
+ | p_top_expr_body kIF_MOD expr_value
2138
+ {
2139
+ body, _, cond = val
2140
+ body = remove_begin body
2141
+
2142
+ result = s(:if, cond, body, nil).line body.line
2143
+ }
2144
+ | p_top_expr_body kUNLESS_MOD expr_value
2145
+ {
2146
+ body, _, cond = val
2147
+ body = remove_begin body
2148
+
2149
+ result = s(:if, cond, nil, body).line body.line
2150
+ }
2151
+
2152
+ p_top_expr_body: p_expr
2153
+ | p_expr tCOMMA
2154
+ {
2155
+ expr, _ = val
2156
+
2157
+ tail = new_array_pattern_tail nil, true, nil, nil
2158
+ result = new_array_pattern nil, expr, tail, expr.line
2159
+ }
2160
+ | p_expr tCOMMA p_args
2161
+ {
2162
+ expr, _, args = val
2163
+
2164
+ result = new_array_pattern nil, expr, args, expr.line
2165
+ }
2166
+ | p_find
2167
+ {
2168
+ find, = val
2169
+
2170
+ result = new_find_pattern nil, find
2171
+ }
2172
+ | p_args_tail
2173
+ {
2174
+ args, = val
2175
+ result = new_array_pattern nil, nil, args, args.line
2176
+ }
2177
+ | p_kwargs
2178
+ {
2179
+ kwargs, = val
2180
+ result = new_hash_pattern nil, kwargs, kwargs.line
2181
+ }
2182
+
2183
+ p_expr: p_as
2184
+
2185
+ p_as: p_expr tASSOC p_variable
2186
+ {
2187
+ # NODE *n = NEW_LIST($1, &@$);
2188
+ # n = list_append(p, n, $3);
2189
+ # $$ = new_hash(p, n, &@$);
2190
+
2191
+ expr, _, var = val
2192
+
2193
+ id = var.last
2194
+
2195
+ self.env[id] = :lvar # HACK: need to extend env
2196
+ lhs = s(:lasgn, id).line var.line
2197
+
2198
+ result = new_assign lhs, expr
2199
+ }
2200
+ | p_alt
2201
+
2202
+ p_alt: p_alt tPIPE p_expr_basic
2203
+ {
2204
+ lhs, _, rhs = val
2205
+
2206
+ result = s(:or, lhs, rhs).line lhs.line
2207
+ }
2208
+ | p_expr_basic
2209
+
2210
+ p_lparen: tLPAREN2 { push_pktbl }
2211
+ p_lbracket: tLBRACK2 { push_pktbl }
2212
+
2213
+ p_expr_basic: p_value
2214
+ #if V > 30
2215
+ | p_variable
2216
+ #endif
2217
+ | p_const p_lparen p_args tRPAREN
2218
+ {
2219
+ lhs, _, args, _ = val
2220
+
2221
+ pop_pktbl
2222
+ result = new_array_pattern(lhs, nil, args, lhs.line)
2223
+ }
2224
+ | p_const p_lparen p_find tRPAREN
2225
+ {
2226
+ const, _, find, _ = val
2227
+
2228
+ pop_pktbl
2229
+ result = new_find_pattern(const, find).line const.line
2230
+ }
2231
+ | p_const p_lparen p_kwargs tRPAREN
2232
+ {
2233
+ lhs, _, kwargs, _ = val
2234
+
2235
+ pop_pktbl
2236
+ result = new_hash_pattern(lhs, kwargs, lhs.line)
2237
+ }
2238
+ | p_const tLPAREN2 tRPAREN
2239
+ {
2240
+ const, _, _ = val
2241
+
2242
+ tail = new_array_pattern_tail nil, nil, nil, nil
2243
+ result = new_array_pattern const, nil, tail, const.line
2244
+ }
2245
+ | p_const p_lbracket p_args rbracket
2246
+ {
2247
+ const, _, pre_arg, _ = val
2248
+
2249
+ pop_pktbl
2250
+ result = new_array_pattern const, nil, pre_arg, const.line
2251
+ }
2252
+ | p_const p_lbracket p_find rbracket
2253
+ {
2254
+ const, _, find, _ = val
2255
+
2256
+ pop_pktbl
2257
+ result = new_find_pattern(const, find).line const.line
2258
+ }
2259
+ | p_const p_lbracket p_kwargs rbracket
2260
+ {
2261
+ const, _, kwargs, _ = val
2262
+
2263
+ result = new_hash_pattern const, kwargs, const.line
2264
+ }
2265
+ | p_const tLBRACK2 rbracket
2266
+ {
2267
+ const, _, _ = val
2268
+
2269
+ tail = new_array_pattern_tail nil, nil, nil, nil
2270
+ result = new_array_pattern const, nil, tail, const.line
2271
+ }
2272
+ | tLBRACK p_args rbracket
2273
+ {
2274
+ _, pat, _ = val
2275
+
2276
+ result = new_array_pattern nil, nil, pat, pat.line
2277
+ }
2278
+ | tLBRACK p_find rbracket
2279
+ {
2280
+ _, find, _ = val
2281
+
2282
+ result = new_find_pattern nil, find
2283
+ }
2284
+ | tLBRACK rbracket
2285
+ {
2286
+ (_, line), _ = val
2287
+
2288
+ result = s(:array_pat).line line
2289
+ }
2290
+ | tLBRACE
2291
+ {
2292
+ push_pktbl
2293
+ result = self.in_kwarg
2294
+ self.in_kwarg = false
2295
+ }
2296
+ p_kwargs rbrace
2297
+ {
2298
+ _, in_kwarg, kwargs, _ = val
2299
+
2300
+ pop_pktbl
2301
+ self.in_kwarg = in_kwarg
2302
+
2303
+ result = new_hash_pattern(nil, kwargs, kwargs.line)
2304
+ }
2305
+ | tLBRACE rbrace
2306
+ {
2307
+ (_, line), _ = val
2308
+
2309
+ tail = new_hash_pattern_tail nil, nil, line
2310
+ result = new_hash_pattern nil, tail, line
2311
+ }
2312
+ | tLPAREN { push_pktbl } p_expr tRPAREN
2313
+ {
2314
+ _, _, expr, _ = val
2315
+
2316
+ pop_pktbl
2317
+ result = expr
2318
+ }
2319
+
2320
+ p_args: p_expr
2321
+ {
2322
+ expr, = val
2323
+
2324
+ ary = s(:array_TAIL, expr).line expr.line
2325
+ result = new_array_pattern_tail(ary, nil, nil, nil).line expr.line
2326
+ }
2327
+ | p_args_head
2328
+ {
2329
+ head, = val
2330
+
2331
+ result = new_array_pattern_tail head, true, nil, nil
2332
+ }
2333
+ | p_args_head p_arg
2334
+ {
2335
+ head, tail = val
2336
+
2337
+ both = array_pat_concat head, tail
2338
+
2339
+ result = new_array_pattern_tail both, nil, nil, nil
2340
+ result.line head.line
2341
+ }
2342
+ | p_args_head tSTAR tIDENTIFIER
2343
+ {
2344
+ head, _, (id, _line) = val
2345
+
2346
+ result = new_array_pattern_tail head, true, id.to_sym, nil
2347
+ result.line head.line
2348
+ }
2349
+ | p_args_head tSTAR tIDENTIFIER tCOMMA p_args_post
2350
+ {
2351
+ head, _, (id, _line), _, post = val
2352
+
2353
+ result = new_array_pattern_tail head, true, id.to_sym, post
2354
+ result.line head.line
2355
+ }
2356
+ | p_args_head tSTAR
2357
+ {
2358
+ expr, _ = val
2359
+
2360
+ result = new_array_pattern_tail(expr, true, nil, nil).line expr.line
2361
+ }
2362
+ | p_args_head tSTAR tCOMMA p_args_post
2363
+ {
2364
+ head, _, _, post = val
2365
+
2366
+ result = new_array_pattern_tail(head, true, nil, post).line head.line
2367
+ }
2368
+ | p_args_tail
2369
+
2370
+ p_args_head: p_arg tCOMMA
2371
+ {
2372
+ arg, _ = val
2373
+ result = arg
2374
+ }
2375
+ | p_args_head p_arg tCOMMA
2376
+ {
2377
+ head, tail, _ = val
2378
+
2379
+ result = s(:PATTERN, *head.sexp_body, *tail.sexp_body)
2380
+ result.line head.line
2381
+ }
2382
+
2383
+ p_args_tail: p_rest
2384
+ {
2385
+ (id, line), = val
2386
+
2387
+ result = new_array_pattern_tail nil, true, id, nil
2388
+ result.line line
2389
+ }
2390
+ | p_rest tCOMMA p_args_post
2391
+ {
2392
+ (id, line), _, rhs = val
2393
+
2394
+ result = new_array_pattern_tail nil, true, id, rhs
2395
+ result.line line
2396
+ }
2397
+
2398
+ p_find: p_rest tCOMMA p_args_post tCOMMA p_rest
2399
+ {
2400
+ lhs, _, mid, _, rhs = val
2401
+
2402
+ result = new_find_pattern_tail lhs, mid, rhs
2403
+ }
2404
+
2405
+ p_rest: tSTAR tIDENTIFIER
2406
+ {
2407
+ _, (id, line) = val
2408
+
2409
+ result = [id.to_sym, line]
2410
+ }
2411
+ | tSTAR
2412
+ {
2413
+ (_id, line), = val
2414
+
2415
+ result = [nil, line]
2416
+ }
2417
+
2418
+ p_args_post: p_arg
2419
+ | p_args_post tCOMMA p_arg
2420
+ {
2421
+ lhs, _, rhs = val
2422
+
2423
+ result = array_pat_concat lhs, rhs
2424
+ }
2425
+
2426
+ p_arg: p_expr
2427
+ {
2428
+ expr, = val
2429
+ expr = s(:array_TAIL, expr).line expr.line unless
2430
+ expr.sexp_type == :array_TAIL
2431
+ result = expr
2432
+ }
2433
+
2434
+ p_kwargs: p_kwarg tCOMMA p_any_kwrest
2435
+ {
2436
+ kw_arg, _, rest = val
2437
+ # TODO? new_unique_key_hash(p, $1, &@$)
2438
+ result = new_hash_pattern_tail kw_arg, rest, kw_arg.line
2439
+ }
2440
+ | p_kwarg
2441
+ {
2442
+ kwarg, = val
2443
+ # TODO? new_unique_key_hash(p, $1, &@$)
2444
+ result = new_hash_pattern_tail kwarg, nil, kwarg.line
2445
+ }
2446
+ | p_kwarg tCOMMA
2447
+ {
2448
+ kwarg, _ = val
2449
+ # TODO? new_unique_key_hash(p, $1, &@$)
2450
+ result = new_hash_pattern_tail kwarg, nil, kwarg.line
2451
+ }
2452
+ | p_any_kwrest
2453
+ {
2454
+ rest, = val
2455
+
2456
+ result = new_hash_pattern_tail nil, rest, rest.line
2457
+ }
2458
+
2459
+ p_kwarg: p_kw # TODO? rb_ary_new_from_args(1, $1)
2460
+ | p_kwarg tCOMMA p_kw
2461
+ {
2462
+ kwarg, _, kw = val
2463
+ kwarg.concat kw.sexp_body
2464
+ result = kwarg
2465
+ }
2466
+
2467
+ p_kw: p_kw_label p_expr
2468
+ {
2469
+ # TODO: error_duplicate_pattern_key(p, get_id($1), &@1);
2470
+ lhs, rhs = val
2471
+
2472
+ result = s(:PAIR, lhs, rhs).line lhs.line
2473
+ }
2474
+ | p_kw_label
2475
+ {
2476
+ lhs, = val
2477
+
2478
+ # TODO: error_duplicate_pattern_variable(p, get_id($1), &@1);
2479
+
2480
+ # TODO: if ($1 && !is_local_id(get_id($1))) {
2481
+ # yyerror1(&@1, "key must be valid as local variables");
2482
+ # }
2483
+
2484
+ # $$ = list_append(p, NEW_LIST(NEW_LIT(ID2SYM($1), &@$), &@$),
2485
+ # assignable(p, $1, 0, &@$));
2486
+
2487
+ case lhs.sexp_type
2488
+ when :lit then
2489
+ assignable [lhs.value, lhs.line]
2490
+ else
2491
+ # TODO or done?
2492
+ debug 10
2493
+ end
2494
+
2495
+ # TODO PAIR -> LIST ?
2496
+ result = s(:PAIR, lhs, nil).line lhs.line
2497
+ }
2498
+
2499
+ p_kw_label: tLABEL
2500
+ {
2501
+ result = wrap :lit, val[0]
2502
+ }
2503
+ #if V > 30
2504
+ | tSTRING_BEG string_contents tLABEL_END
2505
+ {
2506
+ # you can't actually get here the way I lex labels
2507
+ debug 11
2508
+ }
2509
+ #endif
2510
+
2511
+ p_kwrest: kwrest_mark tIDENTIFIER
2512
+ {
2513
+ _, (id, line) = val
2514
+
2515
+ name = id.to_sym
2516
+ self.assignable [name, line]
2517
+ result = s(:kwrest, :"**#{name}").line line
2518
+ }
2519
+ | kwrest_mark
2520
+ {
2521
+ (_, line), = val
2522
+
2523
+ result = s(:kwrest, :"**").line line
2524
+ }
2525
+
2526
+ p_kwnorest: kwrest_mark kNIL
2527
+ {
2528
+ (_, line), _ = val
2529
+
2530
+ # TODO: or s(:norest)? s(:**nil)?
2531
+ result = s(:kwrest, :"**nil").line line
2532
+ }
2533
+
2534
+ p_any_kwrest: p_kwrest
2535
+ | p_kwnorest
2536
+
2537
+ p_value: p_primitive
2538
+ | p_primitive tDOT2 p_primitive
2539
+ {
2540
+ lhs, _, rhs = val
2541
+
2542
+ lhs = value_expr lhs
2543
+ rhs = value_expr rhs
2544
+
2545
+ result = s(:dot2, lhs, rhs).line lhs.line
2546
+ }
2547
+ | p_primitive tDOT3 p_primitive
2548
+ {
2549
+ lhs, _, rhs = val
2550
+
2551
+ lhs = value_expr lhs
2552
+ rhs = value_expr rhs
2553
+
2554
+ result = s(:dot3, lhs, rhs).line lhs.line
2555
+ }
2556
+ | p_primitive tDOT2
2557
+ {
2558
+ v1, _ = val
2559
+
2560
+ result = s(:dot2, v1, nil).line v1.line
2561
+ }
2562
+ | p_primitive tDOT3
2563
+ {
2564
+ v1, _ = val
2565
+
2566
+ result = s(:dot3, v1, nil).line v1.line
2567
+ }
2568
+ #if V == 30
2569
+ | p_variable
2570
+ #endif
2571
+ | p_var_ref
2572
+ #if V > 30
2573
+ | p_expr_ref
2574
+ #endif
2575
+ | p_const
2576
+ | tBDOT2 p_primitive
2577
+ {
2578
+ _, v1 = val
2579
+
2580
+ result = s(:dot2, nil, v1).line v1.line
2581
+ }
2582
+ | tBDOT3 p_primitive
2583
+ {
2584
+ _, v1 = val
2585
+
2586
+ result = s(:dot3, nil, v1).line v1.line
2587
+ }
2588
+
2589
+ p_primitive: literal
2590
+ | strings
2591
+ | xstring
2592
+ | regexp
2593
+ | words
2594
+ | qwords
2595
+ | symbols
2596
+ | qsymbols
2597
+ | keyword_variable
2598
+ {
2599
+ # TODO? if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$);
2600
+ var, = val
2601
+
2602
+ result = var
2603
+ }
2604
+ | lambda
2605
+
2606
+ p_variable: tIDENTIFIER
2607
+ {
2608
+ # TODO: error_duplicate_pattern_variable(p, $1, &@1);
2609
+ # TODO: assignable(p, $1, 0, &@$);
2610
+ result = wrap :lvar, val[0]
2611
+ }
2612
+
2613
+ p_var_ref: tCARET tIDENTIFIER
2614
+ {
2615
+ # TODO: check id against env for lvar or dvar
2616
+ result = wrap :lvar, val[1]
2617
+ }
2618
+ #if V > 30
2619
+ | tCARET nonlocal_var
2620
+ {
2621
+ _, var = val
2622
+ result = var
2623
+ }
2624
+ #endif
2625
+
2626
+ #if V > 30
2627
+ p_expr_ref: tCARET tLPAREN expr_value rparen
2628
+ {
2629
+ _, _, expr, _ = val
2630
+ result = expr # TODO? s(:begin, expr).line expr.line
2631
+ }
2632
+ #endif
2633
+
2634
+ p_const: tCOLON3 cname
2635
+ {
2636
+ result = wrap :colon3, val[1]
2637
+ }
2638
+ | p_const tCOLON2 cname
2639
+ {
2640
+ lhs, _, (id, _line) = val
2641
+
2642
+ l = lhs.line
2643
+ result = s(:const, s(:colon2, lhs, id.to_sym).line(l)).line l
2644
+ }
2645
+ | tCONSTANT
2646
+ {
2647
+ # TODO $$ = gettable(p, $1, &@$);
2648
+ result = wrap :const, val[0]
2649
+ }
2650
+ ######################################################################
2651
+
2652
+ opt_rescue: k_rescue exc_list exc_var then compstmt opt_rescue
2653
+ {
2654
+ (_, line), klasses, var, _, body, rest = val
2655
+
2656
+ klasses ||= s(:array)
2657
+ klasses << new_assign(var, s(:gvar, :"$!").line(var.line)) if var
2658
+ klasses.line line
2659
+
2660
+ result = new_resbody(klasses, body)
2661
+ result << rest if rest # UGH, rewritten above
2662
+ }
2663
+ |
2664
+ {
2665
+ result = nil
2666
+ }
2667
+
2668
+ exc_list: arg_value
2669
+ {
2670
+ arg, = val
2671
+ result = s(:array, arg).line arg.line
2672
+ }
2673
+ | mrhs
2674
+ | none
2675
+
2676
+ exc_var: tASSOC lhs
2677
+ {
2678
+ result = val[1]
2679
+ }
2680
+ | none
2681
+
2682
+ opt_ensure: k_ensure compstmt
2683
+ {
2684
+ (_, line), body = val
2685
+
2686
+ result = body || s(:nil).line(line)
2687
+ }
2688
+ | none
2689
+
2690
+ literal: numeric
2691
+ {
2692
+ (lit, line), = val
2693
+ result = s(:lit, lit).line line
2694
+ }
2695
+ | symbol
2696
+
2697
+ strings: string
2698
+ {
2699
+ str, = val
2700
+ str = s(:dstr, str.value) if str.sexp_type == :evstr
2701
+ result = str
2702
+ }
2703
+
2704
+ string: tCHAR
2705
+ {
2706
+ debug 12
2707
+ }
2708
+ | string1
2709
+ | string string1
2710
+ {
2711
+ result = self.literal_concat val[0], val[1]
2712
+ }
2713
+
2714
+ string1: tSTRING_BEG string_contents tSTRING_END
2715
+ {
2716
+ (_, line), str, (_, func) = val
2717
+
2718
+ str = dedent str if func =~ RubyLexer::STR_FUNC_DEDENT
2719
+
2720
+ result = str.line line
2721
+ }
2722
+ | tSTRING
2723
+ {
2724
+ result = new_string val
2725
+ }
2726
+
2727
+ xstring: tXSTRING_BEG xstring_contents tSTRING_END
2728
+ {
2729
+ result = new_xstring val
2730
+ # TODO: dedent?!?! SERIOUSLY?!?
2731
+ }
2732
+
2733
+ regexp: tREGEXP_BEG regexp_contents tREGEXP_END
2734
+ {
2735
+ result = new_regexp val
2736
+ }
2737
+
2738
+ words: tWORDS_BEG tSPACE tSTRING_END
2739
+ {
2740
+ (_, line), _, _ = val
2741
+
2742
+ result = s(:array).line line
2743
+ }
2744
+ | tWORDS_BEG word_list tSTRING_END
2745
+ {
2746
+ (_, line), list, _ = val
2747
+
2748
+ result = list.line line
2749
+ }
2750
+
2751
+ word_list: none
2752
+ {
2753
+ result = new_word_list
2754
+ }
2755
+ | word_list word tSPACE
2756
+ {
2757
+ result = val[0].dup << new_word_list_entry(val)
2758
+ }
2759
+
2760
+ word: string_content
2761
+ | word string_content
2762
+ {
2763
+ result = self.literal_concat val[0], val[1]
2764
+ }
2765
+
2766
+ symbols: tSYMBOLS_BEG tSPACE tSTRING_END
2767
+ {
2768
+ (_, line), _, _ = val
2769
+
2770
+ result = s(:array).line line
2771
+ }
2772
+ | tSYMBOLS_BEG symbol_list tSTRING_END
2773
+ {
2774
+ (_, line), list, _, = val
2775
+ list.line line
2776
+ result = list
2777
+ }
2778
+
2779
+ symbol_list: none
2780
+ {
2781
+ result = new_symbol_list
2782
+ }
2783
+ | symbol_list word tSPACE
2784
+ {
2785
+ list, * = val
2786
+ result = list.dup << new_symbol_list_entry(val)
2787
+ }
2788
+
2789
+ qwords: tQWORDS_BEG tSPACE tSTRING_END
2790
+ {
2791
+ (_, line), _, _ = val
2792
+
2793
+ result = s(:array).line line
2794
+ }
2795
+ | tQWORDS_BEG qword_list tSTRING_END
2796
+ {
2797
+ (_, line), list, _ = val
2798
+
2799
+ result = list.line line
2800
+ }
2801
+
2802
+ qsymbols: tQSYMBOLS_BEG tSPACE tSTRING_END
2803
+ {
2804
+ (_, line), _, _ = val
2805
+
2806
+ result = s(:array).line line
2807
+ }
2808
+ | tQSYMBOLS_BEG qsym_list tSTRING_END
2809
+ {
2810
+ (_, line), list, _ = val
2811
+
2812
+ result = list.line line
2813
+ }
2814
+
2815
+ qword_list: none
2816
+ {
2817
+ result = new_qword_list
2818
+ }
2819
+ | qword_list tSTRING_CONTENT tSPACE
2820
+ {
2821
+ result = val[0].dup << new_qword_list_entry(val)
2822
+ }
2823
+
2824
+ qsym_list: none
2825
+ {
2826
+ result = new_qsym_list
2827
+ }
2828
+ | qsym_list tSTRING_CONTENT tSPACE
2829
+ {
2830
+ result = val[0].dup << new_qsym_list_entry(val)
2831
+ }
2832
+
2833
+ string_contents: none
2834
+ {
2835
+ line = prev_value_to_lineno _values.last
2836
+ result = s(:str, +"").line line
2837
+ }
2838
+ | string_contents string_content
2839
+ {
2840
+ v1, v2 = val
2841
+ result = literal_concat v1, v2
2842
+ }
2843
+
2844
+ xstring_contents: none
2845
+ {
2846
+ result = nil
2847
+ }
2848
+ | xstring_contents string_content
2849
+ {
2850
+ v1, v2 = val
2851
+ result = literal_concat v1, v2
2852
+ }
2853
+
2854
+ regexp_contents: none
2855
+ {
2856
+ result = nil
2857
+ }
2858
+ | regexp_contents string_content
2859
+ {
2860
+ v1, v2 = val
2861
+ result = literal_concat v1, v2
2862
+ }
2863
+
2864
+ string_content: tSTRING_CONTENT
2865
+ {
2866
+ result = new_string val
2867
+ }
2868
+ | tSTRING_DVAR
2869
+ {
2870
+ result = lexer.lex_strterm
2871
+
2872
+ lexer.lex_strterm = nil
2873
+ lexer.lex_state = EXPR_BEG
2874
+ }
2875
+ string_dvar
2876
+ {
2877
+ _, strterm, str = val
2878
+ lexer.lex_strterm = strterm
2879
+ result = s(:evstr, str).line str.line
2880
+ }
2881
+ | tSTRING_DBEG
2882
+ {
2883
+ result = [lexer.lex_strterm,
2884
+ lexer.brace_nest,
2885
+ lexer.string_nest, # TODO: remove
2886
+ lexer.lex_state,
2887
+ lexer.lineno,
2888
+ ]
2889
+
2890
+ lexer.cmdarg.push false
2891
+ lexer.cond.push false
2892
+
2893
+ lexer.lex_strterm = nil
2894
+ lexer.brace_nest = 0
2895
+ lexer.string_nest = 0
2896
+
2897
+ lexer.lex_state = EXPR_BEG
2898
+ }
2899
+ compstmt
2900
+ tSTRING_DEND
2901
+ {
2902
+ _, memo, stmt, _ = val
2903
+
2904
+ lex_strterm, brace_nest, string_nest, oldlex_state, line = memo
2905
+ # TODO: heredoc_indent
2906
+
2907
+ lexer.lex_strterm = lex_strterm
2908
+ lexer.brace_nest = brace_nest
2909
+ lexer.string_nest = string_nest
2910
+
2911
+ lexer.cond.pop
2912
+ lexer.cmdarg.pop
2913
+
2914
+ lexer.lex_state = oldlex_state
2915
+
2916
+ case stmt
2917
+ when Sexp then
2918
+ case stmt.sexp_type
2919
+ when :str, :dstr, :evstr then
2920
+ result = stmt
2921
+ else
2922
+ result = s(:evstr, stmt).line line
2923
+ end
2924
+ when nil then
2925
+ result = s(:evstr).line line
2926
+ else
2927
+ debug 13
2928
+ raise "unknown string body: #{stmt.inspect}"
2929
+ end
2930
+ }
2931
+
2932
+ string_dvar: tGVAR
2933
+ {
2934
+ result = wrap :gvar, val[0]
2935
+ }
2936
+ | tIVAR
2937
+ {
2938
+ result = wrap :ivar, val[0]
2939
+ }
2940
+ | tCVAR
2941
+ {
2942
+ result = wrap :cvar, val[0]
2943
+ }
2944
+ | backref
2945
+
2946
+ symbol: ssym
2947
+ | dsym
2948
+
2949
+ ssym: tSYMBEG sym
2950
+ {
2951
+ lexer.lex_state = EXPR_END
2952
+ result = wrap :lit, val[1]
2953
+ }
2954
+ | tSYMBOL
2955
+ {
2956
+ lexer.lex_state = EXPR_END
2957
+ result = wrap :lit, val[0]
2958
+ }
2959
+
2960
+ sym: fname | tIVAR | tGVAR | tCVAR
2961
+
2962
+ dsym: tSYMBEG string_contents tSTRING_END
2963
+ {
2964
+ _, result, _ = val
2965
+
2966
+ lexer.lex_state = EXPR_END
2967
+
2968
+ result ||= s(:str, "").line lexer.lineno
2969
+
2970
+ case result.sexp_type
2971
+ when :dstr then
2972
+ result.sexp_type = :dsym
2973
+ when :str then
2974
+ result = s(:lit, result.last.to_sym).line result.line
2975
+ when :evstr then
2976
+ result = s(:dsym, "", result).line result.line
2977
+ else
2978
+ debug 14
2979
+ end
2980
+ }
2981
+
2982
+ numeric: simple_numeric
2983
+ | tUMINUS_NUM simple_numeric =tLOWEST
2984
+ {
2985
+ _, (num, line) = val
2986
+ result = [-num, line]
2987
+ }
2988
+
2989
+ simple_numeric: tINTEGER
2990
+ | tFLOAT
2991
+ | tRATIONAL
2992
+ | tIMAGINARY
2993
+
2994
+ #if V > 30
2995
+ nonlocal_var: tIVAR { result = wrap :ivar, val[0] }
2996
+ | tGVAR { result = wrap :gvar, val[0] }
2997
+ | tCVAR { result = wrap :cvar, val[0] }
2998
+ #endif
2999
+
3000
+ user_variable: tIDENTIFIER
3001
+ | tIVAR
3002
+ | tGVAR
3003
+ | tCONSTANT
3004
+ | tCVAR
3005
+
3006
+ keyword_variable: kNIL { result = s(:nil).line lexer.lineno }
3007
+ | kSELF { result = s(:self).line lexer.lineno }
3008
+ | kTRUE { result = s(:true).line lexer.lineno }
3009
+ | kFALSE { result = s(:false).line lexer.lineno }
3010
+ | k__FILE__ { result = s(:str, self.file).line lexer.lineno }
3011
+ | k__LINE__ { result = s(:lit, lexer.lineno).line lexer.lineno }
3012
+ | k__ENCODING__
3013
+ {
3014
+ l = lexer.lineno
3015
+ result =
3016
+ if defined? Encoding then
3017
+ s(:colon2, s(:const, :Encoding).line(l), :UTF_8).line l
3018
+ else
3019
+ s(:str, "Unsupported!").line l
3020
+ end
3021
+ }
3022
+
3023
+ var_ref: user_variable
3024
+ {
3025
+ raise "NO: #{val.inspect}" if Sexp === val.first
3026
+ (var, line), = val
3027
+ result = Sexp === var ? var : self.gettable(var)
3028
+
3029
+ result.line line
3030
+ }
3031
+ | keyword_variable
3032
+ {
3033
+ var = val[0]
3034
+ result = Sexp === var ? var : self.gettable(var)
3035
+ }
3036
+
3037
+ var_lhs: user_variable
3038
+ {
3039
+ result = self.assignable val[0]
3040
+ }
3041
+ | keyword_variable
3042
+ {
3043
+ result = self.assignable val[0]
3044
+ debug 15
3045
+ }
3046
+
3047
+ backref: tNTH_REF
3048
+ {
3049
+ (ref, line), = val
3050
+ result = s(:nth_ref, ref).line line
3051
+ }
3052
+ | tBACK_REF
3053
+ {
3054
+ (ref, line), = val
3055
+ result = s(:back_ref, ref).line line
3056
+ }
3057
+
3058
+ superclass: tLT
3059
+ {
3060
+ lexer.lex_state = EXPR_BEG
3061
+ lexer.command_start = true
3062
+ }
3063
+ expr_value term
3064
+ {
3065
+ result = val[2]
3066
+ }
3067
+ | none
3068
+ {
3069
+ result = nil
3070
+ }
3071
+
3072
+ f_opt_paren_args: f_paren_args
3073
+ | none
3074
+ {
3075
+ result = end_args val
3076
+ }
3077
+
3078
+ f_paren_args: tLPAREN2 f_args rparen
3079
+ {
3080
+ result = end_args val
3081
+ }
3082
+ #if V == 30
3083
+ | tLPAREN2 f_arg tCOMMA args_forward rparen
3084
+ {
3085
+ result = end_args val
3086
+ }
3087
+ | tLPAREN2 args_forward rparen
3088
+ {
3089
+ result = end_args val
3090
+ }
3091
+ #endif
3092
+
3093
+ f_arglist: f_paren_args
3094
+ | {
3095
+ result = self.in_kwarg
3096
+ self.in_kwarg = true
3097
+ self.lexer.lex_state |= EXPR_LABEL
3098
+ }
3099
+ f_args term
3100
+ {
3101
+ result = end_args val
3102
+ }
3103
+
3104
+ args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
3105
+ {
3106
+ result = args val
3107
+ }
3108
+ | f_kwarg opt_f_block_arg
3109
+ {
3110
+ result = args val
3111
+ }
3112
+ | f_any_kwrest opt_f_block_arg
3113
+ {
3114
+ result = args val
3115
+ }
3116
+ | f_block_arg
3117
+ #if V > 30
3118
+ | args_forward
3119
+ #endif
3120
+
3121
+ opt_args_tail: tCOMMA args_tail
3122
+ {
3123
+ result = val[1]
3124
+ }
3125
+ |
3126
+ {
3127
+ result = nil
3128
+ }
3129
+
3130
+ f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
3131
+ {
3132
+ result = args val
3133
+ }
3134
+ | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
3135
+ {
3136
+ result = args val
3137
+ }
3138
+ | f_arg tCOMMA f_optarg opt_args_tail
3139
+ {
3140
+ result = args val
3141
+ }
3142
+ | f_arg tCOMMA f_optarg tCOMMA f_arg opt_args_tail
3143
+ {
3144
+ result = args val
3145
+ }
3146
+ | f_arg tCOMMA f_rest_arg opt_args_tail
3147
+ {
3148
+ result = args val
3149
+ }
3150
+ | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
3151
+ {
3152
+ result = args val
3153
+ }
3154
+ | f_arg opt_args_tail
3155
+ {
3156
+ result = args val
3157
+ }
3158
+ | f_optarg tCOMMA f_rest_arg opt_args_tail
3159
+ {
3160
+ result = args val
3161
+ }
3162
+ | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
3163
+ {
3164
+ result = args val
3165
+ }
3166
+ | f_optarg opt_args_tail
3167
+ {
3168
+ result = args val
3169
+ }
3170
+ | f_optarg tCOMMA f_arg opt_args_tail
3171
+ {
3172
+ result = args val
3173
+ }
3174
+ | f_rest_arg opt_args_tail
3175
+ {
3176
+ result = args val
3177
+ }
3178
+ | f_rest_arg tCOMMA f_arg opt_args_tail
3179
+ {
3180
+ result = args val
3181
+ }
3182
+ | args_tail
3183
+ {
3184
+ result = args val
3185
+ }
3186
+ |
3187
+ {
3188
+ result = args val
3189
+ # result.line lexer.lineno
3190
+ }
3191
+
3192
+ args_forward: tBDOT3
3193
+ {
3194
+ result = s(:forward_args).line lexer.lineno
3195
+ }
3196
+
3197
+ f_bad_arg: tCONSTANT
3198
+ {
3199
+ yyerror "formal argument cannot be a constant"
3200
+ }
3201
+ | tIVAR
3202
+ {
3203
+ yyerror "formal argument cannot be an instance variable"
3204
+ }
3205
+ | tGVAR
3206
+ {
3207
+ yyerror "formal argument cannot be a global variable"
3208
+ }
3209
+ | tCVAR
3210
+ {
3211
+ yyerror "formal argument cannot be a class variable"
3212
+ }
3213
+
3214
+ f_norm_arg: f_bad_arg
3215
+ | tIDENTIFIER
3216
+ {
3217
+ (id, line), = val
3218
+ identifier = id.to_sym
3219
+ self.env[identifier] = :lvar
3220
+
3221
+ result = [identifier, line]
3222
+ }
3223
+
3224
+ f_arg_asgn: f_norm_arg
3225
+
3226
+ f_arg_item: f_arg_asgn
3227
+ | tLPAREN f_margs rparen
3228
+ {
3229
+ _, margs, _ = val
3230
+
3231
+ result = margs
3232
+ }
3233
+
3234
+ f_arg: f_arg_item
3235
+ {
3236
+ result = new_arg val
3237
+ }
3238
+ | f_arg tCOMMA f_arg_item
3239
+ {
3240
+ list, _, item = val
3241
+
3242
+ if list.sexp_type == :args then
3243
+ result = list
3244
+ else
3245
+ result = s(:args, list).line list.line
3246
+ end
3247
+
3248
+ result << (Sexp === item ? item : item.first)
3249
+ }
3250
+
3251
+ f_label: tLABEL
3252
+
3253
+ f_kw: f_label arg_value
3254
+ {
3255
+ # TODO: new_kw_arg
3256
+ (label, line), arg = val
3257
+
3258
+ identifier = label.to_sym
3259
+ self.env[identifier] = :lvar
3260
+
3261
+ kwarg = s(:kwarg, identifier, arg).line line
3262
+ result = s(:array, kwarg).line line
3263
+ }
3264
+ | f_label
3265
+ {
3266
+ (label, line), = val
3267
+
3268
+ id = label.to_sym
3269
+ self.env[id] = :lvar
3270
+
3271
+ result = s(:array, s(:kwarg, id).line(line)).line line
3272
+ }
3273
+
3274
+ f_block_kw: f_label primary_value
3275
+ {
3276
+ # TODO: new_kw_arg
3277
+ (label, line), expr = val
3278
+ id = label.to_sym
3279
+ self.env[id] = :lvar
3280
+
3281
+ result = s(:array, s(:kwarg, id, expr).line(line)).line line
3282
+ }
3283
+ | f_label
3284
+ {
3285
+ # TODO: new_kw_arg
3286
+ (label, line), = val
3287
+ id = label.to_sym
3288
+ self.env[id] = :lvar
3289
+
3290
+ result = s(:array, s(:kwarg, id).line(line)).line line
3291
+ }
3292
+
3293
+ f_block_kwarg: f_block_kw
3294
+ | f_block_kwarg tCOMMA f_block_kw
3295
+ {
3296
+ list, _, item = val
3297
+ result = list << item.last
3298
+ }
3299
+
3300
+ f_kwarg: f_kw
3301
+ | f_kwarg tCOMMA f_kw
3302
+ {
3303
+ result = args val
3304
+ }
3305
+
3306
+ kwrest_mark: tPOW
3307
+ | tDSTAR
3308
+
3309
+ f_no_kwarg: kwrest_mark kNIL
3310
+ {
3311
+ (_, line), _ = val
3312
+ result = [:"**nil", line]
3313
+ }
3314
+
3315
+ f_kwrest: kwrest_mark tIDENTIFIER
3316
+ {
3317
+ _, (id, line) = val
3318
+
3319
+ name = id.to_sym
3320
+ self.assignable [name, line]
3321
+ result = [:"**#{name}", line]
3322
+ }
3323
+ | kwrest_mark
3324
+ {
3325
+ id = :"**"
3326
+ self.env[id] = :lvar # TODO: needed?!?
3327
+ result = [id, lexer.lineno] # TODO: tPOW/tDSTAR include lineno
3328
+ }
3329
+
3330
+ f_opt: f_arg_asgn
3331
+ #if V > 30
3332
+ f_eq
3333
+ #else
3334
+ tEQL
3335
+ #endif
3336
+ arg_value
3337
+ {
3338
+ lhs, _, rhs = val
3339
+ result = self.assignable lhs, rhs
3340
+ # TODO: detect duplicate names
3341
+ # TODO? p->cur_arg = 0;
3342
+ # TODO? p->ctxt.in_argdef = 1;
3343
+ }
3344
+
3345
+ f_block_opt: f_arg_asgn
3346
+ #if V > 30
3347
+ f_eq
3348
+ #else
3349
+ tEQL
3350
+ #endif
3351
+ primary_value
3352
+ {
3353
+ lhs, _, rhs = val
3354
+ result = self.assignable lhs, rhs
3355
+ # TODO? p->cur_arg = 0;
3356
+ # TODO? p->ctxt.in_argdef = 1;
3357
+ }
3358
+
3359
+ f_block_optarg: f_block_opt
3360
+ {
3361
+ optblk, = val
3362
+ result = s(:block, optblk).line optblk.line
3363
+ }
3364
+ | f_block_optarg tCOMMA f_block_opt
3365
+ {
3366
+ optarg, _, optblk = val
3367
+ result = optarg
3368
+ result << optblk
3369
+ }
3370
+
3371
+ f_optarg: f_opt
3372
+ {
3373
+ opt, = val
3374
+ result = s(:block, opt).line opt.line
3375
+ }
3376
+ | f_optarg tCOMMA f_opt
3377
+ {
3378
+ result = self.block_append val[0], val[2]
3379
+ }
3380
+
3381
+ restarg_mark: tSTAR2 | tSTAR
3382
+
3383
+ f_rest_arg: restarg_mark tIDENTIFIER
3384
+ {
3385
+ # TODO: differs from parse.y - needs tests
3386
+ _, (id, line) = val
3387
+ name = id.to_sym
3388
+ self.assignable [name, line]
3389
+ result = [:"*#{name}", line]
3390
+ }
3391
+ | restarg_mark
3392
+ {
3393
+ name = :"*"
3394
+ self.env[name] = :lvar
3395
+ result = [name, lexer.lineno] # FIX: tSTAR to include lineno
3396
+ }
3397
+
3398
+ blkarg_mark: tAMPER2 | tAMPER
3399
+
3400
+ f_block_arg: blkarg_mark tIDENTIFIER
3401
+ {
3402
+ _, (id, line) = val
3403
+ identifier = id.to_sym
3404
+
3405
+ self.env[identifier] = :lvar
3406
+ result = ["&#{identifier}".to_sym, line]
3407
+ }
3408
+ | blkarg_mark
3409
+ {
3410
+ (_, line), = val
3411
+
3412
+ result = [:&, line]
3413
+ }
3414
+
3415
+ opt_f_block_arg: tCOMMA f_block_arg
3416
+ {
3417
+ _, arg = val
3418
+ result = arg
3419
+ }
3420
+ |
3421
+ {
3422
+ result = nil
3423
+ }
3424
+
3425
+ singleton: var_ref
3426
+ | tLPAREN2
3427
+ {
3428
+ lexer.lex_state = EXPR_BEG
3429
+ }
3430
+ expr rparen
3431
+ {
3432
+ result = val[2]
3433
+ yyerror "Can't define single method for literals." if
3434
+ result.sexp_type == :lit
3435
+ }
3436
+
3437
+ assoc_list: none
3438
+ {
3439
+ result = s(:array).line lexer.lineno
3440
+ }
3441
+ | assocs trailer
3442
+
3443
+ assocs: assoc
3444
+ | assocs tCOMMA assoc
3445
+ {
3446
+ list = val[0].dup
3447
+ more = val[2].sexp_body
3448
+ list.push(*more) unless more.empty?
3449
+ result = list
3450
+ result.sexp_type = :hash
3451
+ }
3452
+
3453
+ assoc: arg_value tASSOC arg_value
3454
+ {
3455
+ v1, _, v2 = val
3456
+ result = s(:array, v1, v2).line v1.line
3457
+ }
3458
+ | tLABEL arg_value
3459
+ {
3460
+ label, arg = val
3461
+
3462
+ lit = wrap :lit, label
3463
+ result = s(:array, lit, arg).line lit.line
3464
+ }
3465
+ | tLABEL
3466
+ {
3467
+ lit = wrap :lit, val[0]
3468
+ arg = nil
3469
+
3470
+ result = s(:array, lit, arg).line lit.line
3471
+ }
3472
+ | tSTRING_BEG string_contents tLABEL_END arg_value
3473
+ {
3474
+ (_, line), sym, _, value = val
3475
+
3476
+ sym.sexp_type = :dsym
3477
+
3478
+ result = s(:array, sym, value).line line
3479
+ }
3480
+ | tDSTAR arg_value
3481
+ {
3482
+ _, arg = val
3483
+ line = arg.line
3484
+ result = s(:array, s(:kwsplat, arg).line(line)).line line
3485
+ }
3486
+
3487
+ operation: tIDENTIFIER | tCONSTANT | tFID
3488
+ operation2: tIDENTIFIER | tCONSTANT | tFID | op
3489
+ operation3: tIDENTIFIER | tFID | op
3490
+ dot_or_colon: tDOT | tCOLON2
3491
+ call_op: tDOT
3492
+ | tLONELY # TODO: rename tANDDOT?
3493
+
3494
+ call_op2: call_op
3495
+ | tCOLON2
3496
+
3497
+ opt_terms: | terms
3498
+ opt_nl: | tNL
3499
+ rparen: opt_nl tRPAREN
3500
+ # TODO:
3501
+ # {
3502
+ # _, close = val
3503
+ # result = [close, lexer.lineno]
3504
+ # }
3505
+ rbracket: opt_nl tRBRACK
3506
+ {
3507
+ _, close = val
3508
+ result = [close, lexer.lineno]
3509
+ }
3510
+ rbrace: opt_nl tRCURLY
3511
+ {
3512
+ _, close = val
3513
+ result = [close, lexer.lineno]
3514
+ }
3515
+ trailer: | tNL | tCOMMA
3516
+
3517
+ term: tSEMI { yyerrok }
3518
+ | tNL
3519
+
3520
+ terms: term
3521
+ | terms tSEMI { yyerrok }
3522
+
3523
+ none: { result = nil; }
3524
+ end
3525
+
3526
+ ---- inner
3527
+
3528
+ require "ruby_lexer"
3529
+ require "ruby_parser_extras"
3530
+ include RubyLexer::State::Values
3531
+
3532
+ # :stopdoc:
3533
+
3534
+ # Local Variables: **
3535
+ # racc-token-length-max:14 **
3536
+ # End: **