parser 2.6.3.0 → 2.6.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bceee2aee10ca7b86d7fb0e29f985b0b1848425b3d256af84e5dd324046ab2f7
4
- data.tar.gz: 9ea970432bb2dc6dc68320baf39d7f24d928c45fc8ca236c14ed4c7c8db4d29e
3
+ metadata.gz: 9e113f6f42c44591674f288ebda60f8c4f17f5b6aee601d1cc5c2e20c50ef2e6
4
+ data.tar.gz: '08cf94385ef5cd8f211de395e1c272e5b7950e155463160e327cda2eb047dfad'
5
5
  SHA512:
6
- metadata.gz: 577db299468896bb4dec4ca23dc14d78e58dd41dd323219de110e70ad2c691d6a9d3563339c1c4dcded9e7aaa69df5227f80ed1565f910d562928cf64c0936b4
7
- data.tar.gz: 28c3a2a9e40727a71ac9255f1ad076ff86d2b60652eb4ac81719645c2542c3be0c818862003eae32b13c983397b86e023d9c0177f495dd45299845f1902871d5
6
+ metadata.gz: 25fd7715c94cf32eb097e8c0049d48f7b8185bef6ea4dafe21f0f7013c13892ff6d929e2e45f18480903f081ed9738aa8f0059287dd528cdb63feb94a47fd42e
7
+ data.tar.gz: 8dfe6966704a8b5b662f99a2ee15d525f6d4cd3d74b62b0c3946f01933c86f50075572cf32a81de3bfe2fe96a07d8197a55a11906f870b80daa2d81e50987944
@@ -11,14 +11,14 @@ matrix:
11
11
  - name: 2.3.8 / Parser tests
12
12
  rvm: 2.3.8
13
13
  script: bundle exec rake test_cov
14
- - name: 2.4.6 / Parser tests
15
- rvm: 2.4.6
14
+ - name: 2.4.7 / Parser tests
15
+ rvm: 2.4.7
16
16
  script: bundle exec rake test_cov
17
- - name: 2.5.5 / Parser tests
18
- rvm: 2.5.5
17
+ - name: 2.5.6 / Parser tests
18
+ rvm: 2.5.6
19
19
  script: bundle exec rake test_cov
20
- - name: 2.6.3 / Parser tests
21
- rvm: 2.6.3
20
+ - name: 2.6.4 / Parser tests
21
+ rvm: 2.6.4
22
22
  script: bundle exec rake test_cov
23
23
  - name: ruby-head / Parser tests
24
24
  rvm: ruby-head
@@ -29,11 +29,11 @@ matrix:
29
29
  - name: rbx-2 / Parser tests
30
30
  rvm: rbx-2
31
31
  script: bundle exec rake test_cov
32
- - name: 2.5.5 / Rubocop tests
33
- rvm: 2.5.5
32
+ - name: 2.5.6 / Rubocop tests
33
+ rvm: 2.5.6
34
34
  script: ./ci/run_rubocop_specs
35
- - name: 2.6.3 / Rubocop tests
36
- rvm: 2.6.3
35
+ - name: 2.6.4 / Rubocop tests
36
+ rvm: 2.6.4
37
37
  script: ./ci/run_rubocop_specs
38
38
  allow_failures:
39
39
  - rvm: ruby-head
