parser 2.3.0.1 → 2.3.0.2

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
  SHA1:
3
- metadata.gz: 452a2098780caf4b2b9d00870b2791ae4e1db7e4
4
- data.tar.gz: a3ec510fb0160c8bfa9f29b0f80edcd4705db85d
3
+ metadata.gz: 3cb2802760d71d558e9ab344e63deb18525be110
4
+ data.tar.gz: 32edc10c308de0d00030d4b9fbac6bd40bfff36f
5
5
  SHA512:
6
- metadata.gz: b3322d4861c4c33a1381791f977928cba01428ee3153fb489cc1aed0ec88bb5c03570cfa448b073b1f6dc5776eb4aed6ef796b81aa5a607dae18439fec36b6c4
7
- data.tar.gz: b490d684a3ee85df2ae7b9700195bee2792fe44273104535080bc22ab5ffbcd7ef351ec8d143e11829579005288606e4af2b5cbd2ff11a3bb824bbb6583d4908
6
+ metadata.gz: 365c674e6cf6b3fa43f81903a7f46ce787075eb927e4aecce9b59ff05d81b5c47d4304f063f2f31c528f8846faec1983736f7bbd169697e19950e03346b0e52a
7
+ data.tar.gz: 1504d14896c1cb0dde7a8bc46aa60b04036e03310b1f097e84e5f14587699f18b086184292fbb5fb1aaff4d201d172cd9c424d1b8bc11de725d2c64567893928
data/CHANGELOG.md CHANGED
@@ -1,6 +1,22 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ v2.3.0.2 (2016-01-24)
5
+ ---------------------
6
+
7
+ Bugs fixed:
8
+ * Add :csend to Parser::Meta::NODE_TYPES (Markus Schirp)
9
+ * lexer/dedenter: "\<\<x\n y\\n z\nx": don't dedent after escaped newline. (whitequark)
10
+
11
+ v2.3.0.2 (2016-01-16)
12
+ ---------------------
13
+
14
+ v2.3.0.1 (2016-01-14)
15
+ ---------------------
16
+
17
+ Features implemented:
18
+ * ruby23.y: implement optional superclass (cremno)
19
+
4
20
  v2.3.0.0 (2016-01-14)
5
21
  ---------------------
6
22
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Parser
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/parser.png)](https://badge.fury.io/rb/parser)
4
- [![Build Status](https://travis-ci.org/whitequark/parser.png?branch=master)](https://travis-ci.org/whitequark/parser)
5
- [![Coverage Status](https://coveralls.io/repos/whitequark/parser/badge.png?branch=master)](https://coveralls.io/r/whitequark/parser)
3
+ [![Gem Version](https://badge.fury.io/rb/parser.svg)](https://badge.fury.io/rb/parser)
4
+ [![Build Status](https://travis-ci.org/whitequark/parser.svg?branch=master)](https://travis-ci.org/whitequark/parser)
5
+ [![Coverage Status](https://coveralls.io/repos/whitequark/parser/badge.svg?branch=master)](https://coveralls.io/r/whitequark/parser)
6
6
 
7
7
  _Parser_ is a production-ready Ruby parser written in pure Ruby. It recognizes as
8
8
  much or more code than Ripper, Melbourne, JRubyParser or ruby\_parser, and
data/lib/parser/lexer.rl CHANGED
@@ -92,7 +92,7 @@ class Parser::Lexer
92
92
  REGEXP_META_CHARACTERS = Regexp.union(*"\\$()*+.<>?[]^{|}".chars).freeze
93
93
  UNDERSCORE_STRING = '_'.freeze
94
94
 
95
- RBRACE_OR_RPAREN = %w"} ]".freeze
95
+ RBRACE_OR_RBRACK = %w"} ]".freeze
96
96
 
97
97
  attr_reader :source_buffer
98
98
  attr_reader :encoding
@@ -426,6 +426,12 @@ class Parser::Lexer
426
426
  else
427
427
  self.class.lex_en_plain_words
428
428
  end
429
+ elsif new_literal.backslash_delimited?
430
+ if new_literal.interpolate?
431
+ self.class.lex_en_interp_backslash_delimited
432
+ else
433
+ self.class.lex_en_plain_backslash_delimited
434
+ end
429
435
  else
430
436
  if new_literal.interpolate?
431
437
  self.class.lex_en_interp_string
@@ -645,10 +651,10 @@ class Parser::Lexer
645
651
  flo_pow = [eE] [+\-]? ( digit+ '_' )* digit+;
646
652
 
647
653
  int_suffix =
648
- '' % { @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } }
649
- | 'r' % { @num_xfrm = lambda { |chars| emit(:tRATIONAL, Rational(chars)) } }
650
- | 'i' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, chars)) } }
651
- | 'ri' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Rational(chars))) } };
654
+ '' % { @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } }
655
+ | 'r' % { @num_xfrm = lambda { |chars| emit(:tRATIONAL, Rational(chars)) } }
656
+ | 'i' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, chars)) } }
657
+ | 'ri' % { @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Rational(chars))) } };
652
658
 
