parser 2.5.1.0 → 3.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/lib/parser.rb +4 -0
  3. data/lib/parser/all.rb +3 -0
  4. data/lib/parser/ast/processor.rb +49 -1
  5. data/lib/parser/base.rb +30 -6
  6. data/lib/parser/builders/default.rb +586 -29
  7. data/lib/parser/context.rb +17 -0
  8. data/lib/parser/current.rb +34 -7
  9. data/lib/parser/current_arg_stack.rb +46 -0
  10. data/lib/parser/diagnostic.rb +1 -1
  11. data/lib/parser/diagnostic/engine.rb +1 -2
  12. data/lib/parser/lexer.rb +23780 -0
  13. data/lib/parser/lexer/dedenter.rb +52 -49
  14. data/lib/parser/lexer/literal.rb +4 -0
  15. data/lib/parser/lexer/stack_state.rb +4 -0
  16. data/lib/parser/macruby.rb +6149 -0
  17. data/lib/parser/max_numparam_stack.rb +56 -0
  18. data/lib/parser/messages.rb +74 -44
  19. data/lib/parser/meta.rb +13 -3
  20. data/lib/parser/ruby18.rb +5667 -0
  21. data/lib/parser/ruby19.rb +6092 -0
  22. data/lib/parser/ruby20.rb +6527 -0
  23. data/lib/parser/ruby21.rb +6578 -0
  24. data/lib/parser/ruby22.rb +6613 -0
  25. data/lib/parser/ruby23.rb +6624 -0
  26. data/lib/parser/ruby24.rb +6694 -0
  27. data/lib/parser/ruby25.rb +6662 -0
  28. data/lib/parser/ruby26.rb +6676 -0
  29. data/lib/parser/ruby27.rb +7862 -0
  30. data/lib/parser/ruby28.rb +8047 -0
  31. data/lib/parser/ruby30.rb +8060 -0
  32. data/lib/parser/ruby31.rb +8075 -0
  33. data/lib/parser/rubymotion.rb +6086 -0
  34. data/lib/parser/runner.rb +36 -2
  35. data/lib/parser/runner/ruby_parse.rb +2 -2
  36. data/lib/parser/runner/ruby_rewrite.rb +2 -2
  37. data/lib/parser/source/buffer.rb +54 -29
  38. data/lib/parser/source/comment.rb +18 -5
  39. data/lib/parser/source/comment/associator.rb +34 -11
  40. data/lib/parser/source/map.rb +1 -1
  41. data/lib/parser/source/map/method_definition.rb +25 -0
  42. data/lib/parser/source/range.rb +20 -4
  43. data/lib/parser/source/tree_rewriter.rb +146 -16
  44. data/lib/parser/source/tree_rewriter/action.rb +137 -28
  45. data/lib/parser/static_environment.rb +14 -0
  46. data/lib/parser/tree_rewriter.rb +3 -3
  47. data/lib/parser/variables_stack.rb +36 -0
  48. data/lib/parser/version.rb +1 -1
  49. data/parser.gemspec +13 -21
  50. metadata +34 -98
  51. data/.gitignore +0 -32
  52. data/.travis.yml +0 -21
  53. data/.yardopts +0 -21
  54. data/CHANGELOG.md +0 -909
  55. data/CONTRIBUTING.md +0 -17
  56. data/Gemfile +0 -10
  57. data/README.md +0 -301
  58. data/Rakefile +0 -165
  59. data/doc/AST_FORMAT.md +0 -1718
  60. data/doc/CUSTOMIZATION.md +0 -37
  61. data/doc/INTERNALS.md +0 -21
  62. data/doc/css/.gitkeep +0 -0
  63. data/doc/css/common.css +0 -68
  64. data/lib/parser/lexer.rl +0 -2376
  65. data/lib/parser/macruby.y +0 -2198
  66. data/lib/parser/ruby18.y +0 -1934
  67. data/lib/parser/ruby19.y +0 -2175
  68. data/lib/parser/ruby20.y +0 -2353
  69. data/lib/parser/ruby21.y +0 -2357
  70. data/lib/parser/ruby22.y +0 -2364
  71. data/lib/parser/ruby23.y +0 -2370
  72. data/lib/parser/ruby24.y +0 -2395
  73. data/lib/parser/ruby25.y +0 -2392
  74. data/lib/parser/ruby26.y +0 -2392
  75. data/lib/parser/rubymotion.y +0 -2182
  76. data/test/bug_163/fixtures/input.rb +0 -5
  77. data/test/bug_163/fixtures/output.rb +0 -5
  78. data/test/bug_163/rewriter.rb +0 -20
  79. data/test/helper.rb +0 -52
  80. data/test/parse_helper.rb +0 -315
  81. data/test/racc_coverage_helper.rb +0 -133
  82. data/test/test_base.rb +0 -31
  83. data/test/test_current.rb +0 -27
  84. data/test/test_diagnostic.rb +0 -96
  85. data/test/test_diagnostic_engine.rb +0 -62
  86. data/test/test_encoding.rb +0 -99
  87. data/test/test_lexer.rb +0 -3537
  88. data/test/test_lexer_stack_state.rb +0 -78
  89. data/test/test_parse_helper.rb +0 -80
  90. data/test/test_parser.rb +0 -6968
  91. data/test/test_runner_rewrite.rb +0 -47
  92. data/test/test_source_buffer.rb +0 -162
  93. data/test/test_source_comment.rb +0 -36
  94. data/test/test_source_comment_associator.rb +0 -367
  95. data/test/test_source_map.rb +0 -15
  96. data/test/test_source_range.rb +0 -172
  97. data/test/test_source_rewriter.rb +0 -541
  98. data/test/test_source_rewriter_action.rb +0 -46
  99. data/test/test_source_tree_rewriter.rb +0 -173
  100. data/test/test_static_environment.rb +0 -45
  101. data/test/using_tree_rewriter/fixtures/input.rb +0 -3
  102. data/test/using_tree_rewriter/fixtures/output.rb +0 -3
  103. 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: 3d4445244332537a2a91b8b6f6a2d35b750ffb1dbc3869c91f1a4de840a89600
