parser 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -7
  2. data/.gitignore +0 -1
  3. data/README.md +4 -2
  4. data/bin/{parse → ruby-parse} +2 -2
  5. data/bin/ruby-rewrite +6 -0
  6. data/{AST_FORMAT.md → doc/AST_FORMAT.md} +45 -29
  7. data/doc/CUSTOMIZATION.md +37 -0
  8. data/doc/INTERNALS.md +21 -0
  9. data/lib/parser.rb +14 -3
  10. data/lib/parser/ast/node.rb +6 -0
  11. data/lib/parser/ast/processor.rb +216 -0
  12. data/lib/parser/builders/default.rb +613 -215
  13. data/lib/parser/compatibility/slop.rb +12 -0
  14. data/lib/parser/lexer.rl +30 -10
  15. data/lib/parser/lexer/explanation.rb +1 -1
  16. data/lib/parser/lexer/literal.rb +5 -6
  17. data/lib/parser/ruby18.y +31 -24
  18. data/lib/parser/ruby19.y +26 -19
  19. data/lib/parser/ruby20.y +27 -20
  20. data/lib/parser/ruby21.y +27 -20
  21. data/lib/parser/runner.rb +198 -0
  22. data/lib/parser/runner/ruby_parse.rb +87 -0
  23. data/lib/parser/runner/ruby_rewrite.rb +13 -0
  24. data/lib/parser/source/buffer.rb +1 -0
  25. data/lib/parser/source/map.rb +20 -0
  26. data/lib/parser/source/map/block.rb +16 -0
  27. data/lib/parser/source/map/collection.rb +16 -0
  28. data/lib/parser/source/map/condition.rb +19 -0
  29. data/lib/parser/source/map/constant.rb +27 -0
  30. data/lib/parser/source/map/definition.rb +21 -0
  31. data/lib/parser/source/map/for.rb +17 -0
  32. data/lib/parser/source/map/keyword.rb +18 -0
  33. data/lib/parser/source/map/rescue_body.rb +19 -0
  34. data/lib/parser/source/map/send.rb +29 -0
  35. data/lib/parser/source/map/ternary.rb +16 -0
  36. data/lib/parser/source/map/variable.rb +26 -0
  37. data/lib/parser/source/range.rb +25 -24
  38. data/lib/parser/version.rb +3 -0
  39. data/parser.gemspec +4 -2
  40. data/test/parse_helper.rb +13 -10
  41. data/test/test_lexer.rb +32 -11
  42. data/test/test_parse_helper.rb +1 -0
  43. data/test/test_parser.rb +176 -128
  44. data/test/test_source_range.rb +18 -6
  45. metadata +161 -91
  46. data/bin/benchmark +0 -47
  47. data/bin/explain-parse +0 -14
  48. data/lib/parser/source/map/variable_assignment.rb +0 -15
@@ -0,0 +1,12 @@
1
+ # https://github.com/injekt/slop/pull/110
2
+ class Slop
3
+ def extract_long_flag(objects, config)
4
+ flag = objects.first.to_s
5
+ if flag =~ /\A(?:--?)?[a-zA-Z0-9][a-zA-Z0-9_.-]+\=?\??\z/
6
+ config[:argument] ||= true if flag.end_with?('=')
7
+ config[:optional_argument] = true if flag.end_with?('=?')
8
+ objects.shift
9
+ clean(flag).sub(/\=\??\z/, '')
10
+ end
11
+ end
12
+ end
data/lib/parser/lexer.rl CHANGED
@@ -992,6 +992,9 @@ class Parser::Lexer
992
992
  => { emit(KEYWORDS[tok]);
993
993
  fnext expr_endfn; fbreak; };
994
994
 
995
+ constant
996
+ => { emit(:tCONSTANT) };
997
+
995
998
  bareword [?=!]?
996
999
  => { emit(:tIDENTIFIER)
997
1000
  fnext expr_endfn; fbreak; };
@@ -1009,6 +1012,9 @@ class Parser::Lexer
1009
1012
  => { emit_table(PUNCTUATION)
1010
1013
  fnext expr_endfn; fbreak; };
1011
1014
 
1015
+ '::'
1016
+ => { fhold; fhold; fgoto expr_end; };
1017
+
1012
1018
  ':'
1013
1019
  => { fhold; fgoto expr_beg; };
1014
1020
 