653
659
  flo_pow_suffix =
654
660
  '' % { @num_xfrm = lambda { |chars| emit(:tFLOAT, Float(chars)) } }
@@ -682,11 +688,8 @@ class Parser::Lexer
682
688
  codepoint = codepoint_str.to_i(16)
683
689
 
684
690
  if codepoint >= 0x110000
685
- @escape = lambda do
686
- diagnostic :error, :unicode_point_too_large, nil,
687
- range(codepoint_s, codepoint_s + codepoint_str.length)
688
- end
689
-
691
+ diagnostic :error, :unicode_point_too_large, nil,
692
+ range(codepoint_s, codepoint_s + codepoint_str.length)
690
693
  break
691
694
  end
692
695
 
@@ -701,9 +704,7 @@ class Parser::Lexer
701
704
  }
702
705
 
703
706
  action invalid_complex_escape {
704
- @escape = lambda do
705
- diagnostic :fatal, :invalid_escape
706
- end
707
+ diagnostic :fatal, :invalid_escape
707
708
  }
708
709
 
709
710
  action slash_c_char {
@@ -731,20 +732,17 @@ class Parser::Lexer
731
732
  % { @escape = encode_escape(tok(@escape_s, p).to_i(8) % 0x100) }
732
733
 
733
734
  # \xff
734
- | ( 'x' xdigit{1,2}
735
+ | 'x' xdigit{1,2}
735
736
  % { @escape = encode_escape(tok(@escape_s + 1, p).to_i(16)) }
737
+
736
738
  # \u263a
737
- | 'u' xdigit{4}
738
- % { @escape = tok(@escape_s + 1, p).to_i(16).chr(Encoding::UTF_8) }
739
- )
739
+ | 'u' xdigit{4}
740
+ % { @escape = tok(@escape_s + 1, p).to_i(16).chr(Encoding::UTF_8) }
740
741
 
741
742
  # %q[\x]
742
743
  | 'x' ( c_any - xdigit )
743
744
  % {
744
- @escape = lambda do
745
- diagnostic :fatal, :invalid_hex_escape, nil,
746
- range(@escape_s - 1, p + 2)
747
- end
745
+ diagnostic :fatal, :invalid_hex_escape, nil, range(@escape_s - 1, p + 2)
748
746
  }
749
747
 
750
748
  # %q[\u123] %q[\u{12]
@@ -756,10 +754,7 @@ class Parser::Lexer
756
754
  )
757
755
  )
758
756
  % {
759
- @escape = lambda do
760
- diagnostic :fatal, :invalid_unicode_escape, nil,
761
- range(@escape_s - 1, p)
762
- end
757
+ diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p)
763
758
  }
764
759
 
765
760
  # \u{123 456}
@@ -770,10 +765,7 @@ class Parser::Lexer
770
765
  | ( c_any - '}' )* c_eof
771
766
  | xdigit{7,}
772
767
  ) % {
773
- @escape = lambda do
774
- diagnostic :fatal, :unterminated_unicode, nil,
775
- range(p - 1, p)
776
- end
768
+ diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p)
777
769
  }
778
770
  )
779
771
 
@@ -881,53 +873,35 @@ class Parser::Lexer
881
873
 
882
874
  action extend_string_escaped {
883
875
  current_literal = literal
884
- if current_literal.nest_and_try_closing('\\', @ts, @ts + 1)
885
- # If the literal is actually closed by the backslash,
886
- # rewind the input prior to consuming the escape sequence.
887
- p = @escape_s - 1
888
- fnext *pop_literal; fbreak;
876
+ # Get the first character after the backslash.
877
+ escaped_char = @source[@escape_s].chr
878
+
879
+ if current_literal.munge_escape? escaped_char
880
+ # If this particular literal uses this character as an opening
881
+ # or closing delimiter, it is an escape sequence for that
882
+ # particular character. Write it without the backslash.
883
+
884
+ if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char)
885
+ # Regular expressions should include escaped delimiters in their
886
+ # escaped form, except when the escaped character is
887
+ # a closing delimiter but not a regexp metacharacter.
888
+ #
889
+ # The backslash itself cannot be used as a closing delimiter
890
+ # at the same time as an escape symbol, but it is always munged,
891
+ # so this branch also executes for the non-closing-delimiter case
892
+ # for the backslash.
893
+ current_literal.extend_string(tok, @ts, @te)
894
+ else
895
+ current_literal.extend_string(escaped_char, @ts, @te)
896
+ end
889
897
  else
