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.
- checksums.yaml +4 -4
- data/lib/parser.rb +4 -0
- data/lib/parser/all.rb +3 -0
- data/lib/parser/ast/processor.rb +49 -1
- data/lib/parser/base.rb +30 -6
- data/lib/parser/builders/default.rb +586 -29
- data/lib/parser/context.rb +17 -0
- data/lib/parser/current.rb +34 -7
- data/lib/parser/current_arg_stack.rb +46 -0
- data/lib/parser/diagnostic.rb +1 -1
- data/lib/parser/diagnostic/engine.rb +1 -2
- data/lib/parser/lexer.rb +23780 -0
- data/lib/parser/lexer/dedenter.rb +52 -49
- data/lib/parser/lexer/literal.rb +4 -0
- data/lib/parser/lexer/stack_state.rb +4 -0
- data/lib/parser/macruby.rb +6149 -0
- data/lib/parser/max_numparam_stack.rb +56 -0
- data/lib/parser/messages.rb +74 -44
- data/lib/parser/meta.rb +13 -3
- data/lib/parser/ruby18.rb +5667 -0
- data/lib/parser/ruby19.rb +6092 -0
- data/lib/parser/ruby20.rb +6527 -0
- data/lib/parser/ruby21.rb +6578 -0
- data/lib/parser/ruby22.rb +6613 -0
- data/lib/parser/ruby23.rb +6624 -0
- data/lib/parser/ruby24.rb +6694 -0
- data/lib/parser/ruby25.rb +6662 -0
- data/lib/parser/ruby26.rb +6676 -0
- data/lib/parser/ruby27.rb +7862 -0
- data/lib/parser/ruby28.rb +8047 -0
- data/lib/parser/ruby30.rb +8060 -0
- data/lib/parser/ruby31.rb +8075 -0
- data/lib/parser/rubymotion.rb +6086 -0
- data/lib/parser/runner.rb +36 -2
- data/lib/parser/runner/ruby_parse.rb +2 -2
- data/lib/parser/runner/ruby_rewrite.rb +2 -2
- data/lib/parser/source/buffer.rb +54 -29
- data/lib/parser/source/comment.rb +18 -5
- data/lib/parser/source/comment/associator.rb +34 -11
- data/lib/parser/source/map.rb +1 -1
- data/lib/parser/source/map/method_definition.rb +25 -0
- data/lib/parser/source/range.rb +20 -4
- data/lib/parser/source/tree_rewriter.rb +146 -16
- data/lib/parser/source/tree_rewriter/action.rb +137 -28
- data/lib/parser/static_environment.rb +14 -0
- data/lib/parser/tree_rewriter.rb +3 -3
- data/lib/parser/variables_stack.rb +36 -0
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +13 -21
- metadata +34 -98
- data/.gitignore +0 -32
- data/.travis.yml +0 -21
- data/.yardopts +0 -21
- data/CHANGELOG.md +0 -909
- data/CONTRIBUTING.md +0 -17
- data/Gemfile +0 -10
- data/README.md +0 -301
- data/Rakefile +0 -165
- data/doc/AST_FORMAT.md +0 -1718
- data/doc/CUSTOMIZATION.md +0 -37
- data/doc/INTERNALS.md +0 -21
- data/doc/css/.gitkeep +0 -0
- data/doc/css/common.css +0 -68
- data/lib/parser/lexer.rl +0 -2376
- data/lib/parser/macruby.y +0 -2198
- data/lib/parser/ruby18.y +0 -1934
- data/lib/parser/ruby19.y +0 -2175
- data/lib/parser/ruby20.y +0 -2353
- data/lib/parser/ruby21.y +0 -2357
- data/lib/parser/ruby22.y +0 -2364
- data/lib/parser/ruby23.y +0 -2370
- data/lib/parser/ruby24.y +0 -2395
- data/lib/parser/ruby25.y +0 -2392
- data/lib/parser/ruby26.y +0 -2392
- data/lib/parser/rubymotion.y +0 -2182
- data/test/bug_163/fixtures/input.rb +0 -5
- data/test/bug_163/fixtures/output.rb +0 -5
- data/test/bug_163/rewriter.rb +0 -20
- data/test/helper.rb +0 -52
- data/test/parse_helper.rb +0 -315
- data/test/racc_coverage_helper.rb +0 -133
- data/test/test_base.rb +0 -31
- data/test/test_current.rb +0 -27
- data/test/test_diagnostic.rb +0 -96
- data/test/test_diagnostic_engine.rb +0 -62
- data/test/test_encoding.rb +0 -99
- data/test/test_lexer.rb +0 -3537
- data/test/test_lexer_stack_state.rb +0 -78
- data/test/test_parse_helper.rb +0 -80
- data/test/test_parser.rb +0 -6968
- data/test/test_runner_rewrite.rb +0 -47
- data/test/test_source_buffer.rb +0 -162
- data/test/test_source_comment.rb +0 -36
- data/test/test_source_comment_associator.rb +0 -367
- data/test/test_source_map.rb +0 -15
- data/test/test_source_range.rb +0 -172
- data/test/test_source_rewriter.rb +0 -541
- data/test/test_source_rewriter_action.rb +0 -46
- data/test/test_source_tree_rewriter.rb +0 -173
- data/test/test_static_environment.rb +0 -45
- data/test/using_tree_rewriter/fixtures/input.rb +0 -3
- data/test/using_tree_rewriter/fixtures/output.rb +0 -3
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c85d02ca4bf90dcc1d33424dd323ae54b9e60581a6473012e950f82ce15d28e
|
4
|
+
data.tar.gz: ebe2c4eb02779209b8a34e051d717a6af84da81fadfeff79d9eab194ecf95d93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/lib/parser/ast/processor.rb
CHANGED
@@ -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
|
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.
|
192
|
-
#
|
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
|
-
|
392
|
+
case node.type
|
393
|
+
when :str
|
266
394
|
str = node.children.first
|
267
395
|
dedenter.dedent(str)
|
268
|
-
|
269
|
-
node.children.
|
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
|
-
|
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
|
-
|
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
|
-
|
635
|
-
|
636
|
-
:regexp, :array, :hash
|
788
|
+
validate_definee(definee)
|
789
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
637
790
|
|
638
|
-
|
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
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
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.
|
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(
|
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(
|
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
|
1652
|
+
:shadowarg
|
1214
1653
|
|
1215
|
-
|
1654
|
+
check_duplicate_arg(this_arg, map)
|
1216
1655
|
|
1217
|
-
|
1218
|
-
that_name, = *that_arg
|
1656
|
+
when :procarg0
|
1219
1657
|
|
1220
|
-
if
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
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::
|
1426
|
-
|
1427
|
-
|
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
|