parser 2.6.5.0 → 2.7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/parser.rb +4 -1
- data/lib/parser/all.rb +1 -0
- data/lib/parser/ast/processor.rb +21 -0
- data/lib/parser/base.rb +25 -5
- data/lib/parser/builders/default.rb +394 -24
- data/lib/parser/context.rb +5 -0
- data/lib/parser/current.rb +16 -7
- data/lib/parser/current_arg_stack.rb +43 -0
- data/lib/parser/diagnostic.rb +1 -1
- data/lib/parser/diagnostic/engine.rb +1 -2
- data/lib/parser/lexer.rb +23770 -0
- data/lib/parser/lexer/dedenter.rb +52 -49
- data/lib/parser/macruby.rb +6149 -0
- data/lib/parser/{lexer/max_numparam_stack.rb → max_numparam_stack.rb} +10 -4
- data/lib/parser/messages.rb +52 -29
- data/lib/parser/meta.rb +10 -5
- data/lib/parser/ruby18.rb +5663 -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 +7803 -0
- data/lib/parser/ruby28.rb +8047 -0
- data/lib/parser/ruby30.rb +8052 -0
- data/lib/parser/rubymotion.rb +6086 -0
- data/lib/parser/runner.rb +26 -2
- data/lib/parser/runner/ruby_rewrite.rb +2 -2
- data/lib/parser/source/buffer.rb +3 -1
- data/lib/parser/source/comment.rb +1 -1
- data/lib/parser/source/comment/associator.rb +14 -4
- data/lib/parser/source/map/method_definition.rb +25 -0
- data/lib/parser/source/range.rb +19 -3
- data/lib/parser/source/tree_rewriter.rb +115 -12
- data/lib/parser/source/tree_rewriter/action.rb +137 -28
- data/lib/parser/static_environment.rb +10 -0
- data/lib/parser/tree_rewriter.rb +1 -2
- data/lib/parser/variables_stack.rb +32 -0
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +10 -18
- metadata +22 -99
- data/.gitignore +0 -33
- data/.travis.yml +0 -45
- data/.yardopts +0 -21
- data/CHANGELOG.md +0 -997
- data/CONTRIBUTING.md +0 -17
- data/Gemfile +0 -10
- data/LICENSE.txt +0 -25
- data/README.md +0 -301
- data/Rakefile +0 -166
- data/ci/run_rubocop_specs +0 -14
- data/doc/AST_FORMAT.md +0 -1816
- 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 -2533
- 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 -2408
- data/lib/parser/ruby25.y +0 -2405
- data/lib/parser/ruby26.y +0 -2413
- data/lib/parser/ruby27.y +0 -2470
- 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 -59
- data/test/parse_helper.rb +0 -316
- data/test/racc_coverage_helper.rb +0 -133
- data/test/test_base.rb +0 -31
- data/test/test_current.rb +0 -29
- 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 -3667
- data/test/test_lexer_stack_state.rb +0 -78
- data/test/test_parse_helper.rb +0 -80
- data/test/test_parser.rb +0 -7644
- data/test/test_runner_parse.rb +0 -35
- 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: 3efc381a3ad92df723e4a698afbceb63f65fdb7c892f690dbd569ba298307d8b
|
4
|
+
data.tar.gz: b9e78eb7dd39f6539fc21883fbec26b1a0c2d377c68bf060d485df5521318e54
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c9b2d1df5a463c289f2881c0064c956e88560bc14af30bbb9fe3828ae7a3e1f8a88352172e353b196f34ba1e98640b6bf38bcbb50bef0f8661aacf9e8ccdc1b
|
7
|
+
data.tar.gz: e394d70911b7d86ee7049b0ecaab839120da2f90372630e48c6bb3c14f3b45b35322a2d99ca516df6cc2e8a8e7c0c79aca1031c3dfa28b0026c300ea10b51ed4
|
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'
|
@@ -67,13 +68,15 @@ module Parser
|
|
67
68
|
require 'parser/lexer/literal'
|
68
69
|
require 'parser/lexer/stack_state'
|
69
70
|
require 'parser/lexer/dedenter'
|
70
|
-
require 'parser/lexer/max_numparam_stack'
|
71
71
|
|
72
72
|
module Builders
|
73
73
|
require 'parser/builders/default'
|
74
74
|
end
|
75
75
|
|
76
76
|
require 'parser/context'
|
77
|
+
require 'parser/max_numparam_stack'
|
78
|
+
require 'parser/current_arg_stack'
|
79
|
+
require 'parser/variables_stack'
|
77
80
|
|
78
81
|
require 'parser/base'
|
79
82
|
|
data/lib/parser/all.rb
CHANGED
data/lib/parser/ast/processor.rb
CHANGED
@@ -124,6 +124,7 @@ module Parser
|
|
124
124
|
alias on_kwarg process_argument_node
|
125
125
|
alias on_kwoptarg process_argument_node
|
126
126
|
alias on_kwrestarg process_argument_node
|
127
|
+
alias on_forward_arg process_argument_node
|
127
128
|
|
128
129
|
def on_procarg0(node)
|
129
130
|
if node.children[0].is_a?(Symbol)
|
@@ -236,6 +237,22 @@ module Parser
|
|
236
237
|
alias on_preexe process_regular_node
|
237
238
|
alias on_postexe process_regular_node
|
238
239
|
|
240
|
+
alias on_case_match process_regular_node
|
241
|
+
alias on_in_match process_regular_node
|
242
|
+
alias on_in_pattern process_regular_node
|
243
|
+
alias on_if_guard process_regular_node
|
244
|
+
alias on_unless_guard process_regular_node
|
245
|
+
alias on_match_var process_variable_node
|
246
|
+
alias on_match_rest process_regular_node
|
247
|
+
alias on_pin process_regular_node
|
248
|
+
alias on_match_alt process_regular_node
|
249
|
+
alias on_match_as process_regular_node
|
250
|
+
alias on_array_pattern process_regular_node
|
251
|
+
alias on_array_pattern_with_tail process_regular_node
|
252
|
+
alias on_hash_pattern process_regular_node
|
253
|
+
alias on_const_pattern process_regular_node
|
254
|
+
alias on_find_pattern process_regular_node
|
255
|
+
|
239
256
|
# @private
|
240
257
|
def process_variable_node(node)
|
241
258
|
warn 'Parser::AST::Processor#process_variable_node is deprecated as a' \
|
@@ -259,6 +276,10 @@ module Parser
|
|
259
276
|
'Parser::AST::Processor#on_argument instead.'
|
260
277
|
on_argument(node)
|
261
278
|
end
|
279
|
+
|
280
|
+
def on_empty_else(node)
|
281
|
+
node
|
282
|
+
end
|
262
283
|
end
|
263
284
|
end
|
264
285
|
end
|
data/lib/parser/base.rb
CHANGED
@@ -114,6 +114,10 @@ module Parser
|
|
114
114
|
attr_reader :static_env
|
115
115
|
attr_reader :source_buffer
|
116
116
|
attr_reader :context
|
117
|
+
attr_reader :max_numparam_stack
|
118
|
+
attr_reader :current_arg_stack
|
119
|
+
attr_reader :pattern_variables
|
120
|
+
attr_reader :pattern_hash_keys
|
117
121
|
|
118
122
|
##
|
119
123
|
# @param [Parser::Builders::Default] builder The AST builder to use.
|
@@ -126,6 +130,18 @@ module Parser
|
|
126
130
|
# Stack that holds current parsing context
|
127
131
|
@context = Context.new
|
128
132
|
|
133
|
+
# Maximum numbered parameters stack
|
134
|
+
@max_numparam_stack = MaxNumparamStack.new
|
135
|
+
|
136
|
+
# Current argument names stack
|
137
|
+
@current_arg_stack = CurrentArgStack.new
|
138
|
+
|
139
|
+
# Stack of set of variables used in the current pattern
|
140
|
+
@pattern_variables = VariablesStack.new
|
141
|
+
|
142
|
+
# Stack of set of keys used in the current hash in pattern matchinig
|
143
|
+
@pattern_hash_keys = VariablesStack.new
|
144
|
+
|
129
145
|
@lexer = Lexer.new(version)
|
130
146
|
@lexer.diagnostics = @diagnostics
|
131
147
|
@lexer.static_env = @static_env
|
@@ -153,21 +169,24 @@ module Parser
|
|
153
169
|
@lexer.reset
|
154
170
|
@static_env.reset
|
155
171
|
@context.reset
|
172
|
+
@current_arg_stack.reset
|
173
|
+
@pattern_variables.reset
|
174
|
+
@pattern_hash_keys.reset
|
156
175
|
|
157
176
|
self
|
158
177
|
end
|
159
178
|
|
160
179
|
##
|
161
|
-
# Parses a source buffer and returns the AST.
|
180
|
+
# Parses a source buffer and returns the AST, or `nil` in case of a non fatal error.
|
162
181
|
#
|
163
182
|
# @param [Parser::Source::Buffer] source_buffer The source buffer to parse.
|
164
|
-
# @return [Parser::AST::Node]
|
183
|
+
# @return [Parser::AST::Node, nil]
|
165
184
|
#
|
166
185
|
def parse(source_buffer)
|
167
186
|
@lexer.source_buffer = source_buffer
|
168
187
|
@source_buffer = source_buffer
|
169
188
|
|
170
|
-
do_parse
|
189
|
+
do_parse || nil # Force `false` to `nil`, see https://github.com/ruby/racc/pull/136
|
171
190
|
ensure
|
172
191
|
# Don't keep references to the source file.
|
173
192
|
@source_buffer = nil
|
@@ -191,8 +210,9 @@ module Parser
|
|
191
210
|
|
192
211
|
##
|
193
212
|
# Parses a source buffer and returns the AST, the source code comments,
|
194
|
-
# and the tokens emitted by the lexer.
|
195
|
-
#
|
213
|
+
# and the tokens emitted by the lexer. In case of a fatal error, a {SyntaxError}
|
214
|
+
# is raised, unless `recover` is true. In case of an error
|
215
|
+
# (non-fatal or recovered), `nil` is returned instead of the AST, and
|
196
216
|
# comments as well as tokens are only returned up to the location of
|
197
217
|
# the error.
|
198
218
|
#
|
@@ -80,6 +80,8 @@ module Parser
|
|
80
80
|
attr_accessor :emit_index
|
81
81
|
end
|
82
82
|
|
83
|
+
@emit_index = false
|
84
|
+
|
83
85
|
class << self
|
84
86
|
##
|
85
87
|
# AST compatibility attribute; causes a single non-mlhs
|
@@ -95,7 +97,36 @@ module Parser
|
|
95
97
|
attr_accessor :emit_arg_inside_procarg0
|
96
98
|
end
|
97
99
|
|
98
|
-
@
|
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
|
99
130
|
|
100
131
|
class << self
|
101
132
|
##
|
@@ -106,6 +137,7 @@ module Parser
|
|
106
137
|
@emit_encoding = true
|
107
138
|
@emit_index = true
|
108
139
|
@emit_arg_inside_procarg0 = true
|
140
|
+
@emit_forward_arg = true
|
109
141
|
end
|
110
142
|
end
|
111
143
|
|
@@ -453,11 +485,6 @@ module Parser
|
|
453
485
|
variable_map(token))
|
454
486
|
end
|
455
487
|
|
456
|
-
def numparam(token)
|
457
|
-
n(:numparam, [ value(token).to_i ],
|
458
|
-
variable_map(token))
|
459
|
-
end
|
460
|
-
|
461
488
|
def back_ref(token)
|
462
489
|
n(:back_ref, [ value(token).to_sym ],
|
463
490
|
token_map(token))
|
@@ -498,6 +525,11 @@ module Parser
|
|
498
525
|
name, = *node
|
499
526
|
|
500
527
|
if @parser.static_env.declared?(name)
|
528
|
+
if name.to_s == parser.current_arg_stack.top
|
529
|
+
diagnostic :error, :circular_argument_reference,
|
530
|
+
{ :var_name => name.to_s }, node.loc.expression
|
531
|
+
end
|
532
|
+
|
501
533
|
node.updated(:lvar)
|
502
534
|
else
|
503
535
|
name, = *node
|
@@ -556,6 +588,13 @@ module Parser
|
|
556
588
|
|
557
589
|
when :ident
|
558
590
|
name, = *node
|
591
|
+
|
592
|
+
var_name = node.children[0].to_s
|
593
|
+
name_loc = node.loc.expression
|
594
|
+
|
595
|
+
check_assignment_to_numparam(var_name, name_loc)
|
596
|
+
check_reserved_for_numparam(var_name, name_loc)
|
597
|
+
|
559
598
|
@parser.static_env.declare(name)
|
560
599
|
|
561
600
|
node.updated(:lvasgn)
|
@@ -616,6 +655,14 @@ module Parser
|
|
616
655
|
binary_op_map(lhs, eql_t, rhs))
|
617
656
|
end
|
618
657
|
|
658
|
+
def rassign(lhs, assoc_t, rhs)
|
659
|
+
assign(rhs, assoc_t, lhs)
|
660
|
+
end
|
661
|
+
|
662
|
+
def multi_rassign(lhs, assoc_t, rhs)
|
663
|
+
multi_assign(rhs, assoc_t, lhs)
|
664
|
+
end
|
665
|
+
|
619
666
|
#
|
620
667
|
# Class and module definition
|
621
668
|
#
|
@@ -645,23 +692,38 @@ module Parser
|
|
645
692
|
|
646
693
|
def def_method(def_t, name_t, args,
|
647
694
|
body, end_t)
|
695
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
696
|
+
|
648
697
|
n(:def, [ value(name_t).to_sym, args, body ],
|
649
698
|
definition_map(def_t, nil, name_t, end_t))
|
650
699
|
end
|
651
700
|
|
701
|
+
def def_endless_method(def_t, name_t, args,
|
702
|
+
assignment_t, body)
|
703
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
704
|
+
|
705
|
+
n(:def, [ value(name_t).to_sym, args, body ],
|
706
|
+
endless_definition_map(def_t, nil, name_t, assignment_t, body))
|
707
|
+
end
|
708
|
+
|
652
709
|
def def_singleton(def_t, definee, dot_t,
|
653
710
|
name_t, args,
|
654
711
|
body, end_t)
|
655
|
-
|
656
|
-
|
657
|
-
:regexp, :array, :hash
|
712
|
+
validate_definee(definee)
|
713
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
658
714
|
|
659
|
-
|
715
|
+
n(:defs, [ definee, value(name_t).to_sym, args, body ],
|
716
|
+
definition_map(def_t, dot_t, name_t, end_t))
|
717
|
+
end
|
660
718
|
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
719
|
+
def def_endless_singleton(def_t, definee, dot_t,
|
720
|
+
name_t, args,
|
721
|
+
assignment_t, body)
|
722
|
+
validate_definee(definee)
|
723
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
724
|
+
|
725
|
+
n(:defs, [ definee, value(name_t).to_sym, args, body ],
|
726
|
+
endless_definition_map(def_t, dot_t, name_t, assignment_t, body))
|
665
727
|
end
|
666
728
|
|
667
729
|
def undef_method(undef_t, names)
|
@@ -688,12 +750,30 @@ module Parser
|
|
688
750
|
n(:numargs, [ max_numparam ], nil)
|
689
751
|
end
|
690
752
|
|
753
|
+
def forward_only_args(begin_t, dots_t, end_t)
|
754
|
+
if self.class.emit_forward_arg
|
755
|
+
arg = forward_arg(dots_t)
|
756
|
+
n(:args, [ arg ],
|
757
|
+
collection_map(begin_t, [ arg ], end_t))
|
758
|
+
else
|
759
|
+
n(:forward_args, [], collection_map(begin_t, token_map(dots_t), end_t))
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
def forward_arg(dots_t)
|
764
|
+
n(:forward_arg, [], token_map(dots_t))
|
765
|
+
end
|
766
|
+
|
691
767
|
def arg(name_t)
|
768
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
769
|
+
|
692
770
|
n(:arg, [ value(name_t).to_sym ],
|
693
771
|
variable_map(name_t))
|
694
772
|
end
|
695
773
|
|
696
774
|
def optarg(name_t, eql_t, value)
|
775
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
776
|
+
|
697
777
|
n(:optarg, [ value(name_t).to_sym, value ],
|
698
778
|
variable_map(name_t).
|
699
779
|
with_operator(loc(eql_t)).
|
@@ -702,6 +782,7 @@ module Parser
|
|
702
782
|
|
703
783
|
def restarg(star_t, name_t=nil)
|
704
784
|
if name_t
|
785
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
705
786
|
n(:restarg, [ value(name_t).to_sym ],
|
706
787
|
arg_prefix_map(star_t, name_t))
|
707
788
|
else
|
@@ -711,17 +792,23 @@ module Parser
|
|
711
792
|
end
|
712
793
|
|
713
794
|
def kwarg(name_t)
|
795
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
796
|
+
|
714
797
|
n(:kwarg, [ value(name_t).to_sym ],
|
715
798
|
kwarg_map(name_t))
|
716
799
|
end
|
717
800
|
|
718
801
|
def kwoptarg(name_t, value)
|
802
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
803
|
+
|
719
804
|
n(:kwoptarg, [ value(name_t).to_sym, value ],
|
720
805
|
kwarg_map(name_t, value))
|
721
806
|
end
|
722
807
|
|
723
808
|
def kwrestarg(dstar_t, name_t=nil)
|
724
809
|
if name_t
|
810
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
811
|
+
|
725
812
|
n(:kwrestarg, [ value(name_t).to_sym ],
|
726
813
|
arg_prefix_map(dstar_t, name_t))
|
727
814
|
else
|
@@ -736,11 +823,15 @@ module Parser
|
|
736
823
|
end
|
737
824
|
|
738
825
|
def shadowarg(name_t)
|
826
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
827
|
+
|
739
828
|
n(:shadowarg, [ value(name_t).to_sym ],
|
740
829
|
variable_map(name_t))
|
741
830
|
end
|
742
831
|
|
743
832
|
def blockarg(amper_t, name_t)
|
833
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
834
|
+
|
744
835
|
n(:blockarg, [ value(name_t).to_sym ],
|
745
836
|
arg_prefix_map(amper_t, name_t))
|
746
837
|
end
|
@@ -837,6 +928,10 @@ module Parser
|
|
837
928
|
end
|
838
929
|
end
|
839
930
|
|
931
|
+
def forwarded_args(dots_t)
|
932
|
+
n(:forwarded_args, [], token_map(dots_t))
|
933
|
+
end
|
934
|
+
|
840
935
|
def call_method(receiver, dot_t, selector_t,
|
841
936
|
lparen_t=nil, args=[], rparen_t=nil)
|
842
937
|
type = call_type_for_dot(dot_t)
|
@@ -866,11 +961,10 @@ module Parser
|
|
866
961
|
end
|
867
962
|
|
868
963
|
last_arg = call_args.last
|
869
|
-
if last_arg && last_arg.type == :block_pass
|
964
|
+
if last_arg && (last_arg.type == :block_pass || last_arg.type == :forwarded_args)
|
870
965
|
diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)]
|
871
966
|
end
|
872
967
|
|
873
|
-
|
874
968
|
if args.type == :numargs
|
875
969
|
block_type = :numblock
|
876
970
|
args = args.children[0]
|
@@ -1006,11 +1100,6 @@ module Parser
|
|
1006
1100
|
end
|
1007
1101
|
end
|
1008
1102
|
|
1009
|
-
def method_ref(receiver, dot_t, selector_t)
|
1010
|
-
n(:meth_ref, [ receiver, value(selector_t).to_sym ],
|
1011
|
-
send_map(receiver, dot_t, selector_t, nil, [], nil))
|
1012
|
-
end
|
1013
|
-
|
1014
1103
|
#
|
1015
1104
|
# Control flow
|
1016
1105
|
#
|
@@ -1203,6 +1292,209 @@ module Parser
|
|
1203
1292
|
end
|
1204
1293
|
end
|
1205
1294
|
|
1295
|
+
#
|
1296
|
+
# PATTERN MATCHING
|
1297
|
+
#
|
1298
|
+
|
1299
|
+
def case_match(case_t, expr, in_bodies, else_t, else_body, end_t)
|
1300
|
+
else_body = n(:empty_else, nil, token_map(else_t)) if else_t && !else_body
|
1301
|
+
n(:case_match, [ expr, *(in_bodies << else_body)],
|
1302
|
+
condition_map(case_t, expr, nil, nil, else_t, else_body, end_t))
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
def in_match(lhs, in_t, rhs)
|
1306
|
+
n(:in_match, [lhs, rhs],
|
1307
|
+
binary_op_map(lhs, in_t, rhs))
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
def in_pattern(in_t, pattern, guard, then_t, body)
|
1311
|
+
children = [pattern, guard, body]
|
1312
|
+
n(:in_pattern, children,
|
1313
|
+
keyword_map(in_t, then_t, children.compact, nil))
|
1314
|
+
end
|
1315
|
+
|
1316
|
+
def if_guard(if_t, if_body)
|
1317
|
+
n(:if_guard, [if_body], guard_map(if_t, if_body))
|
1318
|
+
end
|
1319
|
+
|
1320
|
+
def unless_guard(unless_t, unless_body)
|
1321
|
+
n(:unless_guard, [unless_body], guard_map(unless_t, unless_body))
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
def match_var(name_t)
|
1325
|
+
name = value(name_t).to_sym
|
1326
|
+
name_l = loc(name_t)
|
1327
|
+
|
1328
|
+
check_lvar_name(name, name_l)
|
1329
|
+
check_duplicate_pattern_variable(name, name_l)
|
1330
|
+
@parser.static_env.declare(name)
|
1331
|
+
|
1332
|
+
n(:match_var, [ name ],
|
1333
|
+
variable_map(name_t))
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
def match_hash_var(name_t)
|
1337
|
+
name = value(name_t).to_sym
|
1338
|
+
|
1339
|
+
expr_l = loc(name_t)
|
1340
|
+
name_l = expr_l.adjust(end_pos: -1)
|
1341
|
+
|
1342
|
+
check_lvar_name(name, name_l)
|
1343
|
+
check_duplicate_pattern_variable(name, name_l)
|
1344
|
+
@parser.static_env.declare(name)
|
1345
|
+
|
1346
|
+
n(:match_var, [ name ],
|
1347
|
+
Source::Map::Variable.new(name_l, expr_l))
|
1348
|
+
end
|
1349
|
+
|
1350
|
+
def match_hash_var_from_str(begin_t, strings, end_t)
|
1351
|
+
if strings.length > 1
|
1352
|
+
diagnostic :error, :pm_interp_in_var_name, nil, loc(begin_t).join(loc(end_t))
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
string = strings[0]
|
1356
|
+
|
1357
|
+
case string.type
|
1358
|
+
when :str
|
1359
|
+
# MRI supports plain strings in hash pattern matching
|
1360
|
+
name, = *string
|
1361
|
+
name_l = string.loc.expression
|
1362
|
+
|
1363
|
+
check_lvar_name(name, name_l)
|
1364
|
+
check_duplicate_pattern_variable(name, name_l)
|
1365
|
+
|
1366
|
+
@parser.static_env.declare(name)
|
1367
|
+
|
1368
|
+
if (begin_l = string.loc.begin)
|
1369
|
+
# exclude beginning of the string from the location of the variable
|
1370
|
+
name_l = name_l.adjust(begin_pos: begin_l.length)
|
1371
|
+
end
|
1372
|
+
|
1373
|
+
if (end_l = string.loc.end)
|
1374
|
+
# exclude end of the string from the location of the variable
|
1375
|
+
name_l = name_l.adjust(end_pos: -end_l.length)
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
expr_l = loc(begin_t).join(string.loc.expression).join(loc(end_t))
|
1379
|
+
n(:match_var, [ name.to_sym ],
|
1380
|
+
Source::Map::Variable.new(name_l, expr_l))
|
1381
|
+
when :begin
|
1382
|
+
match_hash_var_from_str(begin_t, string.children, end_t)
|
1383
|
+
else
|
1384
|
+
# we only can get here if there is an interpolation, e.g., ``in "#{ a }":`
|
1385
|
+
diagnostic :error, :pm_interp_in_var_name, nil, loc(begin_t).join(loc(end_t))
|
1386
|
+
end
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
def match_rest(star_t, name_t = nil)
|
1390
|
+
if name_t.nil?
|
1391
|
+
n0(:match_rest,
|
1392
|
+
unary_op_map(star_t))
|
1393
|
+
else
|
1394
|
+
name = match_var(name_t)
|
1395
|
+
n(:match_rest, [ name ],
|
1396
|
+
unary_op_map(star_t, name))
|
1397
|
+
end
|
1398
|
+
end
|
1399
|
+
|
1400
|
+
def hash_pattern(lbrace_t, kwargs, rbrace_t)
|
1401
|
+
args = check_duplicate_args(kwargs)
|
1402
|
+
n(:hash_pattern, args,
|
1403
|
+
collection_map(lbrace_t, args, rbrace_t))
|
1404
|
+
end
|
1405
|
+
|
1406
|
+
def array_pattern(lbrack_t, elements, rbrack_t)
|
1407
|
+
return n(:array_pattern, nil, collection_map(lbrack_t, [], rbrack_t)) if elements.nil?
|
1408
|
+
|
1409
|
+
trailing_comma = false
|
1410
|
+
|
1411
|
+
node_elements = elements.map do |element|
|
1412
|
+
if element.type == :match_with_trailing_comma
|
1413
|
+
trailing_comma = true
|
1414
|
+
element.children.first
|
1415
|
+
else
|
1416
|
+
trailing_comma = false
|
1417
|
+
element
|
1418
|
+
end
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
node_type = trailing_comma ? :array_pattern_with_tail : :array_pattern
|
1422
|
+
|
1423
|
+
n(node_type, node_elements,
|
1424
|
+
collection_map(lbrack_t, elements, rbrack_t))
|
1425
|
+
end
|
1426
|
+
|
1427
|
+
def find_pattern(lbrack_t, elements, rbrack_t)
|
1428
|
+
n(:find_pattern, elements,
|
1429
|
+
collection_map(lbrack_t, elements, rbrack_t))
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
def match_with_trailing_comma(match, comma_t)
|
1433
|
+
n(:match_with_trailing_comma, [ match ], expr_map(match.loc.expression.join(loc(comma_t))))
|
1434
|
+
end
|
1435
|
+
|
1436
|
+
def const_pattern(const, ldelim_t, pattern, rdelim_t)
|
1437
|
+
n(:const_pattern, [const, pattern],
|
1438
|
+
Source::Map::Collection.new(
|
1439
|
+
loc(ldelim_t), loc(rdelim_t),
|
1440
|
+
const.loc.expression.join(loc(rdelim_t))
|
1441
|
+
)
|
1442
|
+
)
|
1443
|
+
end
|
1444
|
+
|
1445
|
+
def pin(pin_t, var)
|
1446
|
+
n(:pin, [ var ],
|
1447
|
+
send_unary_op_map(pin_t, var))
|
1448
|
+
end
|
1449
|
+
|
1450
|
+
def match_alt(left, pipe_t, right)
|
1451
|
+
source_map = binary_op_map(left, pipe_t, right)
|
1452
|
+
|
1453
|
+
n(:match_alt, [ left, right ],
|
1454
|
+
source_map)
|
1455
|
+
end
|
1456
|
+
|
1457
|
+
def match_as(value, assoc_t, as)
|
1458
|
+
source_map = binary_op_map(value, assoc_t, as)
|
1459
|
+
|
1460
|
+
n(:match_as, [ value, as ],
|
1461
|
+
source_map)
|
1462
|
+
end
|
1463
|
+
|
1464
|
+
def match_nil_pattern(dstar_t, nil_t)
|
1465
|
+
n0(:match_nil_pattern,
|
1466
|
+
arg_prefix_map(dstar_t, nil_t))
|
1467
|
+
end
|
1468
|
+
|
1469
|
+
def match_pair(label_type, label, value)
|
1470
|
+
if label_type == :label
|
1471
|
+
check_duplicate_pattern_key(label[0], label[1])
|
1472
|
+
pair_keyword(label, value)
|
1473
|
+
else
|
1474
|
+
begin_t, parts, end_t = label
|
1475
|
+
label_loc = loc(begin_t).join(loc(end_t))
|
1476
|
+
|
1477
|
+
# quoted label like "label": value
|
1478
|
+
if (var_name = static_string(parts))
|
1479
|
+
check_duplicate_pattern_key(var_name, label_loc)
|
1480
|
+
else
|
1481
|
+
diagnostic :error, :pm_interp_in_var_name, nil, label_loc
|
1482
|
+
end
|
1483
|
+
|
1484
|
+
pair_quoted(begin_t, parts, end_t, value)
|
1485
|
+
end
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
def match_label(label_type, label)
|
1489
|
+
if label_type == :label
|
1490
|
+
match_hash_var(label)
|
1491
|
+
else
|
1492
|
+
# quoted label like "label": value
|
1493
|
+
begin_t, strings, end_t = label
|
1494
|
+
match_hash_var_from_str(begin_t, strings, end_t)
|
1495
|
+
end
|
1496
|
+
end
|
1497
|
+
|
1206
1498
|
private
|
1207
1499
|
|
1208
1500
|
#
|
@@ -1292,6 +1584,31 @@ module Parser
|
|
1292
1584
|
end
|
1293
1585
|
end
|
1294
1586
|
|
1587
|
+
def check_assignment_to_numparam(name, loc)
|
1588
|
+
# MRI < 2.7 treats numbered parameters as regular variables
|
1589
|
+
# and so it's allowed to perform assignments like `_1 = 42`.
|
1590
|
+
return if @parser.version < 27
|
1591
|
+
|
1592
|
+
assigning_to_numparam =
|
1593
|
+
@parser.context.in_dynamic_block? &&
|
1594
|
+
name =~ /\A_([1-9])\z/ &&
|
1595
|
+
@parser.max_numparam_stack.has_numparams?
|
1596
|
+
|
1597
|
+
if assigning_to_numparam
|
1598
|
+
diagnostic :error, :cant_assign_to_numparam, { :name => name }, loc
|
1599
|
+
end
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
def check_reserved_for_numparam(name, loc)
|
1603
|
+
# MRI < 3.0 accepts assignemnt to variables like _1
|
1604
|
+
# if it's not a numbererd parameter. MRI 3.0 and newer throws an error.
|
1605
|
+
return if @parser.version < 30
|
1606
|
+
|
1607
|
+
if name =~ /\A_([1-9])\z/
|
1608
|
+
diagnostic :error, :reserved_for_numparam, { :name => name }, loc
|
1609
|
+
end
|
1610
|
+
end
|
1611
|
+
|
1295
1612
|
def arg_name_collides?(this_name, that_name)
|
1296
1613
|
case @parser.version
|
1297
1614
|
when 18
|
@@ -1307,6 +1624,32 @@ module Parser
|
|
1307
1624
|
end
|
1308
1625
|
end
|
1309
1626
|
|
1627
|
+
def check_lvar_name(name, loc)
|
1628
|
+
if name =~ /\A[[[:lower:]]|_][[[:alnum:]]_]*\z/
|
1629
|
+
# OK
|
1630
|
+
else
|
1631
|
+
diagnostic :error, :lvar_name, { name: name }, loc
|
1632
|
+
end
|
1633
|
+
end
|
1634
|
+
|
1635
|
+
def check_duplicate_pattern_variable(name, loc)
|
1636
|
+
return if name.to_s.start_with?('_')
|
1637
|
+
|
1638
|
+
if @parser.pattern_variables.declared?(name)
|
1639
|
+
diagnostic :error, :duplicate_variable_name, { name: name.to_s }, loc
|
1640
|
+
end
|
1641
|
+
|
1642
|
+
@parser.pattern_variables.declare(name)
|
1643
|
+
end
|
1644
|
+
|
1645
|
+
def check_duplicate_pattern_key(name, loc)
|
1646
|
+
if @parser.pattern_hash_keys.declared?(name)
|
1647
|
+
diagnostic :error, :duplicate_pattern_key, { name: name.to_s }, loc
|
1648
|
+
end
|
1649
|
+
|
1650
|
+
@parser.pattern_hash_keys.declare(name)
|
1651
|
+
end
|
1652
|
+
|
1310
1653
|
#
|
1311
1654
|
# SOURCE MAPS
|
1312
1655
|
#
|
@@ -1496,9 +1839,17 @@ module Parser
|
|
1496
1839
|
end
|
1497
1840
|
|
1498
1841
|
def definition_map(keyword_t, operator_t, name_t, end_t)
|
1499
|
-
Source::Map::
|
1500
|
-
|
1501
|
-
|
1842
|
+
Source::Map::MethodDefinition.new(loc(keyword_t),
|
1843
|
+
loc(operator_t), loc(name_t),
|
1844
|
+
loc(end_t), nil, nil)
|
1845
|
+
end
|
1846
|
+
|
1847
|
+
def endless_definition_map(keyword_t, operator_t, name_t, assignment_t, body_e)
|
1848
|
+
body_l = body_e.loc.expression
|
1849
|
+
|
1850
|
+
Source::Map::MethodDefinition.new(loc(keyword_t),
|
1851
|
+
loc(operator_t), loc(name_t), nil,
|
1852
|
+
loc(assignment_t), body_l)
|
1502
1853
|
end
|
1503
1854
|
|
1504
1855
|
def send_map(receiver_e, dot_t, selector_t, begin_t=nil, args=[], end_t=nil)
|
@@ -1655,6 +2006,13 @@ module Parser
|
|
1655
2006
|
begin_l.join(end_l))
|
1656
2007
|
end
|
1657
2008
|
|
2009
|
+
def guard_map(keyword_t, guard_body_e)
|
2010
|
+
keyword_l = loc(keyword_t)
|
2011
|
+
guard_body_l = guard_body_e.loc.expression
|
2012
|
+
|
2013
|
+
Source::Map::Keyword.new(keyword_l, nil, nil, keyword_l.join(guard_body_l))
|
2014
|
+
end
|
2015
|
+
|
1658
2016
|
#
|
1659
2017
|
# HELPERS
|
1660
2018
|
#
|
@@ -1736,6 +2094,18 @@ module Parser
|
|
1736
2094
|
@parser.send :yyerror
|
1737
2095
|
end
|
1738
2096
|
end
|
2097
|
+
|
2098
|
+
def validate_definee(definee)
|
2099
|
+
case definee.type
|
2100
|
+
when :int, :str, :dstr, :sym, :dsym,
|
2101
|
+
:regexp, :array, :hash
|
2102
|
+
|
2103
|
+
diagnostic :error, :singleton_literal, nil, definee.loc.expression
|
2104
|
+
false
|
2105
|
+
else
|
2106
|
+
true
|
2107
|
+
end
|
2108
|
+
end
|
1739
2109
|
end
|
1740
2110
|
|
1741
2111
|
end
|