890
- # Get the first character after the backslash.
891
- escaped_char = @source[@escape_s].chr
892
-
893
- if current_literal.munge_escape? escaped_char
894
- # If this particular literal uses this character as an opening
895
- # or closing delimiter, it is an escape sequence for that
896
- # particular character. Write it without the backslash.
897
-
898
- if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char)
899
- # Regular expressions should include escaped delimiters in their
900
- # escaped form, except when the escaped character is
901
- # a closing delimiter but not a regexp metacharacter.
902
- #
903
- # The backslash itself cannot be used as a closing delimiter
904
- # at the same time as an escape symbol, but it is always munged,
905
- # so this branch also executes for the non-closing-delimiter case
906
- # for the backslash.
907
- current_literal.extend_string(tok, @ts, @te)
908
- else
909
- current_literal.extend_string(escaped_char, @ts, @te)
910
- end
898
+ # It does not. So this is an actual escape sequence, yay!
899
+ if current_literal.regexp?
900
+ # Regular expressions should include escape sequences in their
901
+ # escaped form. On the other hand, escaped newlines are removed.
902
+ current_literal.extend_string(tok.gsub(ESCAPED_NEXT_LINE, BLANK_STRING), @ts, @te)
911
903
  else
912
- # It does not. So this is an actual escape sequence, yay!
913
- # Two things to consider here.
914
- #
915
- # 1. The `escape' rule should be pure and so won't raise any
916
- # errors by itself. Instead, it stores them in lambdas.
917
- #
918
- # 2. Non-interpolated literals do not go through the aforementioned
919
- # rule. As \\ and \' (and variants) are munged, the full token
920
- # should always be written for such literals.
921
-
922
- @escape.call if @escape.respond_to? :call
923
-
924
- if current_literal.regexp?
925
- # Regular expressions should include escape sequences in their
926
- # escaped form. On the other hand, escaped newlines are removed.
927
- current_literal.extend_string(tok.gsub(ESCAPED_NEXT_LINE, BLANK_STRING), @ts, @te)
928
- else
929
- current_literal.extend_string(@escape || tok, @ts, @te)
930
- end
904
+ current_literal.extend_string(@escape || tok, @ts, @te)
931
905
  end
932
906
  end
933
907
  }
@@ -1115,6 +1089,18 @@ class Parser::Lexer
1115
1089
  c_any => extend_string;
1116
1090
  *|;
1117
1091
 
1092
+ interp_backslash_delimited := |*
1093
+ interp_code => extend_interp_code;
1094
+ interp_var => extend_interp_var;
1095
+ c_eol => extend_string_eol;
1096
+ c_any => extend_string;
1097
+ *|;
1098
+
1099
+ plain_backslash_delimited := |*
1100
+ c_eol => extend_string_eol;
1101
+ c_any => extend_string;
1102
+ *|;
1103
+
1118
1104
  regexp_modifiers := |*
1119
1105
  [A-Za-z]+
1120
1106
  => {
@@ -1669,7 +1655,7 @@ class Parser::Lexer
1669
1655
  # %w(we are the people)
1670
1656
  '%' [A-Za-z]+ c_any
1671
1657
  => {
1672
- type, delimiter = tok[0..-2], @source[@te - 1].chr
1658
+ type, delimiter = @source[@ts...(@te - 1)], @source[@te - 1].chr
1673
1659
  fgoto *push_literal(type, delimiter, @ts);
1674
1660
  };
1675
1661
 
@@ -1746,9 +1732,6 @@ class Parser::Lexer
1746
1732
  | (c_any - c_space_nl - e_bs) % { @escape = nil }
1747
1733
  )
