parser 2.7.2.0 → 3.1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +25 -0
  3. data/lib/parser/all.rb +2 -0
  4. data/lib/parser/ast/processor.rb +3 -0
  5. data/lib/parser/base.rb +1 -0
  6. data/lib/parser/builders/default.rb +225 -27
  7. data/lib/parser/context.rb +22 -37
  8. data/lib/parser/current.rb +28 -10
  9. data/lib/parser/current_arg_stack.rb +5 -2
  10. data/lib/parser/lexer/dedenter.rb +7 -1
  11. data/lib/parser/lexer/explanation.rb +1 -1
  12. data/lib/parser/lexer.rb +12728 -11483
  13. data/lib/parser/macruby.rb +2476 -2448
  14. data/lib/parser/max_numparam_stack.rb +16 -8
  15. data/lib/parser/messages.rb +5 -0
  16. data/lib/parser/meta.rb +2 -1
  17. data/lib/parser/ruby18.rb +2161 -2116
  18. data/lib/parser/ruby19.rb +2458 -2424
  19. data/lib/parser/ruby20.rb +2634 -2598
  20. data/lib/parser/ruby21.rb +2700 -2667
  21. data/lib/parser/ruby22.rb +2533 -2491
  22. data/lib/parser/ruby23.rb +2616 -2571
  23. data/lib/parser/ruby24.rb +2651 -2609
  24. data/lib/parser/ruby25.rb +2545 -2513
  25. data/lib/parser/ruby26.rb +2669 -2624
  26. data/lib/parser/ruby27.rb +3953 -3842
  27. data/lib/parser/ruby30.rb +4089 -4045
  28. data/lib/parser/ruby31.rb +8354 -0
  29. data/lib/parser/ruby32.rb +8330 -0
  30. data/lib/parser/rubymotion.rb +2454 -2415
  31. data/lib/parser/runner.rb +12 -1
  32. data/lib/parser/source/buffer.rb +50 -27
  33. data/lib/parser/source/comment/associator.rb +17 -4
  34. data/lib/parser/source/comment.rb +13 -0
  35. data/lib/parser/source/tree_rewriter.rb +27 -0
  36. data/lib/parser/static_environment.rb +13 -0
  37. data/lib/parser/variables_stack.rb +4 -0
  38. data/lib/parser/version.rb +1 -1
  39. data/parser.gemspec +1 -1
  40. metadata +9 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3efc381a3ad92df723e4a698afbceb63f65fdb7c892f690dbd569ba298307d8b
4
- data.tar.gz: b9e78eb7dd39f6539fc21883fbec26b1a0c2d377c68bf060d485df5521318e54
3
+ metadata.gz: 12a38198be7971a87e3fbc2514f45120238a8004b1b267382a481ea971c8d9ec
4
+ data.tar.gz: ec1a2a51e94eb30280b31e5f26cb28cb1e50b94a9d3a11ae35616b79eaf11b52
5
5
  SHA512:
6
- metadata.gz: 3c9b2d1df5a463c289f2881c0064c956e88560bc14af30bbb9fe3828ae7a3e1f8a88352172e353b196f34ba1e98640b6bf38bcbb50bef0f8661aacf9e8ccdc1b
7
- data.tar.gz: e394d70911b7d86ee7049b0ecaab839120da2f90372630e48c6bb3c14f3b45b35322a2d99ca516df6cc2e8a8e7c0c79aca1031c3dfa28b0026c300ea10b51ed4
6
+ metadata.gz: e37d66e7c76e0af7d9ad1e9c3c635741436f92d0eef67032fdad83c38090c90cdb9be49018e20786ae540b24d18628695ab4b372a94c96e93b1ce36418e41da5
7
+ data.tar.gz: 9ad75e610252fb6db157948fb162b0907baedeac7c4107574b78b3869c2490afabec269ab31303ceec2a3a7f17659eb06b43e9b6677b279fb412abade076b93a
data/LICENSE.txt ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2013-2016 whitequark <whitequark@whitequark.org>
2
+
3
+ Parts of the source are derived from ruby_parser:
4
+ Copyright (c) Ryan Davis, seattle.rb
5
+
6
+ MIT License
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining
9
+ a copy of this software and associated documentation files (the
10
+ "Software"), to deal in the Software without restriction, including
11
+ without limitation the rights to use, copy, modify, merge, publish,
12
+ distribute, sublicense, and/or sell copies of the Software, and to
13
+ permit persons to whom the Software is furnished to do so, subject to
14
+ the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be
17
+ included in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/lib/parser/all.rb CHANGED
@@ -11,3 +11,5 @@ require 'parser/ruby25'
11
11
  require 'parser/ruby26'
