parser 1.1.0 → 1.2.0

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 (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