@@ -1266,7 +1272,7 @@ class Parser::Lexer
1266
1272
  => {
1267
1273
  fhold;
1268
1274
  if tok.start_with? '-'
1269
- emit(:tUMINUS_NUM, '-')
1275
+ emit(:tUMINUS_NUM, '-', @ts, @ts + 1)
1270
1276
  fnext expr_end; fbreak;
1271
1277
  end
1272
1278
  };
@@ -1635,13 +1641,18 @@ class Parser::Lexer
1635
1641
  ( '_' digit+ )* digit* '_'?
1636
1642
  | '0' %{ @num_base = 8; @num_digits_s = @ts }
1637
1643
  ( '_' digit+ )* digit* '_'?
1638
- )
1644
+ ) %{ tm = p } c_alpha?
1639
1645
  => {
1640
- digits = tok(@num_digits_s)
1646
+ unless (char = tok(tm, @te)).empty?
1647
+ diagnostic :fatal, Parser::ERRORS[:unexpected] % { :character => char },
1648
+ range(tm, tm + 1)
1649
+ end
1650
+
1651
+ digits = tok(@num_digits_s, tm)
1641
1652
 
1642
1653
  if digits.end_with? '_'
1643
1654
  diagnostic :error, Parser::ERRORS[:trailing_underscore],
1644
- range(@te - 1, @te)
1655
+ range(tm - 1, tm)
1645
1656
  elsif digits.empty? && @num_base == 8 && version?(18)
1646
1657
  # 1.8 did not raise an error on 0o.
1647
1658
  digits = "0"
@@ -1653,7 +1664,8 @@ class Parser::Lexer
1653
1664
  range(invalid_s, invalid_s + 1)
1654
1665
  end
1655
1666
 
1656
- emit(:tINTEGER, digits.to_i(@num_base))
1667
+ emit(:tINTEGER, digits.to_i(@num_base), @ts, tm)
1668
+ p = tm - 1
1657
1669
  fbreak;
1658
1670
  };
1659
1671
 
@@ -1665,18 +1677,26 @@ class Parser::Lexer
1665
1677
  (
1666
1678
  '.' ( digit+ '_' )* digit+ |
1667
1679
  ( '.' ( digit+ '_' )* digit+ )? [eE] [+\-]? ( digit+ '_' )* digit+
1668
- )
1680
+ ) %{ tm = p } c_alpha?
1669
1681
  => {
1670
- if tok.start_with? '.'
1682
+ unless (char = tok(tm, @te)).empty?
1683
+ diagnostic :fatal, Parser::ERRORS[:unexpected] % { :character => char },
1684
+ range(tm, tm + 1)
1685
+ end
1686
+
1687
+ digits = tok(@ts, tm)
1688
+
1689
+ if digits.start_with? '.'
1671
1690
  diagnostic :error, Parser::ERRORS[:no_dot_digit_literal]
1672
- elsif tok =~ /^[eE]/
1691
+ elsif digits =~ /^[eE]/
1673
1692
  # The rule above allows to specify floats as just `e10', which is
1674
1693
  # certainly not a float. Send a patch if you can do this better.
1675
- emit(:tIDENTIFIER, tok)
1694
+ emit(:tIDENTIFIER, digits, @ts, tm)
1676
1695
  fbreak;
1677
1696
  end
1678
1697
 
1679
- emit(:tFLOAT, tok.to_f)
1698
+ emit(:tFLOAT, digits.to_f, @ts, tm)
1699
+ p = tm - 1
1680
1700
  fbreak;
1681
1701
  };
1682
1702
 
@@ -17,7 +17,7 @@ module Parser
17
17
  private
18
18
 
19
19
  def decorate(range, token, info)
20
- from, to = range.begin_column, range.end_column
20
+ from, to = range.begin.column, range.end.column
21
21
 
22
22
  line = range.source_line
23
23
  line[from..to] = "\e[4m#{line[from..to]}\e[0m"
@@ -2,7 +2,7 @@ module Parser
2
2
 
3
3
  class Lexer::Literal
4
4
  DELIMITERS = { '(' => ')', '[' => ']', '{' => '}', '<' => '>' }
5
- MONOLITHIC = { :tSTRING_BEG => :tSTRING, :tSYMBEG => :tSYMBOL }
5
+ MONOLITHIC = { :tSTRING_BEG => :tSTRING }
6
6
 