4
- data.tar.gz: 800b3adeae6c64459f2b604c3c4b935eb728018bfe4136debae16c96df0384bf
3
+ metadata.gz: 6c85d02ca4bf90dcc1d33424dd323ae54b9e60581a6473012e950f82ce15d28e
4
+ data.tar.gz: ebe2c4eb02779209b8a34e051d717a6af84da81fadfeff79d9eab194ecf95d93
5
5
  SHA512:
6
- metadata.gz: 99138e99f88e016a3da7cac3fe45c492068fe5fa5ecb6df640ade2f6890c05fdc2aff096d255e0fd57f75f4e5c3300c15f16fa9be177e9fdc56711c6e6ea29ac
7
- data.tar.gz: 71504873b9c22a3adfd0d0ee304e69e3317b93d52a7e2506c6225e2c768cea2ddd9bf1a874a04c8b0706047f78dc97f49b7841307f64198678f03a3336ad2675
6
+ metadata.gz: 173d8e1bbbbbf0ef06d06f1ea59dc41ca49c8b39c6931523dc70bac259eee1e9c9263730d560afe106c70f88f01ae14edc77862d20a4924a674131ca90b9807c
7
+ data.tar.gz: 1698922a4ff14bf3e826f10b826a8a8e0c3aaf7fefd20669a4666c0ed6ea8a3ed405acbb28fe90985510dedff6414c0330d5affa4639840178bf20dee561e4a9
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'
@@ -73,6 +74,9 @@ module Parser
73
74
  end
74
75
 
75
76
  require 'parser/context'
77
+ require 'parser/max_numparam_stack'
78
+ require 'parser/current_arg_stack'
79
+ require 'parser/variables_stack'
76
80
 
77
81
  require 'parser/base'
78
82
 
data/lib/parser/all.rb CHANGED
@@ -9,3 +9,6 @@ require 'parser/ruby23'
9
9
  require 'parser/ruby24'
10
10
  require 'parser/ruby25'
11
11
  require 'parser/ruby26'
12
+ require 'parser/ruby27'
13
+ require 'parser/ruby30'
14
+ require 'parser/ruby31'
@@ -16,9 +16,11 @@ module Parser
16
16
  alias on_regexp process_regular_node
17
17
  alias on_xstr process_regular_node
18
18
  alias on_splat process_regular_node
19
+ alias on_kwsplat process_regular_node
19
20
  alias on_array process_regular_node
20
21
  alias on_pair process_regular_node
21
22
  alias on_hash process_regular_node
23
+ alias on_kwargs process_regular_node
22
24
  alias on_irange process_regular_node
23
25
  alias on_erange process_regular_node
24
26
 
@@ -123,7 +125,23 @@ module Parser
123
125
  alias on_kwarg process_argument_node
124
126
  alias on_kwoptarg process_argument_node
125
127
  alias on_kwrestarg process_argument_node
126
- alias on_procarg0 process_argument_node
128
+ alias on_forward_arg process_argument_node
129
+
130
+ def on_procarg0(node)
131
+ if node.children[0].is_a?(Symbol)
132
+ # This branch gets executed when the builder
133
+ # is not configured to emit and 'arg' inside 'procarg0', i.e. when
134
+ # Parser::Builders::Default.emit_arg_inside_procarg0
135
+ # is set to false.
136
+ #
137
+ # If this flag is set to true this branch is unreachable.
138
+ # s(:procarg0, :a)
139
+ on_argument(node)
140
+ else
141
+ # s(:procarg0, s(:arg, :a), s(:arg, :b))
142
+ process_regular_node(node)
143
+ end
144
+ end
127
145
 
