parser 2.7.1.0 → 2.7.1.5

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