7
7
  TYPES = {
8
8
  # type start token interpolate?
@@ -64,12 +64,11 @@ module Parser
64
64
 
65
65
  # Monolithic strings are glued into a single token, e.g.
66
66
  # tSTRING_BEG tSTRING_CONTENT tSTRING_END -> tSTRING.
67
- @monolithic = (
68
- [:tSTRING_BEG, :tSYMBEG].include?(type) &&
69
- !heredoc?
70
- )
67
+ @monolithic = (@start_tok == :tSTRING_BEG &&
68
+ %w(' ").include?(str_type) &&
69
+ !heredoc?)
71
70
 
72
- # Also capture delimiter in %w() style literals
71
+ # Capture opening delimiter in percent-literals.
73
72
  unless @heredoc_e || @str_type.end_with?(delimiter)
74
73
  @str_type << delimiter
75
74
  end
data/lib/parser/ruby18.y CHANGED
@@ -51,17 +51,17 @@ rule
51
51
  bodystmt: compstmt opt_rescue opt_else opt_ensure
52
52
  {
53
53
  rescue_bodies = val[1]
54
- else_, t_else = val[2]
55
- ensure_, t_ensure = val[3]
54
+ else_t, else_ = val[2]
55
+ ensure_t, ensure_ = val[3]
56
56
 
57
57
  if rescue_bodies.empty? && !else_.nil?
58
- diagnostic :warning, :useless_else, t_else
58
+ diagnostic :warning, :useless_else, else_t
59
59
  end
60
60
 
61
61
  result = @builder.begin_body(val[0],
62
62
  rescue_bodies,
63
- else_, t_else,
64
- ensure_, t_ensure)
63
+ else_t, else_,
64
+ ensure_t, ensure_)
65
65
  }
66
66
 
67
67
  compstmt: stmts opt_terms
@@ -126,11 +126,11 @@ rule
126
126
  }
127
127
  | stmt kWHILE_MOD expr_value
128
128
  {
129
- result = @builder.loop_mod(val[0], val[1], val[2])
129
+ result = @builder.loop_mod(:while, val[0], val[1], val[2])
130
130
  }
131
131
  | stmt kUNTIL_MOD expr_value
132
132
  {
133
- result = @builder.loop_mod(val[0], val[1], val[2])
133
+ result = @builder.loop_mod(:until, val[0], val[1], val[2])
134
134
  }
135
135
  | stmt kRESCUE_MOD stmt
136
136
  {
@@ -351,7 +351,7 @@ rule
351
351
  }
352
352
  | tLPAREN mlhs_entry tRPAREN
353
353
  {
354
- result = @builder.parenthesize(val[0], val[1], val[2])
354
+ result = @builder.begin(val[0], val[1], val[2])
355
355
  }
356
356
 
357
357
  mlhs_entry: mlhs_basic
@@ -391,7 +391,7 @@ rule
391
391
  mlhs_item: mlhs_node
392
392
  | tLPAREN mlhs_entry tRPAREN
393
393
  {
394
- result = @builder.parenthesize(val[0], val[1], val[2])
394
+ result = @builder.begin(val[0], val[1], val[2])
395
395
  }
396
396
 
397
397
  mlhs_head: mlhs_item tCOMMA
@@ -1009,11 +1009,11 @@ rule
1009
1009
  }
1010
1010
  opt_nl tRPAREN
1011
1011
  {
1012
- result = @builder.parenthesize(val[0], val[1], val[3])
1012
+ result = @builder.begin(val[0], val[1], val[4])
1013
1013
  }
1014
1014
  | tLPAREN compstmt tRPAREN
1015
1015
  {
1016
- result = @builder.parenthesize(val[0], val[1], val[2])
1016
+ result = @builder.begin(val[0], val[1], val[2])
1017
1017
  }
1018
1018
  | primary_value tCOLON2 tCONSTANT
1019
1019
  {
@@ -1095,7 +1095,7 @@ rule
1095
1095
  }
1096
1096
  compstmt kEND
1097
1097
  {
1098
- result = @builder.loop(val[0], val[2], val[3],
1098
+ result = @builder.loop(:while, val[0], val[2], val[3],
1099
1099
  val[5], val[6])
1100
1100
  }
1101
1101
  | kUNTIL
@@ -1108,20 +1108,32 @@ rule
1108
1108
  }
1109
1109
  compstmt kEND
