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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/lib/parser.rb +4 -1
  3. data/lib/parser/all.rb +1 -0
  4. data/lib/parser/ast/processor.rb +21 -0
  5. data/lib/parser/base.rb +25 -5
  6. data/lib/parser/builders/default.rb +394 -24
  7. data/lib/parser/context.rb +5 -0
  8. data/lib/parser/current.rb +16 -7
  9. data/lib/parser/current_arg_stack.rb +43 -0
  10. data/lib/parser/diagnostic.rb +1 -1
  11. data/lib/parser/diagnostic/engine.rb +1 -2
  12. data/lib/parser/lexer.rb +23770 -0
  13. data/lib/parser/lexer/dedenter.rb +52 -49
  14. data/lib/parser/macruby.rb +6149 -0
  15. data/lib/parser/{lexer/max_numparam_stack.rb → max_numparam_stack.rb} +10 -4
  16. data/lib/parser/messages.rb +52 -29
  17. data/lib/parser/meta.rb +10 -5
  18. data/lib/parser/ruby18.rb +5663 -0
  19. data/lib/parser/ruby19.rb +6092 -0
  20. data/lib/parser/ruby20.rb +6527 -0
  21. data/lib/parser/ruby21.rb +6578 -0
  22. data/lib/parser/ruby22.rb +6613 -0
  23. data/lib/parser/ruby23.rb +6624 -0
  24. data/lib/parser/ruby24.rb +6694 -0
  25. data/lib/parser/ruby25.rb +6662 -0
  26. data/lib/parser/ruby26.rb +6676 -0
  27. data/lib/parser/ruby27.rb +7803 -0
  28. data/lib/parser/ruby28.rb +8047 -0
  29. data/lib/parser/ruby30.rb +8052 -0
  30. data/lib/parser/rubymotion.rb +6086 -0
  31. data/lib/parser/runner.rb +26 -2
  32. data/lib/parser/runner/ruby_rewrite.rb +2 -2
  33. data/lib/parser/source/buffer.rb +3 -1
  34. data/lib/parser/source/comment.rb +1 -1
  35. data/lib/parser/source/comment/associator.rb +14 -4
  36. data/lib/parser/source/map/method_definition.rb +25 -0
  37. data/lib/parser/source/range.rb +19 -3
  38. data/lib/parser/source/tree_rewriter.rb +115 -12
  39. data/lib/parser/source/tree_rewriter/action.rb +137 -28
  40. data/lib/parser/static_environment.rb +10 -0
  41. data/lib/parser/tree_rewriter.rb +1 -2
  42. data/lib/parser/variables_stack.rb +32 -0
  43. data/lib/parser/version.rb +1 -1
  44. data/parser.gemspec +10 -18
  45. metadata +22 -99
  46. data/.gitignore +0 -33
  47. data/.travis.yml +0 -45
  48. data/.yardopts +0 -21
  49. data/CHANGELOG.md +0 -997
  50. data/CONTRIBUTING.md +0 -17
  51. data/Gemfile +0 -10
  52. data/LICENSE.txt +0 -25
  53. data/README.md +0 -301
  54. data/Rakefile +0 -166
  55. data/ci/run_rubocop_specs +0 -14
  56. data/doc/AST_FORMAT.md +0 -1816
  57. data/doc/CUSTOMIZATION.md +0 -37
  58. data/doc/INTERNALS.md +0 -21
  59. data/doc/css/.gitkeep +0 -0
  60. data/doc/css/common.css +0 -68
  61. data/lib/parser/lexer.rl +0 -2533
  62. data/lib/parser/macruby.y +0 -2198
  63. data/lib/parser/ruby18.y +0 -1934
  64. data/lib/parser/ruby19.y +0 -2175
  65. data/lib/parser/ruby20.y +0 -2353
  66. data/lib/parser/ruby21.y +0 -2357
  67. data/lib/parser/ruby22.y +0 -2364
  68. data/lib/parser/ruby23.y +0 -2370
  69. data/lib/parser/ruby24.y +0 -2408
  70. data/lib/parser/ruby25.y +0 -2405
  71. data/lib/parser/ruby26.y +0 -2413
  72. data/lib/parser/ruby27.y +0 -2470
  73. data/lib/parser/rubymotion.y +0 -2182
  74. data/test/bug_163/fixtures/input.rb +0 -5
  75. data/test/bug_163/fixtures/output.rb +0 -5
  76. data/test/bug_163/rewriter.rb +0 -20
  77. data/test/helper.rb +0 -59
  78. data/test/parse_helper.rb +0 -316
  79. data/test/racc_coverage_helper.rb +0 -133
  80. data/test/test_base.rb +0 -31
  81. data/test/test_current.rb +0 -29
  82. data/test/test_diagnostic.rb +0 -96
  83. data/test/test_diagnostic_engine.rb +0 -62
  84. data/test/test_encoding.rb +0 -99
  85. data/test/test_lexer.rb +0 -3667
  86. data/test/test_lexer_stack_state.rb +0 -78
  87. data/test/test_parse_helper.rb +0 -80
  88. data/test/test_parser.rb +0 -7644
  89. data/test/test_runner_parse.rb +0 -35
  90. data/test/test_runner_rewrite.rb +0 -47
  91. data/test/test_source_buffer.rb +0 -162
  92. data/test/test_source_comment.rb +0 -36
  93. data/test/test_source_comment_associator.rb +0 -367
  94. data/test/test_source_map.rb +0 -15
  95. data/test/test_source_range.rb +0 -172
  96. data/test/test_source_rewriter.rb +0 -541
  97. data/test/test_source_rewriter_action.rb +0 -46
  98. data/test/test_source_tree_rewriter.rb +0 -173
  99. data/test/test_static_environment.rb +0 -45
  100. data/test/using_tree_rewriter/fixtures/input.rb +0 -3
  101. data/test/using_tree_rewriter/fixtures/output.rb +0 -3
  102. 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: c12b17e36f142aa8aacc1aae95cd464ea9239cf526d973b7b1ed3f0825fc7698