128
146
  alias on_arg_expr process_regular_node
129
147
  alias on_restarg_expr process_regular_node
@@ -172,6 +190,14 @@ module Parser
172
190
  alias on_block process_regular_node
173
191
  alias on_lambda process_regular_node
174
192
 
193
+ def on_numblock(node)
194
+ method_call, max_numparam, body = *node
195
+
196
+ node.updated(nil, [
197
+ process(method_call), max_numparam, process(body)
198
+ ])
199
+ end
200
+
175
201
  alias on_while process_regular_node
176
202
  alias on_while_post process_regular_node
177
203
  alias on_until process_regular_node
@@ -212,6 +238,24 @@ module Parser
212
238
  alias on_preexe process_regular_node
213
239
  alias on_postexe process_regular_node
214
240
 
241
+ alias on_case_match process_regular_node
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
245
+ alias on_in_pattern process_regular_node
246
+ alias on_if_guard process_regular_node
247
+ alias on_unless_guard process_regular_node
248
+ alias on_match_var process_variable_node
249
+ alias on_match_rest process_regular_node
250
+ alias on_pin process_regular_node
251
+ alias on_match_alt process_regular_node
252
+ alias on_match_as process_regular_node
253
+ alias on_array_pattern process_regular_node
254
+ alias on_array_pattern_with_tail process_regular_node
255
+ alias on_hash_pattern process_regular_node
256
+ alias on_const_pattern process_regular_node
257
+ alias on_find_pattern process_regular_node
258
+
215
259
  # @private
216
260
  def process_variable_node(node)
217
261
  warn 'Parser::AST::Processor#process_variable_node is deprecated as a' \
@@ -235,6 +279,10 @@ module Parser
235
279
  'Parser::AST::Processor#on_argument instead.'
236
280
  on_argument(node)
237
281
  end
282
+
283
+ def on_empty_else(node)
284
+ node
285
+ end
238
286
  end
239
287
  end
240
288
  end
data/lib/parser/base.rb CHANGED
@@ -109,11 +109,16 @@ 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
115
116
  attr_reader :source_buffer
116
117
  attr_reader :context
118
+ attr_reader :max_numparam_stack
119
+ attr_reader :current_arg_stack
120
+ attr_reader :pattern_variables
121
+ attr_reader :pattern_hash_keys
117
122
 
118
123
  ##
119
124
  # @param [Parser::Builders::Default] builder The AST builder to use.
@@ -123,13 +128,28 @@ module Parser
123
128
 
124
129
  @static_env = StaticEnvironment.new
125
130
 
131
+ # Stack that holds current parsing context
132
+ @context = Context.new
133
+
134
+ # Maximum numbered parameters stack
135
+ @max_numparam_stack = MaxNumparamStack.new
136
+
137
+ # Current argument names stack
138
+ @current_arg_stack = CurrentArgStack.new
139
+
140
+ # Stack of set of variables used in the current pattern
141
+ @pattern_variables = VariablesStack.new
142
+
143
+ # Stack of set of keys used in the current hash in pattern matchinig
144
+ @pattern_hash_keys = VariablesStack.new
145
+
126
146
  @lexer = Lexer.new(version)
127
147
  @lexer.diagnostics = @diagnostics
128
148
  @lexer.static_env = @static_env
149
+ @lexer.context = @context
129
150
 
130
151
  @builder = builder
131
152
  @builder.parser = self
132
- @context = Context.new
133
153
 
134
154
  # Last emitted token
135
155
  @last_token = nil
@@ -150,21 +170,24 @@ module Parser
150
170
  @lexer.reset
151
171
  @static_env.reset
152
172
  @context.reset
173
+ @current_arg_stack.reset
174
+ @pattern_variables.reset
175
+ @pattern_hash_keys.reset
153
176
 
154
177
  self
155
178
  end
156
179
 
157
180
  ##
158
- # 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.
159
182
  #
160
183
  # @param [Parser::Source::Buffer] source_buffer The source buffer to parse.
161
- # @return [Parser::AST::Node]
184
+ # @return [Parser::AST::Node, nil]
162
185
  #
163
186
  def parse(source_buffer)
164
187
  @lexer.source_buffer = source_buffer
165
188
  @source_buffer = source_buffer
166
189
 
167
- do_parse
190
+ do_parse || nil # Force `false` to `nil`, see https://github.com/ruby/racc/pull/136
168
191
  ensure
169
192
  # Don't keep references to the source file.
170
193
  @source_buffer = nil
@@ -188,8 +211,9 @@ module Parser
188
211
 
189
212
  ##
190
213
  # Parses a source buffer and returns the AST, the source code comments,
191
- # and the tokens emitted by the lexer. If `recover` is true and a fatal
192
- # {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
193
217
  # comments as well as tokens are only returned up to the location of
