parser 2.7.1.0 → 2.7.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -11
  3. data/CHANGELOG.md +70 -1
  4. data/README.md +2 -2
  5. data/Rakefile +2 -1
  6. data/doc/AST_FORMAT.md +107 -3
  7. data/lib/parser.rb +1 -0
  8. data/lib/parser/all.rb +1 -0
  9. data/lib/parser/ast/processor.rb +2 -0
  10. data/lib/parser/base.rb +6 -5
  11. data/lib/parser/builders/default.rb +146 -19
  12. data/lib/parser/context.rb +1 -0
  13. data/lib/parser/current.rb +9 -0
  14. data/lib/parser/diagnostic.rb +1 -1
  15. data/lib/parser/diagnostic/engine.rb +1 -2
  16. data/lib/parser/lexer.rb +23770 -0
  17. data/lib/parser/lexer.rl +15 -1
  18. data/lib/parser/macruby.rb +6149 -0
  19. data/lib/parser/macruby.y +15 -5
  20. data/lib/parser/max_numparam_stack.rb +1 -1
  21. data/lib/parser/messages.rb +17 -0
  22. data/lib/parser/meta.rb +3 -3
  23. data/lib/parser/ruby18.rb +5663 -0
  24. data/lib/parser/ruby18.y +3 -1
  25. data/lib/parser/ruby19.rb +6092 -0
  26. data/lib/parser/ruby19.y +15 -5
  27. data/lib/parser/ruby20.rb +6527 -0
  28. data/lib/parser/ruby20.y +15 -5
  29. data/lib/parser/ruby21.rb +6578 -0
  30. data/lib/parser/ruby21.y +10 -3
  31. data/lib/parser/ruby22.rb +6613 -0
  32. data/lib/parser/ruby22.y +10 -3
  33. data/lib/parser/ruby23.rb +6624 -0
  34. data/lib/parser/ruby23.y +10 -3
  35. data/lib/parser/ruby24.rb +6694 -0
  36. data/lib/parser/ruby24.y +10 -3
  37. data/lib/parser/ruby25.rb +6662 -0
  38. data/lib/parser/ruby25.y +10 -3
  39. data/lib/parser/ruby26.rb +6676 -0
  40. data/lib/parser/ruby26.y +10 -3
  41. data/lib/parser/ruby27.rb +7803 -0
  42. data/lib/parser/ruby27.y +16 -8
  43. data/lib/parser/ruby30.rb +8052 -0
  44. data/lib/parser/ruby30.y +3048 -0
  45. data/lib/parser/rubymotion.rb +6086 -0
  46. data/lib/parser/rubymotion.y +15 -5
  47. data/lib/parser/runner.rb +26 -2
  48. data/lib/parser/runner/ruby_rewrite.rb +2 -2
  49. data/lib/parser/source/buffer.rb +3 -1
  50. data/lib/parser/source/comment.rb +1 -1
  51. data/lib/parser/source/comment/associator.rb +14 -4
  52. data/lib/parser/source/map/method_definition.rb +25 -0
  53. data/lib/parser/source/range.rb +19 -3
  54. data/lib/parser/source/tree_rewriter.rb +115 -12
  55. data/lib/parser/source/tree_rewriter/action.rb +135 -26
  56. data/lib/parser/tree_rewriter.rb +1 -2
  57. data/lib/parser/version.rb +1 -1
  58. data/parser.gemspec +6 -2
  59. data/test/helper.rb +49 -6
  60. data/test/parse_helper.rb +49 -40
  61. data/test/test_ast_processor.rb +32 -0
  62. data/test/test_base.rb +1 -1
  63. data/test/test_current.rb +2 -0
  64. data/test/test_diagnostic.rb +6 -7
  65. data/test/test_diagnostic_engine.rb +5 -8
  66. data/test/test_lexer.rb +17 -8
  67. data/test/test_meta.rb +12 -0
  68. data/test/test_parse_helper.rb +12 -9
  69. data/test/test_parser.rb +612 -56
  70. data/test/test_runner_parse.rb +22 -1
  71. data/test/test_runner_rewrite.rb +1 -1
  72. data/test/test_source_buffer.rb +4 -1
  73. data/test/test_source_comment.rb +2 -2
  74. data/test/test_source_comment_associator.rb +47 -15
  75. data/test/test_source_map.rb +1 -2
  76. data/test/test_source_range.rb +29 -9
  77. data/test/test_source_rewriter.rb +4 -4
  78. data/test/test_source_rewriter_action.rb +2 -2
  79. data/test/test_source_tree_rewriter.rb +201 -13
  80. metadata +19 -13
  81. data/.gitignore +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46184af7a1e0d843e62e720cd7795bb196972603e588eed69f47791b3c799288