4
- data.tar.gz: 49948dbdc512a19d0b02d5edea2e12ff4eed8c89a2827728e5f0f9a618109b44
3
+ metadata.gz: 3efc381a3ad92df723e4a698afbceb63f65fdb7c892f690dbd569ba298307d8b
4
+ data.tar.gz: b9e78eb7dd39f6539fc21883fbec26b1a0c2d377c68bf060d485df5521318e54
5
5
  SHA512:
6
- metadata.gz: 67bbf82221c9795d5a892f51ccb3c51835657448842a078bbcee88b8b1ef649643600d01d2c1c0b2e59982a774803a3a780538c433e8cc3a4fdfe8168838a697
7
- data.tar.gz: 9d7053f65800e04f8f2c0b1f344d9f83efd1282744aba49c02b384ea4242a3bcc5b65b7ac3eca4c4d0c34317ed70393a1eb26e146b34517ad75810b9498eb0a7
6
+ metadata.gz: 3c9b2d1df5a463c289f2881c0064c956e88560bc14af30bbb9fe3828ae7a3e1f8a88352172e353b196f34ba1e98640b6bf38bcbb50bef0f8661aacf9e8ccdc1b
7
+ data.tar.gz: e394d70911b7d86ee7049b0ecaab839120da2f90372630e48c6bb3c14f3b45b35322a2d99ca516df6cc2e8a8e7c0c79aca1031c3dfa28b0026c300ea10b51ed4
@@ -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
 
@@ -10,3 +10,4 @@ require 'parser/ruby24'
10
10
  require 'parser/ruby25'
11
11
  require 'parser/ruby26'
12
12
  require 'parser/ruby27'
13
+ require 'parser/ruby30'
@@ -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
@@ -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. If `recover` is true and a fatal
195
- # {SyntaxError} is encountered, `nil` is returned instead of the AST, and
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
- @emit_index = false
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
- case definee.type
656
- when :int, :str, :dstr, :sym, :dsym,
657
- :regexp, :array, :hash
712
+ validate_definee(definee)
713
+ check_reserved_for_numparam(value(name_t), loc(name_t))
658
714
 
659
- diagnostic :error, :singleton_literal, nil, definee.loc.expression
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
- else
662
- n(:defs, [ definee, value(name_t).to_sym, args, body ],
663
- definition_map(def_t, dot_t, name_t, end_t))
664
- end
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::Definition.new(loc(keyword_t),
1500
- loc(operator_t), loc(name_t),
1501
- loc(end_t))
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