12
12
  require 'parser/ruby27'
13
13
  require 'parser/ruby30'
14
+ require 'parser/ruby31'
15
+ require 'parser/ruby32'
@@ -20,6 +20,7 @@ module Parser
20
20
  alias on_array process_regular_node
21
21
  alias on_pair process_regular_node
22
22
  alias on_hash process_regular_node
23
+ alias on_kwargs process_regular_node
23
24
  alias on_irange process_regular_node
24
25
  alias on_erange process_regular_node
25
26
 
@@ -239,6 +240,8 @@ module Parser
239
240
 
240
241
  alias on_case_match process_regular_node
241
242
  alias on_in_match process_regular_node
243
+ alias on_match_pattern process_regular_node
244
+ alias on_match_pattern_p process_regular_node
242
245
  alias on_in_pattern process_regular_node
243
246
  alias on_if_guard process_regular_node
244
247
  alias on_unless_guard process_regular_node
data/lib/parser/base.rb CHANGED
@@ -109,6 +109,7 @@ module Parser
109
109
  end
110
110
  private_class_method :setup_source_buffer
111
111
 
112
+ attr_reader :lexer
112
113
  attr_reader :diagnostics
113
114
  attr_reader :builder
114
115
  attr_reader :static_env
@@ -128,6 +128,83 @@ module Parser
128
128
 
129
129
  @emit_forward_arg = false
130
130
 
131
+ class << self
132
+ ##
133
+ # AST compatibility attribute; Starting from Ruby 2.7 keyword arguments
134
+ # of method calls that are passed explicitly as a hash (i.e. with curly braces)
135
+ # are treated as positional arguments and Ruby 2.7 emits a warning on such method
136
+ # call. Ruby 3.0 given an ArgumentError.
137
+ #
138
+ # If set to false (the default) the last hash argument is emitted as `hash`:
139
+ #
140
+ # ```
141
+ # (send nil :foo
142
+ # (hash
143
+ # (pair
144
+ # (sym :bar)
145
+ # (int 42))))
146
+ # ```
147
+ #
148
+ # If set to true it is emitted as `kwargs`:
149
+ #
150
+ # ```
151
+ # (send nil :foo
152
+ # (kwargs
153
+ # (pair
154
+ # (sym :bar)
155
+ # (int 42))))
156
+ # ```
157
+ #
158
+ # Note that `kwargs` node is just a replacement for `hash` argument,
159
+ # so if there's are multiple arguments (or a `kwsplat`) all of them
160
+ # are wrapped into `kwargs` instead of `hash`:
161
+ #
162
+ # ```
163
+ # (send nil :foo
164
+ # (kwargs
165
+ # (pair
166
+ # (sym :a)
167
+ # (int 42))
168
+ # (kwsplat
169
+ # (send nil :b))
170
+ # (pair
171
+ # (sym :c)
172
+ # (int 10))))
173
+ # ```
174
+ attr_accessor :emit_kwargs
175
+ end
176
+
177
+ @emit_kwargs = false
178
+
179
+ class << self
180
+ ##
181
+ # AST compatibility attribute; Starting from 3.0 Ruby returns
182
+ # true/false from single-line pattern matching with `in` keyword.
183
+ #
184
+ # Before 3.0 there was an exception if given value doesn't match pattern.
185
+ #
186
+ # NOTE: This attribute affects only Ruby 2.7 grammar.
187
+ # 3.0 grammar always emits `match_pattern`/`match_pattern_p`
188
+ #
189
+ # If compatibility attribute set to false `foo in bar` is emitted as `in_match`:
190
+ #
191
+ # ```
192
+ # (in-match
193
+ # (send nil :foo)
194
+ # (match-var :bar))
195
+ # ```
196
+ #
197
+ # If set to true it's emitted as `match_pattern_p`:
198
+ # ```
199
+ # (match-pattern-p
200
+ # (send nil :foo)
201
+ # (match-var :bar))
202
+ # ```
203
+ attr_accessor :emit_match_pattern
204
+ end
205
+
206
+ @emit_match_pattern = false
207
+
131
208
  class << self
