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.
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