@@ -1,8 +1,30 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- Not released (2019-04-28)
5
- -------------------------
4
+ v2.6.4.0 (2019-08-30)
5
+ ---------------------
6
+
7
+ API modifications:
8
+ * Added specs for heredocs with mixed encoding. (#581) (Ilya Bylich)
9
+
10
+ Features implemented:
11
+ * ruby27.y: Revert "pipeline operator" (#601) (Koichi ITO)
12
+ * ruby27.y: Fix parsing of mutiple assignment with rescue modifier (#600) (Koichi ITO)
13
+ * ruby27.y: hoisted out f_rest_marg. (#594) (Ilya Bylich)
14
+ * ruby27.y: added pipeline operator. (#592) (Ilya Bylich)
15
+ * ruby27.y: reject safe navigator in LHS of mass-assignment. (#586) (Ilya Bylich)
16
+ * lexer.rl: reject whitespaces in meta and control chars. (#585) (Ilya Bylich)
17
+ * lexer.rl: Reject numparams as symbol literals. (#582) (Ilya Bylich)
18
+ * ruby27.y: Added numbered parameters support. (#565) (Ilya Bylich)
19
+ * lexer.rl: Reject \n and \r in heredoc identifiers starting from 2.7. (#575) (Ilya Bylich)
20
+
21
+ Bugs fixed:
22
+ * ruby-parse: print empty string when --emit-json and empty input are given. (#590) (Ilya Bylich)
23
+ * AST_FORMAT: fixed documentation of the string with interpolation. (#589) (Ilya Bylich)
24
+ * builder.rb, processor.rb: Changed format of the procarg0 node. (#587) (Ilya Bylich)
25
+
26
+ v2.6.3.0 (2019-04-28)
27
+ ---------------------
6
28
 
7
29
  Features implemented:
8
30
  * ruby27.y: Added beginless ranges support. (#570) (Ilya Bylich)
@@ -102,10 +102,13 @@ Format:
102
102
  Format:
103
103
 
104
104
  ~~~
105
- (dstr (str "foo") (lvar bar) (str "baz"))
105
+ (dstr (str "foo") (begin (lvar bar)) (str "baz"))
106
106
  '"foo#{bar}baz"'
107
107
  ^ begin ^ end
108
108
  ~~~~~~~~~~~~~~ expression
109
+ ^^ begin (begin)
110
+ ^ end (begin)
111
+ ^^^^^^ expression (begin)
109
112
  ~~~
110
113
 
111
114
  #### Here document
@@ -933,10 +936,15 @@ the sole argument (e.g. `|foo,|`).
933
936
  Format:
934
937
 
935
938
  ~~~
936
- (procarg0 :foo)
939
+ (procarg0 (arg :foo))
937
940
  "|foo|"
938
941
  ~~~ expression
939
- ~~~ name
942
+
943
+ (procarg0 (arg :foo) (arg :bar))
944
+ "|(foo, bar)|"
945
+ ~ begin
946
+ ~ end
947
+ ~~~~~~~~~~ expression
940
948
  ~~~
941
949
 
942
950
  ### Expression arguments
@@ -1083,6 +1091,40 @@ However, the following code results in a parse error:
1083
1091
  def f(*a: b); end
1084
1092
  ~~~
1085
1093
 
1094
+ ## Numbered parameters
1095
+
1096
+ ### Block with numbered parameters
1097
+
1098
+ Ruby 2.7 introduced a feature called "numbered parameters".
1099
+ Numbered and ordinal parameters are mutually exclusive, so if the block
1100
+ has only numbered parameters it also has a different AST node.
1101
+
1102
+ Note that the second child represents a total number of numbered parameters.
1103
+
1104
+ Format:
1105
+
1106
+ ~~~
1107
+ s(:numblock,
1108
+ s(:send, nil, :proc), 3,
1109
+ s(:send,
1110
+ s(:numparam, 1), :+,
1111
+ s(:numparam, 3)))
1112
+ "proc { @1 + @3 }"
1113
+ ~ begin ~ end
1114
+ ~~~~~~~~~~~~~~~~ expression
1115
+ ~~~
1116
+
1117
+ ### Numbered parameter
1118
+
1119
+ Format:
1120
+
1121
+ ~~~
1122
+ (numparam 10)
1123
+ "@10"
1124
+ ~~~ name
1125
+ ~~~ expression
1126
+ ~~~
1127
+
1086
1128
  ## Send
1087
1129
 
1088
1130
  ### To self
@@ -67,6 +67,7 @@ module Parser
67
67
  require 'parser/lexer/literal'
68
68
  require 'parser/lexer/stack_state'
69
69
  require 'parser/lexer/dedenter'
70
+ require 'parser/lexer/max_numparam_stack'
70
71
 
71
72
  module Builders
72
73
  require 'parser/builders/default'
@@ -124,7 +124,22 @@ 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_procarg0 process_argument_node
127
+
128
+ def on_procarg0(node)
129
+ if node.children[0].is_a?(Symbol)
130
+ # This branch gets executed when the builder
131
+ # is not configured to emit and 'arg' inside 'procarg0', i.e. when
132
+ # Parser::Builders::Default.emit_arg_inside_procarg0
133
+ # is set to false.
134
+ #
135
+ # If this flag is set to true this branch is unreachable.
136
+ # s(:procarg0, :a)
137
+ on_argument(node)
138
+ else
139
+ # s(:procarg0, s(:arg, :a), s(:arg, :b))
140
+ process_regular_node(node)
141
+ end
142
+ end
128
143
 
129
144
  alias on_arg_expr process_regular_node
130
145
  alias on_restarg_expr process_regular_node
@@ -173,6 +188,14 @@ module Parser
173
188
  alias on_block process_regular_node
174
189
  alias on_lambda process_regular_node
175
190
 
191
+ def on_numblock(node)
192
+ method_call, max_numparam, body = *node
193
+
194
+ node.updated(nil, [
195
+ process(method_call), max_numparam, process(body)
196
+ ])
197
+ end
198
+
176
199
  alias on_while process_regular_node
177
200
  alias on_while_post process_regular_node
178
201
  alias on_until process_regular_node
@@ -80,6 +80,21 @@ module Parser
80
80
  attr_accessor :emit_index
81
81
  end
82
82
 
83
+ class << self
84
+ ##
85
+ # AST compatibility attribute; causes a single non-mlhs
86
+ # block argument to be wrapped in s(:procarg0).
87
+ #
88
+ # If set to false (the default), block arguments `|a|` are emitted as
89
+ # `s(:args, s(:procarg0, :a))`
90
+ #
91
+ # If set to true, block arguments `|a|` are emitted as
92
+ # `s(:args, s(:procarg0, s(:arg, :a))`
93
+ #
94
+ # @return [Boolean]
95
+ attr_accessor :emit_arg_inside_procarg0
96
+ end
97
+
83
98
  @emit_index = false
84
99
 
85
100
  class << self
@@ -90,6 +105,7 @@ module Parser
90
105
  @emit_procarg0 = true
91
106
  @emit_encoding = true
92
107
  @emit_index = true
108
+ @emit_arg_inside_procarg0 = true
93
109
  end
94
110
  end
95
111
 
@@ -437,6 +453,11 @@ module Parser
437
453
  variable_map(token))
438
454
  end
439
455
 
456
+ def numparam(token)
457
+ n(:numparam, [ value(token).to_i ],
458
+ variable_map(token))
459
+ end
460
+
440
461
  def back_ref(token)
441
462
  n(:back_ref, [ value(token).to_sym ],
442
463
  token_map(token))
@@ -663,6 +684,10 @@ module Parser
663
684
  collection_map(begin_t, args, end_t))
664
685
  end
665
686
 
687
+ def numargs(max_numparam)
688
+ n(:numargs, [ max_numparam ], nil)
689
+ end
690
+
666
691
  def arg(name_t)
667
692
  n(:arg, [ value(name_t).to_sym ],
668
693
  variable_map(name_t))
@@ -717,7 +742,12 @@ module Parser
717
742
 
718
743
  def procarg0(arg)
719
744
  if self.class.emit_procarg0
720
- arg.updated(:procarg0)
745
+ if arg.type == :arg && self.class.emit_arg_inside_procarg0
746
+ n(:procarg0, [ arg ],
747
+ Source::Map::Collection.new(nil, nil, arg.location.expression))
748
+ else
749
+ arg.updated(:procarg0)
750
+ end
721
751
  else
722
752
  arg
723
753
  end
@@ -835,15 +865,23 @@ module Parser
835
865
  diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)]
836
866
  end
837
867
 
868
+
869
+ if args.type == :numargs
870
+ block_type = :numblock
871
+ args = args.children[0]
872
+ else
873
+ block_type = :block
874
+ end
875
+
838
876
  if [:send, :csend, :index, :super, :zsuper, :lambda].include?(method_call.type)
839
- n(:block, [ method_call, args, body ],
877
+ n(block_type, [ method_call, args, body ],
840
878
  block_map(method_call.loc.expression, begin_t, end_t))
841
879
  else
842
880
  # Code like "return foo 1 do end" is reduced in a weird sequence.
843
881
  # Here, method_call is actually (return).
844
882
  actual_send, = *method_call
845
883
  block =
846
- n(:block, [ actual_send, args, body ],
884
+ n(block_type, [ actual_send, args, body ],
847
885
  block_map(actual_send.loc.expression, begin_t, end_t))
848
886
 
849
887
  n(method_call.type, [ block ],
@@ -1215,18 +1253,18 @@ module Parser
1215
1253
  case this_arg.type
1216
1254
  when :arg, :optarg, :restarg, :blockarg,
1217
1255
  :kwarg, :kwoptarg, :kwrestarg,
1218
- :shadowarg, :procarg0
1256
+ :shadowarg
1219
1257
 
1220
- this_name, = *this_arg
1258
+ check_duplicate_arg(this_arg, map)
1221
1259
 
1222
- that_arg = map[this_name]
1223
- that_name, = *that_arg
1260
+ when :procarg0
1224
1261
 
1225
- if that_arg.nil?
1226
- map[this_name] = this_arg
1227
- elsif arg_name_collides?(this_name, that_name)
1228
- diagnostic :error, :duplicate_argument, nil,
1229
- this_arg.loc.name, [ that_arg.loc.name ]
1262
+ if this_arg.children[0].is_a?(Symbol)
1263
+ # s(:procarg0, :a)
1264
+ check_duplicate_arg(this_arg, map)
1265
+ else
1266
+ # s(:procarg0, s(:arg, :a), ...)
1267
+ check_duplicate_args(this_arg.children, map)
1230
1268
  end
1231
1269
 
1232
1270
  when :mlhs
@@ -1235,6 +1273,20 @@ module Parser
1235
1273
  end
1236
1274
  end
1237
1275
 
1276
+ def check_duplicate_arg(this_arg, map={})
1277
+ this_name, = *this_arg
1278
+
1279
+ that_arg = map[this_name]
1280
+ that_name, = *that_arg
1281
+
1282
+ if that_arg.nil?
1283
+ map[this_name] = this_arg
1284
+ elsif arg_name_collides?(this_name, that_name)
1285
+ diagnostic :error, :duplicate_argument, nil,
1286
+ this_arg.loc.name, [ that_arg.loc.name ]
1287
+ end
1288
+ end
1289
+
1238
1290
  def arg_name_collides?(this_name, that_name)
1239
1291
  case @parser.version
1240
1292
  when 18
@@ -47,5 +47,13 @@ module Parser
47
47
  end
48
48
  alias module_definition_allowed? class_definition_allowed?
49
49
  alias dynamic_const_definition_allowed? class_definition_allowed?
50
+
51
+ def in_block?
52
+ @stack.last == :block
53
+ end
54
+
55
+ def in_lambda?
56
+ @stack.last == :lambda
57
+ end
50
58
  end
51
59
  end
@@ -48,7 +48,7 @@ module Parser
48
48
  CurrentRuby = Ruby23
49
49
 
50
50
  when /^2\.4\./
51
- current_version = '2.4.6'
51
+ current_version = '2.4.7'
52
52
  if RUBY_VERSION != current_version
53
53
  warn_syntax_deviation 'parser/ruby24', current_version
54
54
  end
@@ -57,7 +57,7 @@ module Parser
57
57
  CurrentRuby = Ruby24
58
58
 
59
59
  when /^2\.5\./
60
- current_version = '2.5.5'
60
+ current_version = '2.5.6'
61
61
  if RUBY_VERSION != current_version
62
62
  warn_syntax_deviation 'parser/ruby25', current_version
63
63
  end
@@ -66,7 +66,7 @@ module Parser
66
66
  CurrentRuby = Ruby25
67
67
 
68
68
  when /^2\.6\./
69
- current_version = '2.6.3'
69
+ current_version = '2.6.4'
70
70
  if RUBY_VERSION != current_version
71
71
  warn_syntax_deviation 'parser/ruby26', current_version
72
72
  end
@@ -89,7 +89,10 @@ class Parser::Lexer
89
89
 
90
90
  REGEXP_META_CHARACTERS = Regexp.union(*"\\$()*+.<>?[]^{|}".chars).freeze
91
91
 
92
+ NUMPARAM_MAX = 100
93
+
92
94
  attr_reader :source_buffer
95
+ attr_reader :max_numparam_stack
93
96
 
94
97
  attr_accessor :diagnostics
95
98
  attr_accessor :static_env
@@ -176,6 +179,9 @@ class Parser::Lexer
176
179
 
177
180
  # State before =begin / =end block comment
178
181
  @cs_before_block_comment = self.class.lex_en_line_begin
182
+
183
+ # Maximum numbered parameters stack
184
+ @max_numparam_stack = MaxNumparamStack.new
179
185
  end
180
186
 
181
187
  def source_buffer=(source_buffer)
@@ -249,6 +255,10 @@ class Parser::Lexer
249
255
  @cond = @cond_stack.pop
250
256
  end
251
257
 
258
+ def max_numparam
259
+ @max_numparam_stack.top
260
+ end
261
+
252
262
  def dedent_level
253
263
  # We erase @dedent_level as a precaution to avoid accidentally
254
264
  # using a stale value.
@@ -705,6 +715,14 @@ class Parser::Lexer
705
715
  diagnostic :fatal, :invalid_escape
706
716
  }
707
717
 
718
+ action read_post_meta_or_ctrl_char {
719
+ @escape = @source_buffer.slice(p - 1).chr
720
+
721
+ if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord))
722
+ diagnostic :fatal, :invalid_escape
723
+ end
724
+ }
725
+
708
726
  action slash_c_char {
709
727
  @escape = encode_escape(@escape[0].ord & 0x9f)
710
728
  }
@@ -715,13 +733,13 @@ class Parser::Lexer
715
733
 
716
734
  maybe_escaped_char = (
717
735
  '\\' c_any %unescape_char
718
- | ( c_any - [\\] ) % { @escape = @source_buffer.slice(p - 1).chr }
736
+ | ( c_any - [\\] ) %read_post_meta_or_ctrl_char
719
737
  );
720
738
 
721
739
  maybe_escaped_ctrl_char = ( # why?!
722
740
  '\\' c_any %unescape_char %slash_c_char
723
741
  | '?' % { @escape = "\x7f" }
724
- | ( c_any - [\\?] ) % { @escape = @source_buffer.slice(p - 1).chr } %slash_c_char
742
+ | ( c_any - [\\?] ) %read_post_meta_or_ctrl_char %slash_c_char
725
743
  );
726
744
 
727
745
  escape = (
@@ -1301,6 +1319,36 @@ class Parser::Lexer
1301
1319
  fnext *stack_pop; fbreak;
1302
1320
  };
1303
1321
 
1322
+ '@' [0-9]+
1323
+ => {
1324
+ if @version < 27
1325
+ diagnostic :error, :ivar_name, { :name => tok }
1326
+ end
1327
+
1328
+ value = tok[1..-1]
1329
+
1330
+ if value[0] == '0'
1331
+ diagnostic :error, :leading_zero_in_numparam, nil, range(@ts, @te)
1332
+ end
1333
+
1334
+ if value.to_i > NUMPARAM_MAX
1335
+ diagnostic :error, :too_large_numparam, nil, range(@ts, @te)
1336
+ end
1337
+
1338
+ if !@context.in_block? && !@context.in_lambda?
1339
+ diagnostic :error, :numparam_outside_block, nil, range(@ts, @te)
1340
+ end
1341
+
1342
+ if !@max_numparam_stack.can_have_numparams?
1343
+ diagnostic :error, :ordinary_param_defined, nil, range(@ts, @te)
1344
+ end
1345
+
1346
+ @max_numparam_stack.register(value.to_i)
1347
+
1348
+ emit(:tNUMPARAM, tok[1..-1])
1349
+ fnext *stack_pop; fbreak;
1350
+ };
1351
+
1304
1352
  instance_var_v
1305
1353
  => {
1306
1354
  if tok =~ /^@[0-9]/
@@ -1733,7 +1781,11 @@ class Parser::Lexer
1733
1781
  type = $3.empty? ? '<<"'.freeze : ('<<'.freeze + $3)
1734
1782
  delimiter = $4
1735
1783
 
1736
- if @version >= 24
1784
+ if @version >= 27
1785
+ if delimiter.count("\n") > 0 || delimiter.count("\r") > 0
1786
+ diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1)
1787
+ end
1788
+ elsif @version >= 24
1737
1789
  if delimiter.count("\n") > 0
1738
1790
  if delimiter.end_with?("\n")
1739
1791
  diagnostic :warning, :heredoc_id_ends_with_nl, nil, range(@ts, @ts + 1)
@@ -1756,6 +1808,21 @@ class Parser::Lexer
1756
1808
  end
1757
1809
  };
1758
1810
 
1811
+ # Escaped unterminated heredoc start
1812
+ # <<'END | <<"END | <<`END |
1813
+ # <<-'END | <<-"END | <<-`END |
1814
+ # <<~'END | <<~"END | <<~`END
1815
+ #
1816
+ # If the heredoc is terminated the rule above should handle it
1817
+ '<<' [~\-]?
1818
+ ('"' (any - c_nl - '"')*
1819
+ |"'" (any - c_nl - "'")*
1820
+ |"`" (any - c_nl - "`")
1821
+ )
1822
+ => {
1823
+ diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1)
1824
+ };
1825
+
1759
1826
  #
1760
1827
  # SYMBOL LITERALS
1761
1828
  #
@@ -1796,6 +1863,20 @@ class Parser::Lexer
1796
1863
  fnext expr_end; fbreak;
1797
1864
  };
1798
1865
 
1866
+ ':' ( '@' %{ tm = p - 1; diag_msg = :ivar_name }
1867
+ | '@@' %{ tm = p - 2; diag_msg = :cvar_name }
1868
+ ) [0-9]*
1869
+ => {
1870
+ if @version >= 27
1871
+ diagnostic :error, diag_msg, { name: tok(tm, @te) }, range(tm, @te)
1872
+ else
1873
+ emit(:tCOLON, tok(@ts, @ts + 1), @ts, @ts + 1)
1874
+ p = @ts
1875
+ end
1876
+
1877
+ fnext expr_end; fbreak;
1878
+ };
1879
+
1799
1880
  #
1800
1881
  # AMBIGUOUS TERNARY OPERATOR
1801
1882
  #