132
209
  ##
133
210
  # @api private
@@ -138,6 +215,8 @@ module Parser
138
215
  @emit_index = true
139
216
  @emit_arg_inside_procarg0 = true
140
217
  @emit_forward_arg = true
218
+ @emit_kwargs = true
219
+ @emit_match_pattern = true
141
220
  end
142
221
  end
143
222
 
@@ -310,18 +389,23 @@ module Parser
310
389
  if !dedent_level.nil?
311
390
  dedenter = Lexer::Dedenter.new(dedent_level)
312
391
 
313
- if node.type == :str
392
+ case node.type
393
+ when :str
314
394
  str = node.children.first
315
395
  dedenter.dedent(str)
316
- elsif node.type == :dstr || node.type == :xstr
317
- node.children.each do |str_node|
396
+ when :dstr, :xstr
397
+ children = node.children.map do |str_node|
318
398
  if str_node.type == :str
319
399
  str = str_node.children.first
320
400
  dedenter.dedent(str)
401
+ next nil if str.empty?
321
402
  else
322
403
  dedenter.interrupt
323
404
  end
405
+ str_node
324
406
  end
407
+
408
+ node = node.updated(nil, children.compact)
325
409
  end
326
410
  end
327
411
 
@@ -434,12 +518,52 @@ module Parser
434
518
  n(:pair, [ key, value ], pair_map)
435
519
  end
436
520
 
521
+ def pair_label(key_t)
522
+ key_l = loc(key_t)
523
+ value_l = key_l.adjust(end_pos: -1)
524
+
525
+ label = value(key_t)
526
+ value =
527
+ if label =~ /\A[[:lower:]]/
528
+ n(:ident, [ label.to_sym ], Source::Map::Variable.new(value_l))
529
+ else
530
+ n(:const, [ nil, label.to_sym ], Source::Map::Constant.new(nil, value_l, value_l))
531
+ end
532
+ pair_keyword(key_t, accessible(value))
533
+ end
534
+
437
535
  def kwsplat(dstar_t, arg)
438
536
  n(:kwsplat, [ arg ],
439
537
  unary_op_map(dstar_t, arg))
440
538
  end
441
539
 
442
540
  def associate(begin_t, pairs, end_t)
541
+ 0.upto(pairs.length - 1) do |i|
542
+ (i + 1).upto(pairs.length - 1) do |j|
543
+ key1, = *pairs[i]
544
+ key2, = *pairs[j]
545
+
546
+ do_warn = false
547
+
548
+ # keys have to be simple nodes, MRI ignores equal composite keys like
549
+ # `{ a(1) => 1, a(1) => 1 }`
550
+ case key1.type
551
+ when :sym, :str, :int, :float
552
+ if key1 == key2
553
+ do_warn = true
554
+ end
555
+ when :rational, :complex, :regexp
556
+ if @parser.version >= 31 && key1 == key2
557
+ do_warn = true
558
+ end
559
+ end
560
+
561
+ if do_warn
562
+ diagnostic :warning, :duplicate_hash_key, nil, key2.loc.expression
563
+ end
564
+ end
565
+ end
566
+
443
567
  n(:hash, [ *pairs ],
444
568
  collection_map(begin_t, pairs, end_t))
445
569
  end
@@ -524,19 +648,29 @@ module Parser
524
648
  when :ident
525
649
  name, = *node
526
650
 
527
- if @parser.static_env.declared?(name)
528
- if name.to_s == parser.current_arg_stack.top
529
- diagnostic :error, :circular_argument_reference,
530
- { :var_name => name.to_s }, node.loc.expression
531
- end
651
+ if %w[? !].any? { |c| name.to_s.end_with?(c) }
652
+ diagnostic :error, :invalid_id_to_get,
653
+ { :identifier => name.to_s }, node.loc.expression
654
+ end
532
655
 
