parser 2.6.5.0 → 2.7.2.0
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 -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
|