194
218
  # the error.
195
219
  #
@@ -82,6 +82,129 @@ module Parser
82
82
 
83
83
  @emit_index = false
84
84
 
85
+ class << self
86
+ ##
87
+ # AST compatibility attribute; causes a single non-mlhs
88
+ # block argument to be wrapped in s(:procarg0).
89
+ #
90
+ # If set to false (the default), block arguments `|a|` are emitted as
91
+ # `s(:args, s(:procarg0, :a))`
92
+ #
93
+ # If set to true, block arguments `|a|` are emitted as
94
+ # `s(:args, s(:procarg0, s(:arg, :a))`
95
+ #
96
+ # @return [Boolean]
97
+ attr_accessor :emit_arg_inside_procarg0
98
+ end
99
+
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
207
+
85
208
  class << self
86
209
  ##
87
210
  # @api private
@@ -90,6 +213,10 @@ module Parser
90
213
  @emit_procarg0 = true
91
214
  @emit_encoding = true
92
215
  @emit_index = true
216
+ @emit_arg_inside_procarg0 = true
217
+ @emit_forward_arg = true
218
+ @emit_kwargs = true
219
+ @emit_match_pattern = true
93
220
  end
94
221
  end
95
222
 
@@ -262,18 +389,23 @@ module Parser
262
389
  if !dedent_level.nil?
263
390
  dedenter = Lexer::Dedenter.new(dedent_level)
264
391
 
265
- if node.type == :str
392
+ case node.type
393
+ when :str
266
394
  str = node.children.first
267
395
  dedenter.dedent(str)
268
- elsif node.type == :dstr || node.type == :xstr
269
- node.children.each do |str_node|
396
+ when :dstr, :xstr
397
+ children = node.children.map do |str_node|
270
398
  if str_node.type == :str
271
399
  str = str_node.children.first
272
400
  dedenter.dedent(str)
401
+ next nil if str.empty?
273
402
  else
274
403
  dedenter.interrupt
275
404
  end
405
+ str_node
276
406
  end
407
+
408
+ node = node.updated(nil, children.compact)
277
409
  end
278
410
  end
279
411
 
@@ -400,12 +532,12 @@ module Parser
400
532
 
401
533
  def range_inclusive(lhs, dot2_t, rhs)
402
534
  n(:irange, [ lhs, rhs ],
403
- binary_op_map(lhs, dot2_t, rhs))
535
+ range_map(lhs, dot2_t, rhs))
404
536
  end
405
537
 
406
538
  def range_exclusive(lhs, dot3_t, rhs)
407
539
  n(:erange, [ lhs, rhs ],
408
- binary_op_map(lhs, dot3_t, rhs))
540
+ range_map(lhs, dot3_t, rhs))
409
541
  end
410
542
 
411
543
  #
@@ -477,6 +609,11 @@ module Parser
477
609
  name, = *node
478
610
 
479
611
  if @parser.static_env.declared?(name)
612
+ if name.to_s == parser.current_arg_stack.top
613
+ diagnostic :error, :circular_argument_reference,
614
+ { :var_name => name.to_s }, node.loc.expression
615
+ end
616
+
480
617
  node.updated(:lvar)
481
618
  else
482
619
  name, = *node
@@ -535,6 +672,13 @@ module Parser
535
672
 
536
673
  when :ident
537
674
  name, = *node
675
+
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)
681
+
538
682
  @parser.static_env.declare(name)
539
683
 
540
684
  node.updated(:lvasgn)
@@ -624,23 +768,38 @@ module Parser
624
768
 
625
769
  def def_method(def_t, name_t, args,
626
770
  body, end_t)
771
+ check_reserved_for_numparam(value(name_t), loc(name_t))
772
+
627
773
  n(:def, [ value(name_t).to_sym, args, body ],
628
774
  definition_map(def_t, nil, name_t, end_t))
629
775
  end
630
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
+
631
785
  def def_singleton(def_t, definee, dot_t,
632
786
  name_t, args,
633
787
  body, end_t)
634
- case definee.type
635
- when :int, :str, :dstr, :sym, :dsym,
636
- :regexp, :array, :hash
788
+ validate_definee(definee)
789
+ check_reserved_for_numparam(value(name_t), loc(name_t))
637
790
 
638
- 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
639
794
 
640
- else
641
- n(:defs, [ definee, value(name_t).to_sym, args, body ],
642
- definition_map(def_t, dot_t, name_t, end_t))
643
- 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))
644
803
  end
645
804
 
646
805
  def undef_method(undef_t, names)
@@ -663,12 +822,34 @@ module Parser
663
822
  collection_map(begin_t, args, end_t))
664
823
  end
665
824
 
825
+ def numargs(max_numparam)
826
+ n(:numargs, [ max_numparam ], nil)
827
+ end
828
+
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))
841
+ end
842
+
666
843
  def arg(name_t)
