parser 2.7.1.1 → 3.0.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/lib/parser.rb +1 -0
  3. data/lib/parser/all.rb +2 -0
  4. data/lib/parser/ast/processor.rb +5 -0
  5. data/lib/parser/base.rb +7 -5
  6. data/lib/parser/builders/default.rb +263 -23
  7. data/lib/parser/context.rb +5 -0
  8. data/lib/parser/current.rb +24 -6
  9. data/lib/parser/current_arg_stack.rb +5 -2
  10. data/lib/parser/diagnostic.rb +1 -1
  11. data/lib/parser/diagnostic/engine.rb +1 -2
  12. data/lib/parser/lexer.rb +887 -803
  13. data/lib/parser/macruby.rb +2214 -2189
  14. data/lib/parser/max_numparam_stack.rb +13 -5
  15. data/lib/parser/messages.rb +18 -0
  16. data/lib/parser/meta.rb +6 -5
  17. data/lib/parser/ruby18.rb +9 -3
  18. data/lib/parser/ruby19.rb +2297 -2289
  19. data/lib/parser/ruby20.rb +2413 -2397
  20. data/lib/parser/ruby21.rb +2419 -2411
  21. data/lib/parser/ruby22.rb +2468 -2460
  22. data/lib/parser/ruby23.rb +2452 -2452
  23. data/lib/parser/ruby24.rb +2435 -2430
  24. data/lib/parser/ruby25.rb +2220 -2214
  25. data/lib/parser/ruby26.rb +2220 -2214
  26. data/lib/parser/ruby27.rb +3715 -3615
  27. data/lib/parser/ruby28.rb +8047 -0
  28. data/lib/parser/ruby30.rb +8060 -0
  29. data/lib/parser/ruby31.rb +8226 -0
  30. data/lib/parser/rubymotion.rb +2190 -2182
  31. data/lib/parser/runner.rb +31 -2
  32. data/lib/parser/runner/ruby_rewrite.rb +2 -2
  33. data/lib/parser/source/buffer.rb +53 -28
  34. data/lib/parser/source/comment.rb +14 -1
  35. data/lib/parser/source/comment/associator.rb +31 -8
  36. data/lib/parser/source/map/method_definition.rb +25 -0
  37. data/lib/parser/source/range.rb +10 -3
  38. data/lib/parser/source/tree_rewriter.rb +100 -10
  39. data/lib/parser/source/tree_rewriter/action.rb +114 -21
  40. data/lib/parser/static_environment.rb +4 -0
  41. data/lib/parser/tree_rewriter.rb +1 -2
  42. data/lib/parser/variables_stack.rb +4 -0
  43. data/lib/parser/version.rb +1 -1
  44. data/parser.gemspec +3 -18
  45. metadata +17 -98
  46. data/.gitignore +0 -33
  47. data/.travis.yml +0 -42
  48. data/.yardopts +0 -21
  49. data/CHANGELOG.md +0 -1075
  50. data/CONTRIBUTING.md +0 -17
  51. data/Gemfile +0 -10
  52. data/README.md +0 -309
  53. data/Rakefile +0 -166
  54. data/ci/run_rubocop_specs +0 -14
  55. data/doc/AST_FORMAT.md +0 -2180
  56. data/doc/CUSTOMIZATION.md +0 -37
  57. data/doc/INTERNALS.md +0 -21
  58. data/doc/css/.gitkeep +0 -0
  59. data/doc/css/common.css +0 -68
  60. data/lib/parser/lexer.rl +0 -2536
  61. data/lib/parser/macruby.y +0 -2198
  62. data/lib/parser/ruby18.y +0 -1934
  63. data/lib/parser/ruby19.y +0 -2175
  64. data/lib/parser/ruby20.y +0 -2353
  65. data/lib/parser/ruby21.y +0 -2357
  66. data/lib/parser/ruby22.y +0 -2364
  67. data/lib/parser/ruby23.y +0 -2370
  68. data/lib/parser/ruby24.y +0 -2408
  69. data/lib/parser/ruby25.y +0 -2405
  70. data/lib/parser/ruby26.y +0 -2413
  71. data/lib/parser/ruby27.y +0 -2941
  72. data/lib/parser/rubymotion.y +0 -2182
  73. data/test/bug_163/fixtures/input.rb +0 -5
  74. data/test/bug_163/fixtures/output.rb +0 -5
  75. data/test/bug_163/rewriter.rb +0 -20
  76. data/test/helper.rb +0 -60
  77. data/test/parse_helper.rb +0 -319
  78. data/test/racc_coverage_helper.rb +0 -133
  79. data/test/test_base.rb +0 -31
  80. data/test/test_current.rb +0 -29
  81. data/test/test_diagnostic.rb +0 -96
  82. data/test/test_diagnostic_engine.rb +0 -62
  83. data/test/test_encoding.rb +0 -99
  84. data/test/test_lexer.rb +0 -3608
  85. data/test/test_lexer_stack_state.rb +0 -78
  86. data/test/test_parse_helper.rb +0 -80
  87. data/test/test_parser.rb +0 -9430
  88. data/test/test_runner_parse.rb +0 -35
  89. data/test/test_runner_rewrite.rb +0 -47
  90. data/test/test_source_buffer.rb +0 -162
  91. data/test/test_source_comment.rb +0 -36
  92. data/test/test_source_comment_associator.rb +0 -367
  93. data/test/test_source_map.rb +0 -15
  94. data/test/test_source_range.rb +0 -187
  95. data/test/test_source_rewriter.rb +0 -541
  96. data/test/test_source_rewriter_action.rb +0 -46
  97. data/test/test_source_tree_rewriter.rb +0 -253
  98. data/test/test_static_environment.rb +0 -45
  99. data/test/using_tree_rewriter/fixtures/input.rb +0 -3
  100. data/test/using_tree_rewriter/fixtures/output.rb +0 -3
  101. data/test/using_tree_rewriter/using_tree_rewriter.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb7c9797808fcd8920ef34ccce6dae7f416d0fe3084a863fa3fec7fa30b086fc