533
- node.updated(:lvar)
534
- else
535
- name, = *node
536
- n(:send, [ nil, name ],
656
+ # Numbered parameters are not declared anywhere,
657
+ # so they take precedence over method calls in numblock contexts
658
+ if @parser.version >= 27 && @parser.try_declare_numparam(node)
659
+ return node.updated(:lvar)
660
+ end
661
+
662
+ unless @parser.static_env.declared?(name)
663
+ return n(:send, [ nil, name ],
537
664
  var_send_map(node))
538
665
  end
539
666
 
667
+ if name.to_s == parser.current_arg_stack.top
668
+ diagnostic :error, :circular_argument_reference,
669
+ { :var_name => name.to_s }, node.loc.expression
670
+ end
671
+
672
+ node.updated(:lvar)
673
+
540
674
  else
541
675
  node
542
676
  end
@@ -580,7 +714,7 @@ module Parser
580
714
  node.updated(:gvasgn)
581
715
 
582
716
  when :const
583
- unless @parser.context.dynamic_const_definition_allowed?
717
+ if @parser.context.in_def
584
718
  diagnostic :error, :dynamic_const, nil, node.loc.expression
585
719
  end
586
720
 
@@ -599,6 +733,17 @@ module Parser
599
733
 
600
734
  node.updated(:lvasgn)
601
735
 
736
+ when :match_var
737
+ name, = *node
738
+
739
+ var_name = node.children[0].to_s
740
+ name_loc = node.loc.expression
741
+
742
+ check_assignment_to_numparam(var_name, name_loc)
743
+ check_reserved_for_numparam(var_name, name_loc)
744
+
745
+ node
746
+
602
747
  when :nil, :self, :true, :false,
603
748
  :__FILE__, :__LINE__, :__ENCODING__
604
749
  diagnostic :error, :invalid_assignment, nil, node.loc.expression
@@ -655,14 +800,6 @@ module Parser
655
800
  binary_op_map(lhs, eql_t, rhs))
656
801
  end
657
802
 
658
- def rassign(lhs, assoc_t, rhs)
659
- assign(rhs, assoc_t, lhs)
660
- end
661
-
662
- def multi_rassign(lhs, assoc_t, rhs)
663
- multi_assign(rhs, assoc_t, lhs)
664
- end
665
-
666
803
  #
667
804
  # Class and module definition
668
805
  #
@@ -742,8 +879,14 @@ module Parser
742
879
 
743
880
  def args(begin_t, args, end_t, check_args=true)
744
881
  args = check_duplicate_args(args) if check_args
745
- n(:args, args,
746
- collection_map(begin_t, args, end_t))
882
+ validate_no_forward_arg_after_restarg(args)
883
+
884
+ map = collection_map(begin_t, args, end_t)
885
+ if !self.class.emit_forward_arg && args.length == 1 && args[0].type == :forward_arg
886
+ n(:forward_args, [], map)
887
+ else
888
+ n(:args, args, map)
889
+ end
747
890
  end
748
891
 
749
892
  def numargs(max_numparam)
@@ -830,9 +973,12 @@ module Parser
830
973
  end
831
974
 
832
975
  def blockarg(amper_t, name_t)
833
- check_reserved_for_numparam(value(name_t), loc(name_t))
976
+ if !name_t.nil?
977
+ check_reserved_for_numparam(value(name_t), loc(name_t))
978
+ end
834
979
 