1110
1110
  {
1111
- result = @builder.loop(val[0], val[2], val[3],
1111
+ result = @builder.loop(:until, val[0], val[2], val[3],
1112
1112
  val[5], val[6])
1113
1113
  }
1114
1114
  | kCASE expr_value opt_terms case_body kEND
1115
1115
  {
1116
- result = @builder.case(val[0], val[1], val[3], val[4])
1116
+ when_bodies = val[3][0..-2]
1117
+ else_t, else_body = val[3][-1]
1118
+
1119
+ result = @builder.case(val[0], val[1],
1120
+ when_bodies, else_t, else_body,
1121
+ val[4])
1117
1122
  }
1118
1123
  | kCASE opt_terms case_body kEND
1119
1124
  {
1120
- result = @builder.case(val[0], nil, val[2], val[3])
1125
+ when_bodies = val[2][0..-2]
1126
+ else_t, else_body = val[2][-1]
1127
+
1128
+ result = @builder.case(val[0], nil,
1129
+ when_bodies, else_t, else_body,
1130
+ val[3])
1121
1131
  }
1122
1132
  | kCASE opt_terms kELSE compstmt kEND
1123
1133
  {
1124
- result = @builder.case(val[0], nil, [ val[3] ], val[4])
1134
+ result = @builder.case(val[0], nil,
1135
+ [], val[2], val[3],
1136
+ val[4])
1125
1137
  }
1126
1138
  | kFOR for_var kIN
1127
1139
  {
@@ -1456,8 +1468,7 @@ rule
1456
1468
 
1457
1469
  cases: opt_else
1458
1470
  {
1459
- else_t, else_ = val[0]
1460
- result = [ else_ ]
1471
+ result = [ val[0] ]
1461
1472
  }
1462
1473
  | case_body
1463
1474
 
@@ -1488,13 +1499,13 @@ rule
1488
1499
 
1489
1500
  exc_var: tASSOC lhs
1490
1501
  {
1491
- result = val
1502
+ result = [ val[0], val[1] ]
1492
1503
  }
1493
1504
  | none
1494
1505
 
1495
1506
  opt_ensure: kENSURE compstmt
1496
1507
  {
1497
- result = val
1508
+ result = [ val[0], val[1] ]
1498
1509
  }
1499
1510
  | none
1500
1511
 
@@ -1629,10 +1640,6 @@ xstring_contents: # nothing
1629
1640
 
1630
1641
  symbol: tSYMBOL
1631
1642
  {
1632
- if val[0][0].empty?
1633
- diagnostic(:error, :empty_symbol, val[0])
1634
- end
1635
-
1636
1643
  result = @builder.symbol(val[0])
1637
1644
  }
1638
1645
 
data/lib/parser/ruby19.y CHANGED
@@ -77,17 +77,17 @@ rule
77
77
  bodystmt: compstmt opt_rescue opt_else opt_ensure
78
78
  {
79
79
  rescue_bodies = val[1]
80
- else_, t_else = val[2]
81
- ensure_, t_ensure = val[3]
80
+ else_t, else_ = val[2]
81
+ ensure_t, ensure_ = val[3]
82
82
 
83
83
  if rescue_bodies.empty? && !else_.nil?
84
- diagnostic :warning, :useless_else, t_else
84
+ diagnostic :warning, :useless_else, else_t
85
85
  end
86
86
 
87
87
  result = @builder.begin_body(val[0],
88
88
  rescue_bodies,
89
- else_, t_else,
90
- ensure_, t_ensure)
89
+ else_t, else_,
90
+ ensure_t, ensure_)
91
91
  }
92
92
 
93
93
  compstmt: stmts opt_terms
@@ -152,11 +152,11 @@ rule
152
152
  }
153
153
  | stmt kWHILE_MOD expr_value
154
154
  {
155
- result = @builder.loop_mod(val[0], val[1], val[2])
155
+ result = @builder.loop_mod(:while, val[0], val[1], val[2])
156
156
  }
157
157
  | stmt kUNTIL_MOD expr_value
158
158
  {
159
- result = @builder.loop_mod(val[0], val[1], val[2])
159
+ result = @builder.loop_mod(:until, val[0], val[1], val[2])
160
160
  }
161
161
  | stmt kRESCUE_MOD stmt
162
162
  {
@@ -371,7 +371,7 @@ rule
371
371
  }
372
372
  | tLPAREN mlhs_inner rparen
373
373
  {
374
- result = @builder.parenthesize(val[0], val[1], val[2])
374
+ result = @builder.begin(val[0], val[1], val[2])
375
375
  }
376
376
 
377
377
  mlhs_inner: mlhs_basic
@@ -433,7 +433,7 @@ rule
433
433
  mlhs_item: mlhs_node
434
434
  | tLPAREN mlhs_inner rparen