4
- data.tar.gz: 828a937688a35e277c7d435197ca2d023458de366a8e94fbaa67bdd6d3a04145
3
+ metadata.gz: 0b1e9fbbc406eb2665aa17f066247e6584182ebe365b3f1d2ace35628f3f12c6
4
+ data.tar.gz: 8522d4ff0b299c14cb386156a6f04e7d7828bf8c33ed1331a22829ff873312c1
5
5
  SHA512:
6
- metadata.gz: 679bc103f3d8b2663a1ec2de6c3acac41c90c1d738b40bf4b5ed945b8e3f51e22359caa0789e55009f3bd2c45ac832d00182db9ba9be1f43b18e6fe0e0508278
7
- data.tar.gz: b4f4d29766e23ca406644fb578e2134f28a9983d765d4aa45117dcb5a9ee012f27c2b8b65eccf11b7e3818b1543a62cc0483aa510a51352bc2260ad0fd650acd
6
+ metadata.gz: 5871c263e07cdd6bf88f661419578977f9ddd9e01e1631bab14ff7fb485f466a7b8dacebcda30514d7d1f3c6746b8d2e1f6c6feb7de57a899a1cacfb728c05af
7
+ data.tar.gz: 4decb43386adfd5be04356d3c9667c1880fa974ad14bc190312bf25a379fad92e4353b0812bcb8810e1863892f14a0daaf6d0c5d31523e2a45a1bb35f65c4ab0
data/lib/parser.rb CHANGED
@@ -46,6 +46,7 @@ module Parser
46
46
  require 'parser/source/map/variable'
47
47
  require 'parser/source/map/keyword'
48
48
  require 'parser/source/map/definition'
49
+ require 'parser/source/map/method_definition'
49
50
  require 'parser/source/map/send'
50
51
  require 'parser/source/map/index'
51
52
  require 'parser/source/map/condition'
data/lib/parser/all.rb CHANGED
@@ -10,3 +10,5 @@ require 'parser/ruby24'
10
10
  require 'parser/ruby25'
11
11
  require 'parser/ruby26'
12
12
  require 'parser/ruby27'