835
- n(:blockarg, [ value(name_t).to_sym ],
980
+ arg_name = name_t ? value(name_t).to_sym : nil
981
+ n(:blockarg, [ arg_name ],
836
982
  arg_prefix_map(amper_t, name_t))
837
983
  end
838
984
 
@@ -935,6 +1081,11 @@ module Parser
935
1081
  def call_method(receiver, dot_t, selector_t,
936
1082
  lparen_t=nil, args=[], rparen_t=nil)
937
1083
  type = call_type_for_dot(dot_t)
1084
+
1085
+ if self.class.emit_kwargs
1086
+ rewrite_hash_args_to_kwargs(args)
1087
+ end
1088
+
938
1089
  if selector_t.nil?
939
1090
  n(type, [ receiver, :call, *args ],
940
1091
  send_map(receiver, dot_t, nil, lparen_t, args, rparen_t))
@@ -1012,6 +1163,10 @@ module Parser
1012
1163
  end
1013
1164
 
1014
1165
  def index(receiver, lbrack_t, indexes, rbrack_t)
1166
+ if self.class.emit_kwargs
1167
+ rewrite_hash_args_to_kwargs(indexes)
1168
+ end
1169
+
1015
1170
  if self.class.emit_index
1016
1171
  n(:index, [ receiver, *indexes ],
1017
1172
  index_map(receiver, lbrack_t, rbrack_t))
@@ -1174,6 +1329,10 @@ module Parser
1174
1329
  end
1175
1330
  end
1176
1331
 
1332
+ if %i[yield super].include?(type) && self.class.emit_kwargs
1333
+ rewrite_hash_args_to_kwargs(args)
1334
+ end
1335
+
1177
1336
  n(type, args,
1178
1337
  keyword_map(keyword_t, lparen_t, args, rparen_t))
1179
1338
  end
@@ -1307,6 +1466,16 @@ module Parser
1307
1466
  binary_op_map(lhs, in_t, rhs))
1308
1467
  end
1309
1468
 
1469
+ def match_pattern(lhs, match_t, rhs)
1470
+ n(:match_pattern, [lhs, rhs],
1471
+ binary_op_map(lhs, match_t, rhs))
1472
+ end
1473
+
1474
+ def match_pattern_p(lhs, match_t, rhs)
1475
+ n(:match_pattern_p, [lhs, rhs],
1476
+ binary_op_map(lhs, match_t, rhs))
1477
+ end
1478
+
1310
1479
  def in_pattern(in_t, pattern, guard, then_t, body)
1311
1480
  children = [pattern, guard, body]