4
- data.tar.gz: 1a9d809fc7443fb09deb3a36ea19ad418ff56119040b14a292c9ed8d112d1f29
3
+ metadata.gz: 58735baf961ddf249964c59136cdfc0c5abbb15f09e2d09c591442cad5e559fb
4
+ data.tar.gz: f77b0c5380882d193b3e20f383eecaa92fd9a3807ca8b85154138677a493b02f
5
5
  SHA512:
6
- metadata.gz: 9a91995ac131a4048976358a7bce1bd09b09893bb0b13fa39f2128c47fb0b1179f830a4adbb766df768bfbd2f89a1c5a5ee437dc1433ccaf5ad2307ff7c09d77
7
- data.tar.gz: 4fe835bc9fe1ff030d57e9a4d9a4657a0d244db23bac3c117e8f78bfc51d9dc330f51257e04c8ba5ef737d3feab11152db2e1ecde1e8b136d4fcc4f253ed549d
6
+ metadata.gz: 702a6fe61f52f33fcbd3324a347fa4ffa5f3677503b53324637502db1d762c8007f2e45fdf57745f520d48e2ec1f48913f31ad1b1e5f360115d0fc4634532bb7
7
+ data.tar.gz: eb549a8defabd4dccd7ee746b32b59886b12380d370a5293dcc3f3ab3cad39b959d65e7cc2c72a8e366fb67102930eaf84cf104ff8361b95a97939eb39c1dc71
@@ -1,9 +1,15 @@
1
1
  dist: trusty
2
2
  language: ruby
3
- matrix:
3
+ jobs:
4
4
  include:
5
- - name: 2.4.9 / Parser tests
6
- rvm: 2.4.9
5
+ - name: jruby-9.1.15.0 / Parser tests
6
+ rvm: jruby-9.1.15.0
7
+ script: bundle exec rake test
8
+ - name: truffleruby / Parser tests
9
+ rvm: truffleruby
10
+ script: TRUFFLERUBYOPT=--engine.Mode=latency bundle exec rake test
11
+ - name: 2.4.10 / Parser tests
12
+ rvm: 2.4.10
7
13
  script: bundle exec rake test_cov
8
14
  - name: 2.5.8 / Parser tests
9
15
  rvm: 2.5.8
@@ -17,12 +23,6 @@ matrix:
17
23
  - name: ruby-head / Parser tests
18
24
  rvm: ruby-head
19
25
  script: bundle exec rake test_cov
20
- - name: jruby-9.1.15.0 / Parser tests
21
- rvm: jruby-9.1.15.0
22
- script: bundle exec rake test_cov
23
- - name: rbx-2 / Parser tests
24
- rvm: rbx-2
25
- script: bundle exec rake test_cov
26
26
  - name: 2.5.8 / Rubocop tests
27
27
  rvm: 2.5.8
28
28
  script: ./ci/run_rubocop_specs
@@ -34,9 +34,8 @@ matrix:
34
34
  script: ./ci/run_rubocop_specs
35
35
  allow_failures:
36
36
  - rvm: ruby-head
37
- - rvm: rbx-2
37
+ - rvm: truffleruby
38
38
  - script: ./ci/run_rubocop_specs
39
39
  before_install:
40
- - gem install bundler -v '< 2'
41
40
  - bundle --version
42
41
  - gem --version
@@ -1,9 +1,78 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- Not released (2020-04-03)
4
+ Not released (2020-09-24)
5
5
  -------------------------
6
6
 