844
+ check_reserved_for_numparam(value(name_t), loc(name_t))
845
+
667
846
  n(:arg, [ value(name_t).to_sym ],
668
847
  variable_map(name_t))
669
848
  end
670
849
 
671
850
  def optarg(name_t, eql_t, value)
851
+ check_reserved_for_numparam(value(name_t), loc(name_t))
852
+
672
853
  n(:optarg, [ value(name_t).to_sym, value ],
673
854
  variable_map(name_t).
674
855
  with_operator(loc(eql_t)).
@@ -677,6 +858,7 @@ module Parser
677
858
 
678
859
  def restarg(star_t, name_t=nil)
679
860
  if name_t
861
+ check_reserved_for_numparam(value(name_t), loc(name_t))
680
862
  n(:restarg, [ value(name_t).to_sym ],
681
863
  arg_prefix_map(star_t, name_t))
682
864
  else
@@ -686,17 +868,23 @@ module Parser
686
868
  end
687
869
 
688
870
  def kwarg(name_t)
871
+ check_reserved_for_numparam(value(name_t), loc(name_t))
872
+
689
873
  n(:kwarg, [ value(name_t).to_sym ],
690
874
  kwarg_map(name_t))
691
875
  end
692
876
 
693
877
  def kwoptarg(name_t, value)
878
+ check_reserved_for_numparam(value(name_t), loc(name_t))
879
+
694
880
  n(:kwoptarg, [ value(name_t).to_sym, value ],
695
881
  kwarg_map(name_t, value))
696
882
  end
697
883
 
698
884
  def kwrestarg(dstar_t, name_t=nil)
699
885
  if name_t
886
+ check_reserved_for_numparam(value(name_t), loc(name_t))
887
+
700
888
  n(:kwrestarg, [ value(name_t).to_sym ],
701
889
  arg_prefix_map(dstar_t, name_t))
702
890
  else
@@ -705,19 +893,33 @@ module Parser
705
893
  end
706
894
  end
707
895
 
896
+ def kwnilarg(dstar_t, nil_t)
897
+ n0(:kwnilarg,
898
+ arg_prefix_map(dstar_t, nil_t))
899
+ end
900
+
708
901
  def shadowarg(name_t)
902
+ check_reserved_for_numparam(value(name_t), loc(name_t))
903
+
709
904
  n(:shadowarg, [ value(name_t).to_sym ],
710
905
  variable_map(name_t))
711
906
  end
712
907
 
713
908
  def blockarg(amper_t, name_t)
909
+ check_reserved_for_numparam(value(name_t), loc(name_t))
910
+
714
911
  n(:blockarg, [ value(name_t).to_sym ],
715
912
  arg_prefix_map(amper_t, name_t))
716
913
  end
717
914
 
718
915
  def procarg0(arg)
719
916
  if self.class.emit_procarg0
720
- arg.updated(:procarg0)
917
+ if arg.type == :arg && self.class.emit_arg_inside_procarg0
918
+ n(:procarg0, [ arg ],
919
+ Source::Map::Collection.new(nil, nil, arg.location.expression))
920
+ else
921
+ arg.updated(:procarg0)
922
+ end
721
923
  else
722
924
  arg
723
925
  end
@@ -802,9 +1004,18 @@ module Parser
802
1004
  end
803
1005
  end
804
1006
 
1007
+ def forwarded_args(dots_t)
1008
+ n(:forwarded_args, [], token_map(dots_t))
1009
+ end
1010
+
805
1011
  def call_method(receiver, dot_t, selector_t,
806
1012
  lparen_t=nil, args=[], rparen_t=nil)
807
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
+
808
1019
  if selector_t.nil?
809
1020
  n(type, [ receiver, :call, *args ],
810
1021
  send_map(receiver, dot_t, nil, lparen_t, args, rparen_t))
@@ -831,19 +1042,26 @@ module Parser
831
1042
  end
832
1043
 
833
1044
  last_arg = call_args.last
834
- if last_arg && last_arg.type == :block_pass
1045
+ if last_arg && (last_arg.type == :block_pass || last_arg.type == :forwarded_args)
835
1046
  diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)]
836
1047
  end
837
1048
 
1049
+ if args.type == :numargs
1050
+ block_type = :numblock
1051
+ args = args.children[0]
1052
+ else
1053
+ block_type = :block
1054
+ end
1055
+
838
1056
  if [:send, :csend, :index, :super, :zsuper, :lambda].include?(method_call.type)