435
435
  {
436
- result = @builder.parenthesize(val[0], val[1], val[2])
436
+ result = @builder.begin(val[0], val[1], val[2])
437
437
  }
438
438
 
439
439
  mlhs_head: mlhs_item tCOMMA
@@ -962,11 +962,11 @@ rule
962
962
  }
963
963
  opt_nl tRPAREN
964
964
  {
965
- result = @builder.parenthesize(val[0], val[1], val[4])
965
+ result = @builder.begin(val[0], val[1], val[4])
966
966
  }
967
967
  | tLPAREN compstmt tRPAREN
968
968
  {
969
- result = @builder.parenthesize(val[0], val[1], val[2])
969
+ result = @builder.begin(val[0], val[1], val[2])
970
970
  }
971
971
  | primary_value tCOLON2 tCONSTANT
972
972
  {
@@ -1060,7 +1060,7 @@ rule
1060
1060
  }
1061
1061
  compstmt kEND
1062
1062
  {
1063
- result = @builder.loop(val[0], val[2], val[3],
1063
+ result = @builder.loop(:while, val[0], val[2], val[3],
1064
1064
  val[5], val[6])
1065
1065
  }
1066
1066
  | kUNTIL
@@ -1073,16 +1073,24 @@ rule
1073
1073
  }
1074
1074
  compstmt kEND
1075
1075
  {
1076
- result = @builder.loop(val[0], val[2], val[3],
1076
+ result = @builder.loop(:until, val[0], val[2], val[3],
1077
1077
  val[5], val[6])
1078
1078
  }
1079
1079
  | kCASE expr_value opt_terms case_body kEND
1080
1080
  {
1081
- result = @builder.case(val[0], val[1], val[3], val[4])
1081
+ *when_bodies, (else_t, else_body) = *val[3]
1082
+
1083
+ result = @builder.case(val[0], val[1],
1084
+ when_bodies, else_t, else_body,
1085
+ val[4])
1082
1086
  }
1083
1087
  | kCASE opt_terms case_body kEND
1084
1088
  {
1085
- result = @builder.case(val[0], nil, val[2], val[3])
1089
+ *when_bodies, (else_t, else_body) = *val[2]
1090
+
1091
+ result = @builder.case(val[0], nil,
1092
+ when_bodies, else_t, else_body,
1093
+ val[3])
1086
1094
  }
1087
1095
  | kFOR for_var kIN
1088
1096
  {
@@ -1567,8 +1575,7 @@ rule
1567
1575
 
1568
1576
  cases: opt_else
1569
1577
  {
1570
- else_t, else_ = val[0]
1571
- result = [ else_ ]
1578
+ result = [ val[0] ]
1572
1579
  }
1573
1580
  | case_body
1574
1581
 
@@ -1599,13 +1606,13 @@ rule
1599
1606
 
1600
1607
  exc_var: tASSOC lhs
1601
1608
  {
1602
- result = val
1609
+ result = [ val[0], val[1] ]
1603
1610
  }
1604
1611
  | none
1605
1612
 
1606
1613
  opt_ensure: kENSURE compstmt
1607
1614
  {
1608
- result = val
1615
+ result = [ val[0], val[1] ]
1609
1616
  }
1610
1617
  | none
1611
1618
 
data/lib/parser/ruby20.y CHANGED
@@ -78,17 +78,17 @@ rule
78
78
  bodystmt: compstmt opt_rescue opt_else opt_ensure
79
79
  {
80
80
  rescue_bodies = val[1]
81
- else_, t_else = val[2]
82
- ensure_, t_ensure = val[3]
81
+ else_t, else_ = val[2]
82
+ ensure_t, ensure_ = val[3]
83
83
 
84
84
  if rescue_bodies.empty? && !else_.nil?
85
- diagnostic :warning, :useless_else, t_else
85
+ diagnostic :warning, :useless_else, else_t
86
86
  end
87
87
 
88
88
  result = @builder.begin_body(val[0],
89
89
  rescue_bodies,
90
- else_, t_else,
91
- ensure_, t_ensure)
90
+ else_t, else_,
91
+ ensure_t, ensure_)
92
92
  }
93
93
 
94
94
  compstmt: stmts opt_terms
@@ -163,11 +163,11 @@ rule
163
163
  }
164
164
  | stmt kWHILE_MOD expr_value
165
165
  {
166
- result = @builder.loop_mod(val[0], val[1], val[2])
166
+ result = @builder.loop_mod(:while, val[0], val[1], val[2])
167
167
  }
