parser 2.5.1.0 → 3.0.1.1
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.
- 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
|