839
- n(:block, [ method_call, args, body ],
1057
+ n(block_type, [ method_call, args, body ],
840
1058
  block_map(method_call.loc.expression, begin_t, end_t))
841
1059
  else
842
1060
  # Code like "return foo 1 do end" is reduced in a weird sequence.
843
1061
  # Here, method_call is actually (return).
844
1062
  actual_send, = *method_call
845
1063
  block =
846
- n(:block, [ actual_send, args, body ],
1064
+ n(block_type, [ actual_send, args, body ],
847
1065
  block_map(actual_send.loc.expression, begin_t, end_t))
848
1066
 
849
1067
  n(method_call.type, [ block ],
@@ -875,6 +1093,10 @@ module Parser
875
1093
  end
876
1094
 
877
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
+
878
1100
  if self.class.emit_index
879
1101
  n(:index, [ receiver, *indexes ],
880
1102
  index_map(receiver, lbrack_t, rbrack_t))
@@ -1037,6 +1259,10 @@ module Parser
1037
1259
  end
1038
1260
  end
1039
1261
 
1262
+ if %i[yield super].include?(type) && self.class.emit_kwargs
1263
+ rewrite_hash_args_to_kwargs(args)
1264
+ end
1265
+
1040
1266
  n(type, args,
1041
1267
  keyword_map(keyword_t, lparen_t, args, rparen_t))
1042
1268
  end
@@ -1155,6 +1381,219 @@ module Parser
1155
1381
  end
1156
1382
  end
1157
1383
 
1384
+ #
1385
+ # PATTERN MATCHING
1386
+ #
1387
+
1388
+ def case_match(case_t, expr, in_bodies, else_t, else_body, end_t)
1389
+ else_body = n(:empty_else, nil, token_map(else_t)) if else_t && !else_body
1390
+ n(:case_match, [ expr, *(in_bodies << else_body)],
1391
+ condition_map(case_t, expr, nil, nil, else_t, else_body, end_t))
1392
+ end
1393
+
1394
+ def in_match(lhs, in_t, rhs)
1395
+ n(:in_match, [lhs, rhs],
1396
+ binary_op_map(lhs, in_t, rhs))
1397
+ end
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
+
1409
+ def in_pattern(in_t, pattern, guard, then_t, body)
1410
+ children = [pattern, guard, body]
1411
+ n(:in_pattern, children,
1412
+ keyword_map(in_t, then_t, children.compact, nil))
1413
+ end
1414
+
1415
+ def if_guard(if_t, if_body)
1416
+ n(:if_guard, [if_body], guard_map(if_t, if_body))
1417
+ end
1418
+
1419
+ def unless_guard(unless_t, unless_body)
1420
+ n(:unless_guard, [unless_body], guard_map(unless_t, unless_body))
1421
+ end
1422
+
1423
+ def match_var(name_t)
1424
+ name = value(name_t).to_sym
1425
+ name_l = loc(name_t)
1426
+
1427
+ check_lvar_name(name, name_l)
1428
+ check_duplicate_pattern_variable(name, name_l)
1429
+ @parser.static_env.declare(name)
1430
+
1431
+ n(:match_var, [ name ],
1432
+ variable_map(name_t))
1433
+ end
1434
+
1435
+ def match_hash_var(name_t)
1436
+ name = value(name_t).to_sym
1437
+
1438
+ expr_l = loc(name_t)
1439
+ name_l = expr_l.adjust(end_pos: -1)
1440
+
1441
+ check_lvar_name(name, name_l)
1442
+ check_duplicate_pattern_variable(name, name_l)
1443
+ @parser.static_env.declare(name)
1444
+
1445
+ n(:match_var, [ name ],
1446
+ Source::Map::Variable.new(name_l, expr_l))
1447
+ end
1448
+
1449
+ def match_hash_var_from_str(begin_t, strings, end_t)
1450
+ if strings.length > 1
1451
+ diagnostic :error, :pm_interp_in_var_name, nil, loc(begin_t).join(loc(end_t))
1452
+ end
1453
+
1454
+ string = strings[0]
1455
+
1456
+ case string.type
1457
+ when :str
1458
+ # MRI supports plain strings in hash pattern matching
1459
+ name, = *string
1460
+ name_l = string.loc.expression
1461
+
1462
+ check_lvar_name(name, name_l)
1463
+ check_duplicate_pattern_variable(name, name_l)
1464
+
1465
+ @parser.static_env.declare(name)
1466
+
1467
+ if (begin_l = string.loc.begin)
1468
+ # exclude beginning of the string from the location of the variable
1469
+ name_l = name_l.adjust(begin_pos: begin_l.length)
1470
+ end
1471
+
1472
+ if (end_l = string.loc.end)
1473
+ # exclude end of the string from the location of the variable
1474
+ name_l = name_l.adjust(end_pos: -end_l.length)
1475
+ end
1476
+
1477
+ expr_l = loc(begin_t).join(string.loc.expression).join(loc(end_t))
1478
+ n(:match_var, [ name.to_sym ],
1479
+ Source::Map::Variable.new(name_l, expr_l))
1480
+ when :begin
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))
1485
+ end
1486
+ end
1487
+
1488
+ def match_rest(star_t, name_t = nil)
1489
+ if name_t.nil?
1490
+ n0(:match_rest,
1491
+ unary_op_map(star_t))
1492
+ else
1493
+ name = match_var(name_t)
1494
+ n(:match_rest, [ name ],
1495
+ unary_op_map(star_t, name))
1496
+ end
1497
+ end
1498
+
1499
+ def hash_pattern(lbrace_t, kwargs, rbrace_t)
1500
+ args = check_duplicate_args(kwargs)
1501
+ n(:hash_pattern, args,
1502
+ collection_map(lbrace_t, args, rbrace_t))
1503
+ end
1504
+
1505
+ def array_pattern(lbrack_t, elements, rbrack_t)
1506
+ return n(:array_pattern, nil, collection_map(lbrack_t, [], rbrack_t)) if elements.nil?
1507
+
1508
+ trailing_comma = false
1509
+
1510
+ node_elements = elements.map do |element|
1511
+ if element.type == :match_with_trailing_comma
1512
+ trailing_comma = true
1513
+ element.children.first
1514
+ else
1515
+ trailing_comma = false
1516
+ element
1517
+ end
1518
+ end
1519
+
1520
+ node_type = trailing_comma ? :array_pattern_with_tail : :array_pattern
1521
+
1522
+ n(node_type, node_elements,
1523
+ collection_map(lbrack_t, elements, rbrack_t))
1524
+ end
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
+
1531
+ def match_with_trailing_comma(match, comma_t)
1532
+ n(:match_with_trailing_comma, [ match ], expr_map(match.loc.expression.join(loc(comma_t))))
1533
+ end
1534
+
1535
+ def const_pattern(const, ldelim_t, pattern, rdelim_t)
1536
+ n(:const_pattern, [const, pattern],
1537
+ Source::Map::Collection.new(
1538
+ loc(ldelim_t), loc(rdelim_t),
1539
+ const.loc.expression.join(loc(rdelim_t))
1540
+ )
1541
+ )
1542
+ end
1543
+
1544
+ def pin(pin_t, var)
1545
+ n(:pin, [ var ],
1546
+ send_unary_op_map(pin_t, var))
1547
+ end
1548
+
1549
+ def match_alt(left, pipe_t, right)
1550
+ source_map = binary_op_map(left, pipe_t, right)
1551
+
1552
+ n(:match_alt, [ left, right ],
1553
+ source_map)
1554
+ end
1555
+
1556
+ def match_as(value, assoc_t, as)
1557
+ source_map = binary_op_map(value, assoc_t, as)
1558
+
1559
+ n(:match_as, [ value, as ],
1560
+ source_map)
1561
+ end
1562
+
1563
+ def match_nil_pattern(dstar_t, nil_t)
1564
+ n0(:match_nil_pattern,
1565
+ arg_prefix_map(dstar_t, nil_t))
1566
+ end
1567
+
1568
+ def match_pair(label_type, label, value)
1569
+ if label_type == :label
1570
+ check_duplicate_pattern_key(label[0], label[1])
1571
+ pair_keyword(label, value)
1572
+ else
1573
+ begin_t, parts, end_t = label
1574
+ label_loc = loc(begin_t).join(loc(end_t))
1575
+
1576
+ # quoted label like "label": value
1577
+ if (var_name = static_string(parts))
1578
+ check_duplicate_pattern_key(var_name, label_loc)
1579
+ else
1580
+ diagnostic :error, :pm_interp_in_var_name, nil, label_loc
1581
+ end
1582
+
1583
+ pair_quoted(begin_t, parts, end_t, value)
1584
+ end
1585
+ end
1586
+
1587
+ def match_label(label_type, label)
1588
+ if label_type == :label
1589
+ match_hash_var(label)
1590
+ else
1591
+ # quoted label like "label": value
1592
+ begin_t, strings, end_t = label
1593
+ match_hash_var_from_str(begin_t, strings, end_t)
1594
+ end
1595
+ end
1596
+
1158
1597
  private
1159
1598
 
1160
1599
  #
@@ -1210,18 +1649,18 @@ module Parser
1210
1649
  case this_arg.type
1211
1650
  when :arg, :optarg, :restarg, :blockarg,
1212
1651
  :kwarg, :kwoptarg, :kwrestarg,
1213
- :shadowarg, :procarg0
1652
+ :shadowarg
1214
1653
 
1215
- this_name, = *this_arg
1654
+ check_duplicate_arg(this_arg, map)
1216
1655
 
1217
- that_arg = map[this_name]
1218
- that_name, = *that_arg
1656
+ when :procarg0
1219
1657
 
1220
- if that_arg.nil?
1221
- map[this_name] = this_arg
1222
- elsif arg_name_collides?(this_name, that_name)
1223
- diagnostic :error, :duplicate_argument, nil,
1224
- this_arg.loc.name, [ that_arg.loc.name ]
1658
+ if this_arg.children[0].is_a?(Symbol)
1659
+ # s(:procarg0, :a)
1660
+ check_duplicate_arg(this_arg, map)
1661
+ else
1662
+ # s(:procarg0, s(:arg, :a), ...)
1663
+ check_duplicate_args(this_arg.children, map)
1225
1664
  end
1226
1665
 
1227
1666
  when :mlhs
@@ -1230,6 +1669,45 @@ module Parser
1230
1669
  end
1231
1670
  end
1232
1671
 
1672
+ def check_duplicate_arg(this_arg, map={})
1673
+ this_name, = *this_arg
1674
+
1675
+ that_arg = map[this_name]
1676
+ that_name, = *that_arg
1677
+
1678
+ if that_arg.nil?
1679
+ map[this_name] = this_arg
1680
+ elsif arg_name_collides?(this_name, that_name)
1681
+ diagnostic :error, :duplicate_argument, nil,
1682
+ this_arg.loc.name, [ that_arg.loc.name ]
1683
+ end
1684
+ end
1685
+
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
1690
+
1691
+ assigning_to_numparam =
1692
+ @parser.context.in_dynamic_block? &&
1693
+ name =~ /\A_([1-9])\z/ &&
1694
+ @parser.max_numparam_stack.has_numparams?
1695
+
1696
+ if assigning_to_numparam
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
1708
+ end
1709
+ end
1710
+
1233
1711
  def arg_name_collides?(this_name, that_name)
1234
1712
  case @parser.version
1235
1713
  when 18
@@ -1245,6 +1723,32 @@ module Parser
1245
1723
  end
1246
1724
  end
1247
1725
 
1726
+ def check_lvar_name(name, loc)
1727
+ if name =~ /\A[[[:lower:]]_][[[:alnum:]]_]*\z/
1728
+ # OK
1729
+ else
1730
+ diagnostic :error, :lvar_name, { name: name }, loc
1731
+ end
1732
+ end
1733
+
1734
+ def check_duplicate_pattern_variable(name, loc)
1735
+ return if name.to_s.start_with?('_')
1736
+
1737
+ if @parser.pattern_variables.declared?(name)
1738
+ diagnostic :error, :duplicate_variable_name, { name: name.to_s }, loc
1739
+ end
1740
+
1741
+ @parser.pattern_variables.declare(name)
1742
+ end
1743
+
1744
+ def check_duplicate_pattern_key(name, loc)
1745
+ if @parser.pattern_hash_keys.declared?(name)
1746
+ diagnostic :error, :duplicate_pattern_key, { name: name.to_s }, loc
1747
+ end
1748
+
1749
+ @parser.pattern_hash_keys.declare(name)
1750
+ end
1751
+
1248
1752
  #
1249
1753
  # SOURCE MAPS
1250
1754
  #
@@ -1388,6 +1892,18 @@ module Parser
1388
1892
  Source::Map::Operator.new(loc(op_t), expr_l)
1389
1893
  end
1390
1894
 
1895
+ def range_map(start_e, op_t, end_e)
1896
+ if start_e && end_e
1897
+ expr_l = join_exprs(start_e, end_e)
1898
+ elsif start_e
1899
+ expr_l = start_e.loc.expression.join(loc(op_t))
1900
+ elsif end_e
1901
+ expr_l = loc(op_t).join(end_e.loc.expression)
1902
+ end
1903
+
1904
+ Source::Map::Operator.new(loc(op_t), expr_l)
1905
+ end
1906
+
1391
1907
  def arg_prefix_map(op_t, name_t=nil)
1392
1908
  if name_t.nil?
1393
1909
  expr_l = loc(op_t)
@@ -1422,9 +1938,17 @@ module Parser
1422
1938
  end
1423
1939
 
1424
1940
  def definition_map(keyword_t, operator_t, name_t, end_t)
1425
- Source::Map::Definition.new(loc(keyword_t),
1426
- loc(operator_t), loc(name_t),
1427
- 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)
1428
1952
  end
1429
1953
 
1430
1954
  def send_map(receiver_e, dot_t, selector_t, begin_t=nil, args=[], end_t=nil)
@@ -1581,6 +2105,13 @@ module Parser
1581
2105
  begin_l.join(end_l))
1582
2106
  end
1583
2107
 
2108
+ def guard_map(keyword_t, guard_body_e)
2109
+ keyword_l = loc(keyword_t)
2110
+ guard_body_l = guard_body_e.loc.expression
2111
+
2112
+ Source::Map::Keyword.new(keyword_l, nil, nil, keyword_l.join(guard_body_l))
2113
+ end
2114
+
1584
2115
  #
1585
2116
  # HELPERS
1586
2117
  #
@@ -1662,6 +2193,32 @@ module Parser
1662
2193
  @parser.send :yyerror
1663
2194
  end
1664
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
1665
2222
  end
1666
2223
 
1667
2224
  end