168
168
  | stmt kUNTIL_MOD expr_value
169
169
  {
170
- result = @builder.loop_mod(val[0], val[1], val[2])
170
+ result = @builder.loop_mod(:until, val[0], val[1], val[2])
171
171
  }
172
172
  | stmt kRESCUE_MOD stmt
173
173
  {
@@ -379,7 +379,7 @@ rule
379
379
  }
380
380
  | tLPAREN mlhs_inner rparen
381
381
  {
382
- result = @builder.parenthesize(val[0], val[1], val[2])
382
+ result = @builder.begin(val[0], val[1], val[2])
383
383
  }
384
384
 
385
385
  mlhs_inner: mlhs_basic
@@ -441,7 +441,7 @@ rule
441
441
  mlhs_item: mlhs_node
442
442
  | tLPAREN mlhs_inner rparen
443
443
  {
444
- result = @builder.parenthesize(val[0], val[1], val[2])
444
+ result = @builder.begin(val[0], val[1], val[2])
445
445
  }
446
446
 
447
447
  mlhs_head: mlhs_item tCOMMA
@@ -991,7 +991,7 @@ rule
991
991
  }
992
992
  opt_nl tRPAREN
993
993
  {
994
- result = @builder.parenthesize(val[0], val[1], val[4])
994
+ result = @builder.begin(val[0], val[1], val[4])
995
995
  }
996
996
  | tLPAREN_ARG
997
997
  {
@@ -999,11 +999,11 @@ rule
999
999
  }
1000
1000
  opt_nl tRPAREN
1001
1001
  {
1002
- result = @builder.parenthesize(val[0], nil, val[3])
1002
+ result = @builder.begin(val[0], nil, val[3])
1003
1003
  }
1004
1004
  | tLPAREN compstmt tRPAREN
1005
1005
  {
1006
- result = @builder.parenthesize(val[0], val[1], val[2])
1006
+ result = @builder.begin(val[0], val[1], val[2])
1007
1007
  }
1008
1008
  | primary_value tCOLON2 tCONSTANT
1009
1009
  {
@@ -1097,7 +1097,7 @@ rule
1097
1097
  }
1098
1098
  compstmt kEND
1099
1099
  {
1100
- result = @builder.loop(val[0], val[2], val[3],
1100
+ result = @builder.loop(:while, val[0], val[2], val[3],
1101
1101
  val[5], val[6])
1102
1102
  }
1103
1103
  | kUNTIL
@@ -1110,16 +1110,24 @@ rule
1110
1110
  }
1111
1111
  compstmt kEND
1112
1112
  {
1113
- result = @builder.loop(val[0], val[2], val[3],
1113
+ result = @builder.loop(:until, val[0], val[2], val[3],
1114
1114
  val[5], val[6])
1115
1115
  }
1116
1116
  | kCASE expr_value opt_terms case_body kEND
1117
1117
  {
1118
- result = @builder.case(val[0], val[1], val[3], val[4])
1118
+ *when_bodies, (else_t, else_body) = *val[3]
1119
+
1120
+ result = @builder.case(val[0], val[1],
1121
+ when_bodies, else_t, else_body,
1122
+ val[4])
1119
1123
  }
1120
1124
  | kCASE opt_terms case_body kEND
1121
1125
  {
1122
- result = @builder.case(val[0], nil, val[2], val[3])
1126
+ *when_bodies, (else_t, else_body) = *val[2]
1127
+
1128
+ result = @builder.case(val[0], nil,
1129
+ when_bodies, else_t, else_body,
1130
+ val[3])
1123
1131
  }
1124
1132
  | kFOR for_var kIN
1125
1133
  {
@@ -1641,8 +1649,7 @@ opt_block_args_tail:
1641
1649
 
1642
1650
  cases: opt_else
1643
1651
  {
1644
- else_t, else_ = val[0]
1645
- result = [ else_ ]
1652
+ result = [ val[0] ]
1646
1653
  }
1647
1654
  | case_body
1648
1655
 
@@ -1673,13 +1680,13 @@ opt_block_args_tail:
1673
1680
 
1674
1681
  exc_var: tASSOC lhs
1675
1682
  {
1676
- result = val
1683
+ result = [ val[0], val[1] ]
1677
1684
  }
1678
1685
  | none
1679
1686
 
1680
1687
  opt_ensure: kENSURE compstmt
1681
1688
  {
1682
- result = val
1689
+ result = [ val[0], val[1] ]
1683
1690
  }
1684
1691
  | none
1685
1692