7
+ API modifications:
8
+ * right assignment: use existing AST node types (#738) (#739) (Marc-André Lafortune)
9
+ * ruby28.y -> ruby30.y (#729) (Vladimir Dementyev)
10
+
11
+ Features implemented:
12
+ * Optimize Range#column_range (#741) (Marc-André Lafortune)
13
+ * ruby30.y: reject endless setter. (#736) (Ilya Bylich)
14
+ * ruby28.y: reject assignment to numparam. (#725) (Ilya Bylich)
15
+ * emit "endless method def" as `:def` node. (#716) (Ilya Bylich)
16
+
17
+ Bugs fixed:
18
+ * rename 2.8 to 3.0 everywhere (#732) (Ilya Bylich)
19
+ * test_current.rb: 2.8 -> 3.0 (#731) (Vladimir Dementyev)
20
+ * Parser#parse returns nil instead of false if error is thrown (#722) (Marc-André Lafortune)
21
+ * unify locations for normal and endless method definition (#718) (Marc-André Lafortune)
22
+ * ruby27.y: accept const names as hash keys for pattern matching (#717) (Koichi ITO)
23
+ * Fix locations for alias / undef nodes with internal symbols (#715) (Marc-André Lafortune)
24
+
25
+ v2.7.1.4 (2020-06-19)
26
+ ---------------------
27
+
28
+ Features implemented:
29
+ * ruby28.y: add find pattern. (#714) (Ilya Bylich)
30
+ * lexer.rl: reject `->...` and `->(...)` with the same error. (#713) (Ilya Bylich)
31
+ * ruby28.y: accept leading args before forward arg. (#712) (Ilya Bylich)
32
+ * Added `emit_forward_arg` compatibility flag. (#710) (Ilya Bylich)
33
+ * ruby28.y: include entire lambda expr in lambda rule. (#708) (Ilya Bylich)
34
+ * ruby28.y: extracted excessed_comma rule. (#706) (Ilya Bylich)
35
+ * Source::TreeRewriter: Improved merging and representations (#703) (Marc-André Lafortune)
36
+
37
+ Bugs fixed:
38
+ * ruby*.y: fixed context inside lambda args and module. (#709) (Ilya Bylich)
39
+
40
+ v2.7.1.3 (2020-05-26)
41
+ ---------------------
42
+
43
+ API modifications:
44
+ * fixed all warnings. tests are running in verbose mode now. (#685) (Ilya Bylich)
45
+
46
+ Features implemented:
47
+ * ruby-[parse, rewrite]: add legacy switches (#699) (Marc-André Lafortune)
48
+ * Added Parser::Source::Range#to_range. (#697) (Ilya Bylich)
49
+ * ruby28.y: support rescue modifier in endless method definition. (#696) (Ilya Bylich)
50
+ * ruby28.y: unify kwrest and no-kwrest rules. (#694) (Ilya Bylich)
51
+ * ruby28.y: add right hand assignment (#682) (Vladimir Dementyev)
52
+
53
+ Bugs fixed:
54
+ * fix Comment.associate for postfix conditions/loops (#688) (Marc-André Lafortune)
55
+
56
+ v2.7.1.2 (2020-04-30)
57
+ ---------------------
58
+
59
+ Features implemented:
60
+ * ruby28.y: endless method definition (#676) (Vladimir Dementyev)
61
+ * ruby28.y: branch parser (#677) (Vladimir Dementyev)
62
+
63
+ Bugs fixed:
64
+ * ruby27.y: reject invalid lvar in pattern matching (#680) (Vladimir Dementyev)
65
+
66
+ v2.7.1.1 (2020-04-15)
67
+ ---------------------
68
+
69
+ Features implemented:
70
+ * Add Source::Range#eql? and hash (#675) (Marc-André Lafortune)
71
+ * Source::TreeRewriter: Add #merge, #merge! and #empty? (#674) (Marc-André Lafortune)
72
+
73
+ v2.7.1.0 (2020-04-03)
74
+ ---------------------
75
+
7
76
  API modifications:
8
77
  * Bump ruby versions to 2.4.10, 2.5.8, 2.6.6, 2.7.1. (#665) (Ilya Bylich)
9
78
 
data/README.md CHANGED
@@ -29,6 +29,7 @@ below for explanation of `emit_*` calls):
29
29
  Parser::Builders::Default.emit_encoding = true
30
30
  Parser::Builders::Default.emit_index = true
31
31
  Parser::Builders::Default.emit_arg_inside_procarg0 = true
32
+ Parser::Builders::Default.emit_forward_arg = true
32
33
 
33
34
  Parse a chunk of code:
34
35
 
@@ -59,8 +60,7 @@ Parse a chunk of code and display all diagnostics:
59
60
  puts diag.render
60
61
  end
61
62
 
62
- buffer = Parser::Source::Buffer.new('(string)')
63
- buffer.source = "foo *bar"
63
+ buffer = Parser::Source::Buffer.new('(string)', source: "foo *bar")
64
64
 
65
65
  p parser.parse(buffer)
66
66
  # (string):1:5: warning: `*' interpreted as argument prefix
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ task :default => [:test]
11
11
  Rake::TestTask.new do |t|
12
12
  t.libs = %w(test/ lib/)
13
13
  t.test_files = FileList["test/**/test_*.rb"]
14
- t.warning = false
14
+ t.warning = true
15
15
  end
16
16
 
17
17
  task :test_cov do
@@ -32,6 +32,7 @@ GENERATED_FILES = %w(lib/parser/lexer.rb
32
32
  lib/parser/ruby25.rb
33
33
  lib/parser/ruby26.rb
34
34
  lib/parser/ruby27.rb
35
+ lib/parser/ruby30.rb
35
36
  lib/parser/macruby.rb
36
37
  lib/parser/rubymotion.rb)
37
38
 
@@ -637,7 +637,7 @@ Format:
637
637
  (masgn (mlhs (ivasgn :@a) (cvasgn :@@b)) (array (splat (lvar :c))))
638
638
  "@a, @@b = *c"
639
639
 
640
- (masgn (mlhs (mlhs (lvasgn :a) (lvasgn :b)) (lvasgn :c)) (lvar :d))
640
+ (masgn (mlhs (lvasgn :a) (mlhs (lvasgn :b)) (lvasgn :c)) (lvar :d))
641
641
  "a, (b, c) = d"
642
642
 
643
643
  (masgn (mlhs (send (self) :a=) (send (self) :[]= (int 1))) (lvar :a))
@@ -730,6 +730,29 @@ Format:
730
730
 
731
731
  ~~~
732
732
 
733
+ ### Right-hand assignment
734
+
735
+ Format:
736
+
737
+ ~~~
738
+ (lvasgn :a (int 1))
739
+ "1 => a"
740
+ ~~~~~~ expression
741
+ ~ name
742
+ ~~ operator
743
+ ~~~
744
+
745
+ #### Multiple right-hand assignment
746
+
747
+ Format:
748
+
749
+ ~~~
750
+ (masgn (mlhs (lvasgn :a) (lvasgn :b)) (send (int 13) :divmod (int 5)))
751
+ "13.divmod(5) => a,b"
752
+ ~~~~~~~~~~~~~~~~~~~ expression
753
+ ^^ operator
754
+ ~~~
755
+
733
756
  ## Class and module definition
734
757
 
735
758
  ### Module
@@ -802,6 +825,33 @@ Format:
802
825
  ~~~~~~~~~~~~~~~~~ expression
803
826
  ~~~
804
827
 
828
+ ### "Endless" method
829
+
830
+ Format:
831
+
832
+ ~~~
833
+ (def :foo (args) (int 42))
834
+ "def foo() = 42"
835
+ ~~~ keyword
836
+ ~~~ name
837
+ ^ assignment
838
+ ~~~~~~~~~~~~~~ expression
839
+ ~~~
840
+
841
+
842
+ ### "Endless" singleton method
843
+
844
+ Format:
845
+
846
+ ~~~
847
+ (defs (self) :foo (args) (int 42))
848
+ "def self.foo() = 42"
849
+ ~~~ keyword
850
+ ~~~ name
851
+ ^ assignment
852
+ ~~~~~~~~~~~~~~~~~~~ expression
853
+ ~~~
854
+
805
855
  ### Undefinition
806
856
 
807
857
  Format:
@@ -1115,13 +1165,13 @@ s(:numblock,
1115
1165
 
1116
1166
  ## Forward arguments
1117
1167
 
1118
- ### Method definition accepting forwarding arguments
1168
+ ### Method definition accepting only forwarding arguments
1119
1169
 
1120
1170
  Ruby 2.7 introduced a feature called "arguments forwarding".
1121
1171
  When a method takes any arguments for forwarding them in the future
1122
1172
  the whole `args` node gets replaced with `forward-args` node.
1123
1173
 
1124
- Format:
1174
+ Format if `emit_forward_arg` compatibility flag is disabled:
1125
1175
 
1126
1176
  ~~~
1127
1177
  (def :foo
@@ -1132,6 +1182,25 @@ Format:
1132
1182
  ~~~~~ expression
1133
1183
  ~~~
1134
1184
 
1185
+ However, Ruby 3.0 added support for leading arguments before `...`, and so
1186
+ it can't be used as a replacement of the `(args)` node anymore. To solve it
1187
+ `emit_forward_arg` should be enabled.
1188
+
1189
+ Format if `emit_forward_arg` compatibility flag is enabled:
1190
+
1191
+ ~~~
1192
+ (def :foo
1193
+ (args
1194
+ (forward-arg)) nil)
1195
+ "def foo(...); end"
1196
+ ~ begin (args)
1197
+ ~ end (args)
1198
+ ~~~~~ expression (args)
1199
+ ~~~ expression (forward_arg)
1200
+ ~~~
1201
+
1202
+ Note that the node is called `forward_arg` when emitted separately.
1203
+
1135
1204
  ### Method call taking arguments of the currently forwarding method
1136
1205
 
1137
1206
  Format:
@@ -2123,6 +2192,24 @@ Format:
2123
2192
  ~~~ name (match-nil-pattern)
2124
2193
  ~~~
2125
2194
 
2195
+ ### Matching using find pattern
2196
+
2197
+ Format:
2198
+
2199
+ ~~~
2200
+ (find-pattern
2201
+ (match-rest
2202
+ (match-var :a))
2203
+ (int 42)
2204
+ (match-rest))
2205
+ "in [*, 42, *]"
2206
+ ~ begin
2207
+ ~ end
2208
+ ~~~~~~~~~~ expression
2209
+ ~~~
2210
+
2211
+ Note that it can be used as a top-level pattern only when used in a `case` statement. In that case `begin` and `end` are empty.
2212
+
2126
2213
  ### Matching using const pattern
2127
2214
 
2128
2215
  #### With array pattern
@@ -2178,3 +2265,20 @@ Format:
2178
2265
  ~ expression (const-pattern.const)
2179
2266
  ~~ expression (const-pattern.array_pattern)
2180
2267
  ~~~
2268
+
2269
+ #### With find pattern
2270
+
2271
+ Format:
2272
+
2273
+ ~~~
2274
+ (const-pattern
2275
+ (const nil :X)
2276
+ (find-pattern
2277
+ (match-rest)
2278
+ (int 42)
2279
+ (match-rest)))
2280
+ "in X[*, 42, *]"
2281
+ ~ begin
2282
+ ~ end
2283
+ ~~~~~~~~~~~ expression
2284
+ ~~~
@@ -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'
@@ -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)
@@ -250,6 +251,7 @@ module Parser
250
251
  alias on_array_pattern_with_tail process_regular_node
251
252
  alias on_hash_pattern process_regular_node
252
253
  alias on_const_pattern process_regular_node
254
+ alias on_find_pattern process_regular_node
253
255
 
254
256
  # @private
255
257
  def process_variable_node(node)
@@ -177,16 +177,16 @@ module Parser
177
177
  end
178
178
 
179
179
  ##
180
- # 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.
181
181
  #
182
182
  # @param [Parser::Source::Buffer] source_buffer The source buffer to parse.
183
- # @return [Parser::AST::Node]
183
+ # @return [Parser::AST::Node, nil]
184
184
  #
185
185
  def parse(source_buffer)
186
186
  @lexer.source_buffer = source_buffer
187
187
  @source_buffer = source_buffer
188
188
 
189
- do_parse
189
+ do_parse || nil # Force `false` to `nil`, see https://github.com/ruby/racc/pull/136
190
190
  ensure
191
191
  # Don't keep references to the source file.
192
192
  @source_buffer = nil
@@ -210,8 +210,9 @@ module Parser
210
210
 
211
211
  ##
212
212
  # Parses a source buffer and returns the AST, the source code comments,
213
- # and the tokens emitted by the lexer. If `recover` is true and a fatal
214
- # {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
215
216
  # comments as well as tokens are only returned up to the location of
216
217
  # the error.
217
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
 
@@ -557,7 +589,11 @@ module Parser
557
589
  when :ident
558
590
  name, = *node
559
591
 
560
- check_assignment_to_numparam(node)
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)
561
597
 
562
598
  @parser.static_env.declare(name)
563
599
 
@@ -619,6 +655,14 @@ module Parser
619
655
  binary_op_map(lhs, eql_t, rhs))
620
656
  end
621
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
+
622
666
  #
623
667
  # Class and module definition
624
668
  #
@@ -648,23 +692,38 @@ module Parser
648
692
 
649
693
  def def_method(def_t, name_t, args,
650
694
  body, end_t)
695
+ check_reserved_for_numparam(value(name_t), loc(name_t))
696
+
651
697
  n(:def, [ value(name_t).to_sym, args, body ],
652
698
  definition_map(def_t, nil, name_t, end_t))
653
699
  end
654
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
+
655
709
  def def_singleton(def_t, definee, dot_t,
656
710
  name_t, args,
657
711
  body, end_t)
658
- case definee.type
659
- when :int, :str, :dstr, :sym, :dsym,
660
- :regexp, :array, :hash
712
+ validate_definee(definee)
713
+ check_reserved_for_numparam(value(name_t), loc(name_t))
661
714
 
662
- 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
663
718
 
664
- else
665
- n(:defs, [ definee, value(name_t).to_sym, args, body ],
666
- definition_map(def_t, dot_t, name_t, end_t))
667
- 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))
668
727
  end
669
728
 
670
729
  def undef_method(undef_t, names)
@@ -691,16 +750,30 @@ module Parser
691
750
  n(:numargs, [ max_numparam ], nil)
692
751
  end
693
752
 
694
- def forward_args(begin_t, dots_t, end_t)
695
- n(:forward_args, [], collection_map(begin_t, token_map(dots_t), end_t))
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))
696
765
  end
697
766
 
698
767
  def arg(name_t)
768
+ check_reserved_for_numparam(value(name_t), loc(name_t))
769
+
699
770
  n(:arg, [ value(name_t).to_sym ],
700
771
  variable_map(name_t))
701
772
  end
702
773
 
703
774
  def optarg(name_t, eql_t, value)
775
+ check_reserved_for_numparam(value(name_t), loc(name_t))
776
+
704
777
  n(:optarg, [ value(name_t).to_sym, value ],
705
778
  variable_map(name_t).
706
779
  with_operator(loc(eql_t)).
@@ -709,6 +782,7 @@ module Parser
709
782
 
710
783
  def restarg(star_t, name_t=nil)
711
784
  if name_t
785
+ check_reserved_for_numparam(value(name_t), loc(name_t))
712
786
  n(:restarg, [ value(name_t).to_sym ],
713
787
  arg_prefix_map(star_t, name_t))
714
788
  else
@@ -718,17 +792,23 @@ module Parser
718
792
  end
719
793
 
720
794
  def kwarg(name_t)
795
+ check_reserved_for_numparam(value(name_t), loc(name_t))
796
+
721
797
  n(:kwarg, [ value(name_t).to_sym ],
722
798
  kwarg_map(name_t))
723
799
  end
724
800
 
725
801
  def kwoptarg(name_t, value)
802
+ check_reserved_for_numparam(value(name_t), loc(name_t))
803
+
726
804
  n(:kwoptarg, [ value(name_t).to_sym, value ],
727
805
  kwarg_map(name_t, value))
728
806
  end
729
807
 
730
808
  def kwrestarg(dstar_t, name_t=nil)
731
809
  if name_t
810
+ check_reserved_for_numparam(value(name_t), loc(name_t))
811
+
732
812
  n(:kwrestarg, [ value(name_t).to_sym ],
733
813
  arg_prefix_map(dstar_t, name_t))
734
814
  else
@@ -743,11 +823,15 @@ module Parser
743
823
  end
744
824
 
745
825
  def shadowarg(name_t)
826
+ check_reserved_for_numparam(value(name_t), loc(name_t))
827
+
746
828
  n(:shadowarg, [ value(name_t).to_sym ],
747
829
  variable_map(name_t))
748
830
  end
749
831
 
750
832
  def blockarg(amper_t, name_t)
833
+ check_reserved_for_numparam(value(name_t), loc(name_t))
834
+
751
835
  n(:blockarg, [ value(name_t).to_sym ],
752
836
  arg_prefix_map(amper_t, name_t))
753
837
  end
@@ -1239,8 +1323,10 @@ module Parser
1239
1323
 
1240
1324
  def match_var(name_t)
1241
1325
  name = value(name_t).to_sym
1326
+ name_l = loc(name_t)
1242
1327
 
1243
- check_duplicate_pattern_variable(name, loc(name_t))
1328
+ check_lvar_name(name, name_l)
1329
+ check_duplicate_pattern_variable(name, name_l)
1244
1330
  @parser.static_env.declare(name)
1245
1331
 
1246
1332
  n(:match_var, [ name ],
@@ -1253,6 +1339,7 @@ module Parser
1253
1339
  expr_l = loc(name_t)
1254
1340
  name_l = expr_l.adjust(end_pos: -1)
1255
1341
 
1342
+ check_lvar_name(name, name_l)
1256
1343
  check_duplicate_pattern_variable(name, name_l)
1257
1344
  @parser.static_env.declare(name)
1258
1345
 
@@ -1293,6 +1380,9 @@ module Parser
1293
1380
  Source::Map::Variable.new(name_l, expr_l))
1294
1381
  when :begin
1295
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))
1296
1386
  end
1297
1387
  end
1298
1388
 
@@ -1334,6 +1424,11 @@ module Parser
1334
1424
  collection_map(lbrack_t, elements, rbrack_t))
1335
1425
  end
1336
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
+
1337
1432
  def match_with_trailing_comma(match, comma_t)
1338
1433
  n(:match_with_trailing_comma, [ match ], expr_map(match.loc.expression.join(loc(comma_t))))
1339
1434
  end
@@ -1489,8 +1584,10 @@ module Parser
1489
1584
  end
1490
1585
  end
1491
1586
 
1492
- def check_assignment_to_numparam(node)
1493
- name = node.children[0].to_s
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
1494
1591
 
1495
1592
  assigning_to_numparam =
1496
1593
  @parser.context.in_dynamic_block? &&
@@ -1498,7 +1595,17 @@ module Parser
1498
1595
  @parser.max_numparam_stack.has_numparams?
1499
1596
 
1500
1597
  if assigning_to_numparam
1501
- diagnostic :error, :cant_assign_to_numparam, { :name => name }, node.loc.expression
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
1502
1609
  end
1503
1610
  end
1504
1611
 
@@ -1732,9 +1839,17 @@ module Parser
1732
1839
  end
1733
1840
 
1734
1841
  def definition_map(keyword_t, operator_t, name_t, end_t)
1735
- Source::Map::Definition.new(loc(keyword_t),
1736
- loc(operator_t), loc(name_t),
1737
- 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)
1738
1853
  end
1739
1854
 
1740
1855
  def send_map(receiver_e, dot_t, selector_t, begin_t=nil, args=[], end_t=nil)
@@ -1979,6 +2094,18 @@ module Parser
1979
2094
  @parser.send :yyerror
1980
2095
  end
1981
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
1982
2109
  end
1983
2110
 
1984
2111
  end