13
+ require 'parser/ruby30'
14
+ require 'parser/ruby31'
@@ -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
 
@@ -124,6 +125,7 @@ module Parser
124
125
  alias on_kwarg process_argument_node
125
126
  alias on_kwoptarg process_argument_node
126
127
  alias on_kwrestarg process_argument_node
128
+ alias on_forward_arg process_argument_node
127
129
 
128
130
  def on_procarg0(node)
129
131
  if node.children[0].is_a?(Symbol)
@@ -238,6 +240,8 @@ module Parser
238
240
 
239
241
  alias on_case_match process_regular_node
240
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
241
245
  alias on_in_pattern process_regular_node
242
246
  alias on_if_guard process_regular_node
243
247
  alias on_unless_guard process_regular_node
@@ -250,6 +254,7 @@ module Parser
250
254
  alias on_array_pattern_with_tail process_regular_node
251
255
  alias on_hash_pattern process_regular_node
252
256
  alias on_const_pattern process_regular_node
257
+ alias on_find_pattern process_regular_node
253
258
 
254
259
  # @private
255
260
  def process_variable_node(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
@@ -177,16 +178,16 @@ module Parser
177
178
  end
178
179
 
179
180
  ##
180
- # Parses a source buffer and returns the AST.
181
+ # Parses a source buffer and returns the AST, or `nil` in case of a non fatal error.
181
182
  #
182
183
  # @param [Parser::Source::Buffer] source_buffer The source buffer to parse.
183
- # @return [Parser::AST::Node]
184
+ # @return [Parser::AST::Node, nil]
184
185
  #
185
186
  def parse(source_buffer)
186
187
  @lexer.source_buffer = source_buffer
187
188
  @source_buffer = source_buffer
188
189
 
189
- do_parse
190
+ do_parse || nil # Force `false` to `nil`, see https://github.com/ruby/racc/pull/136
190
191
  ensure
191
192
  # Don't keep references to the source file.
192
193
  @source_buffer = nil
@@ -210,8 +211,9 @@ module Parser
210
211
 
211
212
  ##
212
213
  # Parses a source buffer and returns the AST, the source code comments,
213
- # and the tokens emitted by the lexer. If `recover` is true and a fatal
214
- # {SyntaxError} is encountered, `nil` is returned instead of the AST, and
214
+ # and the tokens emitted by the lexer. In case of a fatal error, a {SyntaxError}
215
+ # is raised, unless `recover` is true. In case of an error
216
+ # (non-fatal or recovered), `nil` is returned instead of the AST, and
215
217
  # comments as well as tokens are only returned up to the location of
216
218
  # the error.
217
219
  #
@@ -80,6 +80,8 @@ module Parser
80
80
  attr_accessor :emit_index
81
81
  end
82
82
 
83
+ @emit_index = false
84
+
83
85
  class << self
84
86
  ##
85
87
  # AST compatibility attribute; causes a single non-mlhs
@@ -95,7 +97,113 @@ module Parser
95
97
  attr_accessor :emit_arg_inside_procarg0
96
98
  end
97
99
 
98
- @emit_index = false
100
+ @emit_arg_inside_procarg0 = false
101
+
102
+ class << self
103
+ ##
104
+ # AST compatibility attribute; arguments forwarding initially
105
+ # didn't have support for leading arguments
106
+ # (i.e. `def m(a, ...); end` was a syntax error). However, Ruby 3.0
107
+ # added support for any number of arguments in front of the `...`.
108
+ #
109
+ # If set to false (the default):
110
+ # 1. `def m(...) end` is emitted as
111
+ # s(:def, :m, s(:forward_args), nil)
112
+ # 2. `def m(a, b, ...) end` is emitted as
113
+ # s(:def, :m,
114
+ # s(:args, s(:arg, :a), s(:arg, :b), s(:forward_arg)))
115
+ #
116
+ # If set to true it uses a single format:
117
+ # 1. `def m(...) end` is emitted as
118
+ # s(:def, :m, s(:args, s(:forward_arg)))
119
+ # 2. `def m(a, b, ...) end` is emitted as
120
+ # s(:def, :m, s(:args, s(:arg, :a), s(:arg, :b), s(:forward_arg)))
121
+ #
122
+ # It does't matter that much on 2.7 (because there can't be any leading arguments),
123
+ # but on 3.0 it should be better enabled to use a single AST format.
124
+ #
125
+ # @return [Boolean]
126
+ attr_accessor :emit_forward_arg
127
+ end
128
+
129
+ @emit_forward_arg = false
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
+ # (hash
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
99
207
 
100
208
  class << self
101
209
  ##
@@ -106,6 +214,9 @@ module Parser
106
214
  @emit_encoding = true
107
215
  @emit_index = true
108
216
  @emit_arg_inside_procarg0 = true
217
+ @emit_forward_arg = true
218
+ @emit_kwargs = true
219
+ @emit_match_pattern = true
109
220
  end
110
221
  end
111
222
 
@@ -278,18 +389,23 @@ module Parser
278
389
  if !dedent_level.nil?
279
390
  dedenter = Lexer::Dedenter.new(dedent_level)
280
391
 
281
- if node.type == :str
392
+ case node.type
393
+ when :str
282
394
  str = node.children.first
283
395
  dedenter.dedent(str)
284
- elsif node.type == :dstr || node.type == :xstr
285
- node.children.each do |str_node|
396
+ when :dstr, :xstr
397
+ children = node.children.map do |str_node|
286
398
  if str_node.type == :str
287
399
  str = str_node.children.first
288
400
  dedenter.dedent(str)
401
+ next nil if str.empty?
289
402
  else
290
403
  dedenter.interrupt
291
404
  end
405
+ str_node
292
406
  end
407
+
408
+ node = node.updated(nil, children.compact)
293
409
  end
294
410
  end
295
411
 
@@ -557,7 +673,11 @@ module Parser
557
673
  when :ident
558
674
  name, = *node
559
675
 
560
- check_assignment_to_numparam(node)
676
+ var_name = node.children[0].to_s
677
+ name_loc = node.loc.expression
678
+
679
+ check_assignment_to_numparam(var_name, name_loc)
680
+ check_reserved_for_numparam(var_name, name_loc)
561
681
 
562
682
  @parser.static_env.declare(name)
563
683
 
@@ -648,23 +768,38 @@ module Parser
648
768
 
649
769
  def def_method(def_t, name_t, args,
650
770
  body, end_t)
771
+ check_reserved_for_numparam(value(name_t), loc(name_t))
772
+
651
773
  n(:def, [ value(name_t).to_sym, args, body ],
652
774
  definition_map(def_t, nil, name_t, end_t))
653
775
  end
654
776
 
777
+ def def_endless_method(def_t, name_t, args,
778
+ assignment_t, body)
779
+ check_reserved_for_numparam(value(name_t), loc(name_t))
780
+
781
+ n(:def, [ value(name_t).to_sym, args, body ],
782
+ endless_definition_map(def_t, nil, name_t, assignment_t, body))
783
+ end
784
+
655
785
  def def_singleton(def_t, definee, dot_t,
656
786
  name_t, args,
657
787
  body, end_t)
658
- case definee.type
659
- when :int, :str, :dstr, :sym, :dsym,
660
- :regexp, :array, :hash
788
+ validate_definee(definee)
789
+ check_reserved_for_numparam(value(name_t), loc(name_t))
661
790
 
662
- diagnostic :error, :singleton_literal, nil, definee.loc.expression
791
+ n(:defs, [ definee, value(name_t).to_sym, args, body ],
792
+ definition_map(def_t, dot_t, name_t, end_t))
793
+ end
663
794
 
664
- else
665
- n(:defs, [ definee, value(name_t).to_sym, args, body ],
666
- definition_map(def_t, dot_t, name_t, end_t))
667
- end
795
+ def def_endless_singleton(def_t, definee, dot_t,
796
+ name_t, args,
797
+ assignment_t, body)
798
+ validate_definee(definee)
799
+ check_reserved_for_numparam(value(name_t), loc(name_t))
800
+
801
+ n(:defs, [ definee, value(name_t).to_sym, args, body ],
802
+ endless_definition_map(def_t, dot_t, name_t, assignment_t, body))
668
803
  end
669
804
 
670
805
  def undef_method(undef_t, names)
@@ -691,16 +826,30 @@ module Parser
691
826
  n(:numargs, [ max_numparam ], nil)
692
827
  end
693
828
 
694
- def forward_args(begin_t, dots_t, end_t)
695
- n(:forward_args, [], collection_map(begin_t, token_map(dots_t), end_t))
829
+ def forward_only_args(begin_t, dots_t, end_t)
830
+ if self.class.emit_forward_arg
831
+ arg = forward_arg(dots_t)
832
+ n(:args, [ arg ],
833
+ collection_map(begin_t, [ arg ], end_t))
834
+ else
835
+ n(:forward_args, [], collection_map(begin_t, token_map(dots_t), end_t))
836
+ end
837
+ end
838
+
839
+ def forward_arg(dots_t)
840
+ n(:forward_arg, [], token_map(dots_t))
696
841
  end
697
842
 
698
843
  def arg(name_t)
844
+ check_reserved_for_numparam(value(name_t), loc(name_t))
845
+
699
846
  n(:arg, [ value(name_t).to_sym ],
700
847
  variable_map(name_t))
701
848
  end
702
849
 
703
850
  def optarg(name_t, eql_t, value)
851
+ check_reserved_for_numparam(value(name_t), loc(name_t))
852
+
704
853
  n(:optarg, [ value(name_t).to_sym, value ],
705
854
  variable_map(name_t).
706
855
  with_operator(loc(eql_t)).
@@ -709,6 +858,7 @@ module Parser
709
858
 
710
859
  def restarg(star_t, name_t=nil)
711
860
  if name_t
861
+ check_reserved_for_numparam(value(name_t), loc(name_t))
712
862
  n(:restarg, [ value(name_t).to_sym ],
713
863
  arg_prefix_map(star_t, name_t))
714
864
  else
@@ -718,17 +868,23 @@ module Parser
718
868
  end
719
869
 
720
870
  def kwarg(name_t)
871
+ check_reserved_for_numparam(value(name_t), loc(name_t))
872
+
721
873
  n(:kwarg, [ value(name_t).to_sym ],
722
874
  kwarg_map(name_t))
723
875
  end
724
876
 
725
877
  def kwoptarg(name_t, value)
878
+ check_reserved_for_numparam(value(name_t), loc(name_t))
879
+
726
880
  n(:kwoptarg, [ value(name_t).to_sym, value ],
727
881
  kwarg_map(name_t, value))
728
882
  end
729
883
 
730
884
  def kwrestarg(dstar_t, name_t=nil)
731
885
  if name_t
886
+ check_reserved_for_numparam(value(name_t), loc(name_t))
887
+
732
888
  n(:kwrestarg, [ value(name_t).to_sym ],
733
889
  arg_prefix_map(dstar_t, name_t))
734
890
  else
@@ -743,11 +899,15 @@ module Parser
743
899
  end
744
900
 
745
901
  def shadowarg(name_t)
902
+ check_reserved_for_numparam(value(name_t), loc(name_t))
903
+
746
904
  n(:shadowarg, [ value(name_t).to_sym ],
747
905
  variable_map(name_t))
748
906
  end
749
907
 
750
908
  def blockarg(amper_t, name_t)
909
+ check_reserved_for_numparam(value(name_t), loc(name_t))
910
+
751
911
  n(:blockarg, [ value(name_t).to_sym ],
752
912
  arg_prefix_map(amper_t, name_t))
753
913
  end
@@ -851,6 +1011,11 @@ module Parser
851
1011
  def call_method(receiver, dot_t, selector_t,
852
1012
  lparen_t=nil, args=[], rparen_t=nil)
853
1013
  type = call_type_for_dot(dot_t)
1014
+
1015
+ if self.class.emit_kwargs
1016
+ rewrite_hash_args_to_kwargs(args)
1017
+ end
1018
+
854
1019
  if selector_t.nil?
855
1020
  n(type, [ receiver, :call, *args ],
856
1021
  send_map(receiver, dot_t, nil, lparen_t, args, rparen_t))
@@ -928,6 +1093,10 @@ module Parser
928
1093
  end
929
1094
 
930
1095
  def index(receiver, lbrack_t, indexes, rbrack_t)
1096
+ if self.class.emit_kwargs
1097
+ rewrite_hash_args_to_kwargs(indexes)
1098
+ end
1099
+
931
1100
  if self.class.emit_index
932
1101
  n(:index, [ receiver, *indexes ],
933
1102
  index_map(receiver, lbrack_t, rbrack_t))
@@ -1090,6 +1259,10 @@ module Parser
1090
1259
  end
1091
1260
  end
1092
1261
 
1262
+ if %i[yield super].include?(type) && self.class.emit_kwargs
1263
+ rewrite_hash_args_to_kwargs(args)
1264
+ end
1265
+
1093
1266
  n(type, args,
1094
1267
  keyword_map(keyword_t, lparen_t, args, rparen_t))
1095
1268
  end
@@ -1223,6 +1396,16 @@ module Parser
1223
1396
  binary_op_map(lhs, in_t, rhs))
1224
1397
  end
1225
1398
 
1399
+ def match_pattern(lhs, match_t, rhs)
1400
+ n(:match_pattern, [lhs, rhs],
1401
+ binary_op_map(lhs, match_t, rhs))
1402
+ end
1403
+
1404
+ def match_pattern_p(lhs, match_t, rhs)
1405
+ n(:match_pattern_p, [lhs, rhs],
1406
+ binary_op_map(lhs, match_t, rhs))
1407
+ end
1408
+
1226
1409
  def in_pattern(in_t, pattern, guard, then_t, body)
1227
1410
  children = [pattern, guard, body]
1228
1411
  n(:in_pattern, children,
@@ -1239,8 +1422,10 @@ module Parser
1239
1422
 
1240
1423
  def match_var(name_t)
1241
1424
  name = value(name_t).to_sym
1425
+ name_l = loc(name_t)
1242
1426
 
1243
- check_duplicate_pattern_variable(name, loc(name_t))
1427
+ check_lvar_name(name, name_l)
1428
+ check_duplicate_pattern_variable(name, name_l)
1244
1429
  @parser.static_env.declare(name)
1245
1430
 
1246
1431
  n(:match_var, [ name ],
@@ -1253,6 +1438,7 @@ module Parser
1253
1438
  expr_l = loc(name_t)
1254
1439
  name_l = expr_l.adjust(end_pos: -1)
1255
1440
 
1441
+ check_lvar_name(name, name_l)
1256
1442
  check_duplicate_pattern_variable(name, name_l)
1257
1443
  @parser.static_env.declare(name)
1258
1444
 
@@ -1293,6 +1479,9 @@ module Parser
1293
1479
  Source::Map::Variable.new(name_l, expr_l))
1294
1480
  when :begin
1295
1481
  match_hash_var_from_str(begin_t, string.children, end_t)
1482
+ else
1483
+ # we only can get here if there is an interpolation, e.g., ``in "#{ a }":`
1484
+ diagnostic :error, :pm_interp_in_var_name, nil, loc(begin_t).join(loc(end_t))
1296
1485
  end
1297
1486
  end
1298
1487
 
@@ -1334,6 +1523,11 @@ module Parser
1334
1523
  collection_map(lbrack_t, elements, rbrack_t))
1335
1524
  end
1336
1525
 
1526
+ def find_pattern(lbrack_t, elements, rbrack_t)
1527
+ n(:find_pattern, elements,
1528
+ collection_map(lbrack_t, elements, rbrack_t))
1529
+ end
1530
+
1337
1531
  def match_with_trailing_comma(match, comma_t)
1338
1532
  n(:match_with_trailing_comma, [ match ], expr_map(match.loc.expression.join(loc(comma_t))))
1339
1533
  end
@@ -1489,8 +1683,10 @@ module Parser
1489
1683
  end
1490
1684
  end
1491
1685
 
1492
- def check_assignment_to_numparam(node)
1493
- name = node.children[0].to_s
1686
+ def check_assignment_to_numparam(name, loc)
1687
+ # MRI < 2.7 treats numbered parameters as regular variables
1688
+ # and so it's allowed to perform assignments like `_1 = 42`.
1689
+ return if @parser.version < 27
1494
1690
 
1495
1691
  assigning_to_numparam =
1496
1692
  @parser.context.in_dynamic_block? &&
@@ -1498,7 +1694,17 @@ module Parser
1498
1694
  @parser.max_numparam_stack.has_numparams?
1499
1695
 
1500
1696
  if assigning_to_numparam
1501
- diagnostic :error, :cant_assign_to_numparam, { :name => name }, node.loc.expression
1697
+ diagnostic :error, :cant_assign_to_numparam, { :name => name }, loc
1698
+ end
1699
+ end
1700
+
1701
+ def check_reserved_for_numparam(name, loc)
1702
+ # MRI < 3.0 accepts assignemnt to variables like _1
1703
+ # if it's not a numbered parameter. MRI 3.0 and newer throws an error.
1704
+ return if @parser.version < 30
1705
+
1706
+ if name =~ /\A_([1-9])\z/
1707
+ diagnostic :error, :reserved_for_numparam, { :name => name }, loc
1502
1708
  end
1503
1709
  end
1504
1710
 
@@ -1518,7 +1724,7 @@ module Parser
1518
1724
  end
1519
1725
 
1520
1726
  def check_lvar_name(name, loc)
1521
- if name =~ /\A[[[:lower:]]|_][[[:alnum:]]_]*\z/
1727
+ if name =~ /\A[[[:lower:]]_][[[:alnum:]]_]*\z/
1522
1728
  # OK
1523
1729
  else
1524
1730
  diagnostic :error, :lvar_name, { name: name }, loc
@@ -1732,9 +1938,17 @@ module Parser
1732
1938
  end
1733
1939
 
1734
1940
  def definition_map(keyword_t, operator_t, name_t, end_t)
1735
- Source::Map::Definition.new(loc(keyword_t),
1736
- loc(operator_t), loc(name_t),
1737
- loc(end_t))
1941
+ Source::Map::MethodDefinition.new(loc(keyword_t),
1942
+ loc(operator_t), loc(name_t),
1943
+ loc(end_t), nil, nil)
1944
+ end
1945
+
1946
+ def endless_definition_map(keyword_t, operator_t, name_t, assignment_t, body_e)
1947
+ body_l = body_e.loc.expression
1948
+
1949
+ Source::Map::MethodDefinition.new(loc(keyword_t),
1950
+ loc(operator_t), loc(name_t), nil,
1951
+ loc(assignment_t), body_l)
1738
1952
  end
1739
1953
 
1740
1954
  def send_map(receiver_e, dot_t, selector_t, begin_t=nil, args=[], end_t=nil)
@@ -1979,6 +2193,32 @@ module Parser
1979
2193
  @parser.send :yyerror
1980
2194
  end
1981
2195
  end
2196
+
2197
+ def validate_definee(definee)
2198
+ case definee.type
2199
+ when :int, :str, :dstr, :sym, :dsym,
2200
+ :regexp, :array, :hash
2201
+
2202
+ diagnostic :error, :singleton_literal, nil, definee.loc.expression
2203
+ false
2204
+ else
2205
+ true
2206
+ end
2207
+ end
2208
+
2209
+ def rewrite_hash_args_to_kwargs(args)
2210
+ if args.any? && kwargs?(args.last)
2211
+ # foo(..., bar: baz)
2212
+ args[args.length - 1] = args[args.length - 1].updated(:kwargs)
2213
+ elsif args.length > 1 && args.last.type == :block_pass && kwargs?(args[args.length - 2])
2214
+ # foo(..., bar: baz, &blk)
2215
+ args[args.length - 2] = args[args.length - 2].updated(:kwargs)
2216
+ end
2217
+ end
2218
+
2219
+ def kwargs?(node)
2220
+ node.type == :hash && node.loc.begin.nil? && node.loc.end.nil?
2221
+ end
1982
2222
  end
1983
2223
 
1984
2224
  end