1748
1734
  => {
1749
- # Show an error if memorized.
1750
- @escape.call if @escape.respond_to? :call
1751
-
1752
1735
  value = @escape || tok(@ts + 1)
1753
1736
 
1754
1737
  if version?(18)
@@ -2177,7 +2160,7 @@ class Parser::Lexer
2177
2160
  emit_table(PUNCTUATION)
2178
2161
  @cond.lexpop; @cmdarg.lexpop
2179
2162
 
2180
- if RBRACE_OR_RPAREN.include?(tok)
2163
+ if RBRACE_OR_RBRACK.include?(tok)
2181
2164
  fnext expr_endarg;
2182
2165
  else # )
2183
2166
  # fnext expr_endfn; ?
@@ -9,6 +9,7 @@ module Parser
9
9
 
10
10
  def dedent(string)
11
11
  space_begin = space_end = offset = 0
12
+ last_index = string.length - 1
12
13
  string.chars.each_with_index do |char, index|
13
14
  if @at_line_begin
14
15
  if char == ?\n || @indent_level >= @dedent_level
@@ -26,7 +27,7 @@ module Parser
26
27
  @indent_level += 8 - @indent_level % 8
27
28
  space_end += 1
28
29
  end
29
- elsif char == ?\n
30
+ elsif char == ?\n && index == last_index
30
31
  @at_line_begin = true
31
32
  @indent_level = 0
32
33
  space_begin = space_end = index - offset + 1
@@ -4,7 +4,6 @@ module Parser
4
4
 
5
5
  class Lexer::Literal
6
6
  DELIMITERS = { '(' => ')', '[' => ']', '{' => '}', '<' => '>' }
7
- MONOLITHIC = { :tSTRING_BEG => :tSTRING }
8
7
 
9
8
  TYPES = {
10
9
  # type start token interpolate?
@@ -79,9 +78,7 @@ module Parser
79
78
  !heredoc?)
80
79
 
81
80
  # Capture opening delimiter in percent-literals.
82
- unless @heredoc_e || @str_type.end_with?(delimiter)
83
- @str_type << delimiter
84
- end
81
+ @str_type << delimiter if @str_type.start_with?('%')
85
82
 
86
83
  clear_buffer
87
84
 
@@ -105,6 +102,10 @@ module Parser
105
102
  !!@heredoc_e
106
103
  end
107
104
 
105
+ def backslash_delimited?
106
+ @end_delim == '\\'
107
+ end
108
+
108
109
  def type
109
110
  @start_tok
110
111
  end
@@ -141,7 +142,7 @@ module Parser
141
142
  emit(:tLABEL_END, @end_delim, ts, te + 1)
142
143
  elsif @monolithic
143
144
  # Emit the string as a single token.
144
- emit(MONOLITHIC[@start_tok], @buffer, @str_s, te)
145
+ emit(:tSTRING, @buffer, @str_s, te)
145
146
  else
146
147
  # If this is a heredoc, @buffer contains the sentinel now.
147
148
  # Just throw it out. Lexer flushes the heredoc after each
@@ -183,10 +184,7 @@ module Parser
183
184
  end
184
185
 
185
186
  def extend_string(string, ts, te)
186
- if @buffer_s.nil?
187
- @buffer_s = ts
188
- end
189
-
187
+ @buffer_s ||= ts
190
188
  @buffer_e = te
191
189
 
192
190
  @buffer << string
data/lib/parser/meta.rb CHANGED
@@ -16,7 +16,7 @@ module Parser
16
16
  match_with_lvasgn match_current_line
17
17
  module class sclass def defs undef alias args
18
18
  cbase arg optarg restarg blockarg block_pass args def kwarg kwoptarg
19
- kwrestarg send super zsuper yield block send
19
+ kwrestarg send csend super zsuper yield block
20
20
  and not or if when case while until while_post
21
21
  until_post for break next redo return resbody
22
22
  kwbegin begin retry preexe postexe iflipflop eflipflop
@@ -1,3 +1,3 @@
1
1
  module Parser
2
- VERSION = '2.3.0.1'
2
+ VERSION = '2.3.0.2'
3
3
  end
data/test/test_lexer.rb CHANGED
@@ -1796,6 +1796,14 @@ class TestLexer < Minitest::Test
1796
1796
  :tREGEXP_OPT, "")
1797
1797
  end
1798
1798
 
1799
+ def test_regexp_escape_other_meta
1800
+ assert_scanned("/\\.\\$\\*\\+\\.\\?\\|/",
1801
+ :tREGEXP_BEG, "/",
1802
+ :tSTRING_CONTENT, "\\.\\$\\*\\+\\.\\?\\|",
1803
+ :tSTRING_END, "/",
1804
+ :tREGEXP_OPT, "")
1805
+ end
1806
+
1799
1807
  def test_regexp_nm