1312
1481
  n(:in_pattern, children,
@@ -1584,6 +1753,21 @@ module Parser
1584
1753
  end
1585
1754
  end
1586
1755
 
1756
+ def validate_no_forward_arg_after_restarg(args)
1757
+ restarg = nil
1758
+ forward_arg = nil
1759
+ args.each do |arg|
1760
+ case arg.type
1761
+ when :restarg then restarg = arg
1762
+ when :forward_arg then forward_arg = arg
1763
+ end
1764
+ end
1765
+
1766
+ if !forward_arg.nil? && !restarg.nil?
1767
+ diagnostic :error, :forward_arg_after_restarg, nil, forward_arg.loc.expression, [restarg.loc.expression]
1768
+ end
1769
+ end
1770
+
1587
1771
  def check_assignment_to_numparam(name, loc)
1588
1772
  # MRI < 2.7 treats numbered parameters as regular variables
1589
1773
  # and so it's allowed to perform assignments like `_1 = 42`.
@@ -1601,7 +1785,7 @@ module Parser
1601
1785
 
1602
1786
  def check_reserved_for_numparam(name, loc)
1603
1787
  # MRI < 3.0 accepts assignemnt to variables like _1
1604
- # if it's not a numbererd parameter. MRI 3.0 and newer throws an error.
1788
+ # if it's not a numbered parameter. MRI 3.0 and newer throws an error.
1605
1789
  return if @parser.version < 30
1606
1790
 
1607
1791
  if name =~ /\A_([1-9])\z/
@@ -1625,7 +1809,7 @@ module Parser
1625
1809
  end
1626
1810
 
1627
1811
  def check_lvar_name(name, loc)
1628
- if name =~ /\A[[[:lower:]]|_][[[:alnum:]]_]*\z/
1812
+ if name =~ /\A[[[:lower:]]_][[[:alnum:]]_]*\z/
1629
1813
  # OK
1630
1814
  else
1631
1815
  diagnostic :error, :lvar_name, { name: name }, loc
@@ -2106,6 +2290,20 @@ module Parser
2106
2290
  true
2107
2291
  end
2108
2292
  end
2293
+
2294
+ def rewrite_hash_args_to_kwargs(args)
2295
+ if args.any? && kwargs?(args.last)
2296
+ # foo(..., bar: baz)
2297
+ args[args.length - 1] = args[args.length - 1].updated(:kwargs)
2298
+ elsif args.length > 1 && args.last.type == :block_pass && kwargs?(args[args.length - 2])
2299
+ # foo(..., bar: baz, &blk)
2300
+ args[args.length - 2] = args[args.length - 2].updated(:kwargs)
2301
+ end
2302
+ end
2303
+
2304
+ def kwargs?(node)
2305
+ node.type == :hash && node.loc.begin.nil? && node.loc.end.nil?
2306
+ end
2109
2307
  end
2110
2308
 
2111
2309
  end
@@ -9,56 +9,41 @@ module Parser
9
9
  # + :sclass - in the singleton class body (class << obj; end)
10
10
  # + :def - in the method body (def m; end)
11
11
  # + :defs - in the singleton method body (def self.m; end)
12
+ # + :def_open_args - in the arglist of the method definition
13
+ # keep in mind that it's set **only** after reducing the first argument,
14
+ # if you need to handle the first argument check `lex_state == expr_fname`
12
15
  # + :block - in the block body (tap {})
13
16
  # + :lambda - in the lambda body (-> {})
14
17
  #
15
18
  class Context
16
- attr_reader :stack
19
+ FLAGS = %i[
20
+ in_defined
21
+ in_kwarg
22
+ in_argdef
23
+ in_def
24
+ in_class
25
+ in_block
26
+ in_lambda
27
+ ]
17
28
 
18
29
  def initialize
19
- @stack = []
20
- freeze
21
- end
22
-
23
- def push(state)
24
- @stack << state
25
- end
26
-
27
- def pop
28
- @stack.pop
30
+ reset
29
31
  end
30
32
 
31
33
  def reset
32
- @stack.clear
33
- end
34
-
35
- def in_class?
36
- @stack.last == :class
37
- end
38
-
39
- def indirectly_in_def?
40
- @stack.include?(:def) || @stack.include?(:defs)
41
- end
42
-
43
- def class_definition_allowed?
44
- def_index = stack.rindex { |item| [:def, :defs].include?(item) }
45
- sclass_index = stack.rindex(:sclass)
46
-
47
- def_index.nil? || (!sclass_index.nil? && sclass_index > def_index)
34
+ @in_defined = false
35
+ @in_kwarg = false
36
+ @in_argdef = false
37
+ @in_def = false
38
+ @in_class = false
39
+ @in_block = false
40
+ @in_lambda = false
48
41
  end
49
- alias module_definition_allowed? class_definition_allowed?
50
- alias dynamic_const_definition_allowed? class_definition_allowed?
51
42
 
52
- def in_block?
53
- @stack.last == :block
54
- end
55
-
56
- def in_lambda?
57
- @stack.last == :lambda
58
- end
43
+ attr_accessor(*FLAGS)
59
44
 
60
45
  def in_dynamic_block?
61
- in_block? || in_lambda?
46
+ in_block || in_lambda
62
47
  end
63
48
  end
64
49
  end
@@ -3,9 +3,9 @@
3
3
  module Parser
4
4
  class << self
5
5
  def warn_syntax_deviation(feature, version)
6
- warn "warning: parser/current is loading #{feature}, which recognizes"
7
- warn "warning: #{version}-compliant syntax, but you are running #{RUBY_VERSION}."
8
- warn "warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri."
6
+ warn "warning: parser/current is loading #{feature}, which recognizes" \
7
+ "#{version}-compliant syntax, but you are running #{RUBY_VERSION}.\n" \
8
+ "Please see https://github.com/whitequark/parser#compatibility-with-ruby-mri."
9
9
  end
10
10
  private :warn_syntax_deviation
11
11
  end
@@ -57,7 +57,7 @@ module Parser
57
57
  CurrentRuby = Ruby24
58
58
 
59
59
  when /^2\.5\./
60
- current_version = '2.5.8'
60
+ current_version = '2.5.9'
61
61
  if RUBY_VERSION != current_version
62
62
  warn_syntax_deviation 'parser/ruby25', current_version
63
63
  end
@@ -66,7 +66,7 @@ module Parser
66
66
  CurrentRuby = Ruby25
67
67
 
68
68
  when /^2\.6\./
69
- current_version = '2.6.6'
69
+ current_version = '2.6.9'
70
70
  if RUBY_VERSION != current_version
71
71
  warn_syntax_deviation 'parser/ruby26', current_version
72
72
  end
@@ -75,7 +75,7 @@ module Parser
75
75
  CurrentRuby = Ruby26
76
76
 
77
77
  when /^2\.7\./
78
- current_version = '2.7.2'
78
+ current_version = '2.7.5'
79
79
  if RUBY_VERSION != current_version
80
80
  warn_syntax_deviation 'parser/ruby27', current_version
81
81
  end
@@ -84,7 +84,7 @@ module Parser
84
84
  CurrentRuby = Ruby27
85
85
 
86
86
  when /^3\.0\./
87
- current_version = '3.0.0-dev'
87
+ current_version = '3.0.3'
88
88
  if RUBY_VERSION != current_version
89
89
  warn_syntax_deviation 'parser/ruby30', current_version
90
90
  end
@@ -92,10 +92,28 @@ module Parser
92
92
  require 'parser/ruby30'
93
93
  CurrentRuby = Ruby30
94
94
 
95
+ when /^3\.1\./
96
+ current_version = '3.1.1'
97
+ if RUBY_VERSION != current_version
98
+ warn_syntax_deviation 'parser/ruby31', current_version
99
+ end
100
+
101
+ require 'parser/ruby31'
102
+ CurrentRuby = Ruby31
103
+
104
+ when /^3\.2\./
105
+ current_version = '3.2.0-dev'
106
+ if RUBY_VERSION != current_version
107
+ warn_syntax_deviation 'parser/ruby32', current_version
108
+ end
109
+
110
+ require 'parser/ruby32'
111
+ CurrentRuby = Ruby32
112
+
95
113
  else # :nocov:
96
114
  # Keep this in sync with released Ruby.
97
- warn_syntax_deviation 'parser/ruby27', '2.7.x'
98
- require 'parser/ruby27'
99
- CurrentRuby = Ruby27
115
+ warn_syntax_deviation 'parser/ruby31', '3.1.x'
116
+ require 'parser/ruby31'
117
+ CurrentRuby = Ruby31
100
118
  end
101
119
  end
@@ -19,13 +19,16 @@ module Parser
19
19
  freeze
20
20
  end
21
21
 
22
+ def empty?
23
+ @stack.size == 0
24
+ end
25
+
22
26
  def push(value)
23
27
  @stack << value
24
28
  end
25
29
 
26
30
  def set(value)
27
- pop
28
- push(value)
31
+ @stack[@stack.length - 1] = value
29
32
  end
30
33
 
31
34
  def pop
@@ -38,7 +38,13 @@ module Parser
38
38
  # Prevent the following error when processing binary encoded source.
39
39
  # "\xC0".split # => ArgumentError (invalid byte sequence in UTF-8)
40
40
  lines = string.force_encoding(Encoding::BINARY).split("\\\n")
41
- lines.map! {|s| s.force_encoding(original_encoding) }
41
+ if lines.length == 1
42
+ # If the line continuation sequence was found but there is no second
43
+ # line, it was not really a line continuation and must be ignored.
44
+ lines = [string.force_encoding(original_encoding)]
45
+ else
46
+ lines.map! {|s| s.force_encoding(original_encoding) }
47
+ end
42
48
 
43
49
  if @at_line_begin
44
50
  lines_to_dedent = lines
@@ -18,7 +18,7 @@ module Parser
18
18
  def advance
19
19
  type, (val, range) = advance_before_explanation
20
20
 
21
- more = "(in-kwarg)" if @in_kwarg
21
+ more = "(in-kwarg)" if @context.in_kwarg
22
22
 
23
23
  puts decorate(range,
24
24
  Color.green("#{type} #{val.inspect}"),