1800
1808
  assert_scanned("/.*/nm",
1801
1809
  :tREGEXP_BEG, "/",
@@ -2097,7 +2105,7 @@ class TestLexer < Minitest::Test
2097
2105
 
2098
2106
  def test_string_pct_pct
2099
2107
  assert_scanned("%%blah%",
2100
- :tSTRING_BEG, '%',
2108
+ :tSTRING_BEG, '%%',
2101
2109
  :tSTRING_CONTENT, "blah",
2102
2110
  :tSTRING_END, '%')
2103
2111
  end
@@ -2159,6 +2167,48 @@ class TestLexer < Minitest::Test
2159
2167
  :tSTRING_END, ')')
2160
2168
  end
2161
2169
 
2170
+ def test_string_pct_backslash
2171
+ assert_scanned("%\\a\\",
2172
+ :tSTRING_BEG, "%\\",
2173
+ :tSTRING_CONTENT, "a",
2174
+ :tSTRING_END, "\\")
2175
+ end
2176
+
2177
+ def test_string_pct_backslash_with_bad_escape
2178
+ # No escapes are allowed in a backslash-delimited string
2179
+ refute_scanned("%\\a\\n\\",
2180
+ :tSTRING_BEG, "%\\",
2181
+ :tSTRING_CONTENT, "a",
2182
+ :tSTRING_END, "\\",
2183
+ :tIDENTIFIER, "n")
2184
+ end
2185
+
2186
+ def test_string_pct_intertwined_with_heredoc
2187
+ assert_scanned("<<-foo + %\\a\nbar\nfoo\nb\\",
2188
+ :tSTRING_BEG, "<<\"",
2189
+ :tSTRING_CONTENT, "bar\n",
2190
+ :tSTRING_END, "foo",
2191
+ :tPLUS, "+",
2192
+ :tSTRING_BEG, "%\\",
2193
+ :tSTRING_CONTENT, "a\n",
2194
+ :tSTRING_CONTENT, "b",
2195
+ :tSTRING_END, "\\")
2196
+ end
2197
+
2198
+ def test_string_pct_q_backslash
2199
+ assert_scanned("%q\\a\\",
2200
+ :tSTRING_BEG, "%q\\",
2201
+ :tSTRING_CONTENT, "a",
2202
+ :tSTRING_END, "\\")
2203
+ end
2204
+
2205
+ def test_string_pct_Q_backslash
2206
+ assert_scanned("%Q\\a\\",
2207
+ :tSTRING_BEG, "%Q\\",
2208
+ :tSTRING_CONTENT, "a",
2209
+ :tSTRING_END, "\\")
2210
+ end
2211
+
2162
2212
  def test_string_single
2163
2213
  assert_scanned("'string'",
2164
2214
  :tSTRING, "string")
data/test/test_parser.rb CHANGED
@@ -5286,17 +5286,15 @@ class TestParser < Minitest::Test
5286
5286
  ALL_VERSIONS - %w(1.8 1.9 mac ios 2.0)) # no 1.9 backport
5287
5287
  end
5288
5288
 
5289
- # We implement broken behavior, and Ruby is not fixed as of 2016-01-14.
5290
5289
  def test_ruby_bug_11989
5291
5290
  assert_parses(
5292
5291
  s(:send, nil, :p,
5293
- s(:str, "x\n y\n")),
5292
+ s(:str, "x\n y\n")),
5294
5293
  %Q{p <<~"E"\n x\\n y\nE},
5295
5294
  %q{},
5296
5295
  ALL_VERSIONS - %w(1.8 1.9 2.0 2.1 2.2 ios mac))
5297
5296
  end
5298
5297
 
5299
- # We implement correct behavior, but Ruby is not fixed as of 2016-01-14.
5300
5298
  def test_ruby_bug_11990
5301
5299
  assert_parses(
5302
5300
  s(:send, nil, :p,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0.1
4
+ version: 2.3.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - whitequark
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-14 00:00:00.000000000 Z
11
+ date: 2016-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast
@@ -354,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
354
354
  version: '0'
355
355
  requirements: []
356
356
  rubyforge_project:
357
- rubygems_version: 2.4.1
357
+ rubygems_version: 2.5.1
358
358
  signing_key:
359
359
  specification_version: 4
360
360
  summary: A Ruby parser written in pure Ruby.