redparse 0.8.1 → 0.8.2

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.
@@ -16,6 +16,19 @@
16
16
  along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  =end
18
18
 
19
+ #this is actually fixing a bug in reg 0.4.7, grrrrr
20
+ unless Array===(Class*5).subregs
21
+ module ::Reg
22
+ class Repeat
23
+ undef subregs if instance_methods.include? "subregs"
24
+ def subregs
25
+ [@reg]
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+
19
32
  unless defined? ::Reg::Transform and ::Reg::Transform.ancestors.include? ::Reg::HasCmatch
20
33
  #hack, until support for this syntax makes it into the release of reg
21
34
  module ::Reg
@@ -49,6 +62,10 @@
49
62
  @reg
50
63
  end
51
64
 
65
+ def subregs
66
+ [@reg]
67
+ end
68
+
52
69
  def itemrange
53
70
  0..0
54
71
  end
@@ -72,6 +89,10 @@
72
89
  @reg
73
90
  end
74
91
 
92
+ def subregs
93
+ [@reg]
94
+ end
95
+
75
96
  def itemrange
76
97
  0..0
77
98
  end
@@ -1,3 +1,3 @@
1
1
  class RedParse
2
- VERSION='0.8.1'
2
+ VERSION='0.8.2'
3
3
  end
@@ -0,0 +1,2 @@
1
+ def foo(a = 1) end; def foo(a=b=c={}) end; def bar(a=b=c=1,d=2) end
2
+
@@ -39,7 +39,7 @@ $RUBY=ENV['RUBY']||'ruby'
39
39
 
40
40
  #$RUBYLEXERVSRUBY="#$RUBY test/code/rubylexervsruby.rb"
41
41
 
42
- RUBY_VERSION[/^1\.8\.7/] or raise 'need ruby>= 1.8.7'
42
+ RUBY_VERSION[/^1\.8\.6/] or raise 'need ruby>= 1.8.6'
43
43
 
44
44
 
45
45
 
@@ -140,6 +140,7 @@ RUBYLIST=(pf.badlist+
140
140
  split("\n")
141
141
  ].sort_by{rand})-pf.goodlist + pf.goodlist
142
142
  RUBYLIST.reject!{|x| %r{japanese/zipcodes\.rb$}===x } #65M of ruby src!!!
143
+ RUBYLIST.reject!{|x| /\A\s*\Z/===x }
143
144
  RUBYLIST.uniq!
144
145
 
145
146
  def self.main
@@ -20,21 +20,277 @@
20
20
  require 'test/unit'
21
21
  require 'rubygems'
22
22
  require 'parse_tree'
23
+ require 'tempfile'
23
24
 
24
25
  require "redparse"
25
26
 
26
- begin
27
27
  require "rubylexer/test/testcases"
28
- rescue Exception
29
- puts "!!!!!!rubylexer/test/testcases not found!!!!"
30
- module TestCases;TESTCASES=[];end
28
+
29
+ $VERBOSE=1
30
+
31
+ class Test::Unit::TestCase
32
+ def known_error
33
+ from=caller.first
34
+ from=from[/ in `.*'\Z/] || from[/\A[^:]*:[^:]*/]
35
+ yield
36
+ rescue Test::Unit::AssertionFailedError=>e
37
+ warn "an expected error occurred in #{from}: #{e.message}"
38
+ if defined? @@known_errors
39
+ @@known_errors+=1
40
+ else
41
+ @@known_errors=1
42
+ at_exit {warn "!!!UNFIXED KNOWN ERRORS!!!: #@@known_errors"}
43
+ end
44
+ rescue Exception=>e
45
+ raise
46
+ else
47
+ warn "expected error in #{from}, but was fixed(?!)"
48
+ if defined? @@known_errors_fixed
49
+ @@known_errors_fixed+=1
50
+ else
51
+ @@known_errors_fixed=1
52
+ at_exit {warn "unexpectedly fixed known errors: #@@known_errors_fixed"}
53
+ end
54
+ end
55
+
56
+ def known_failure
57
+ from=caller.first
58
+ from=from[/ in `.*'\Z/] || from[/\A[^:]*:[^:]*/]
59
+ yield
60
+ rescue Exception=>e
61
+ warn "an expected failure occurred in #{from}: #{e}"
62
+ if defined? @@known_failures
63
+ @@known_failures+=1
64
+ else
65
+ @@known_failures=1
66
+ at_exit {warn "!!!UNFIXED KNOWN FAILURES!!!: #@@known_failures"}
67
+ end
68
+ else
69
+ warn "expected failure in #{from}, but was fixed(?!)"
70
+ if defined? @@known_failures_fixed
71
+ @@known_failures_fixed+=1
72
+ else
73
+ @@known_failures_fixed=1
74
+ at_exit {warn "unexpectedly fixed known failures: #@@known_failures_fixed"}
75
+ end
76
+ end
77
+
78
+ def slow
79
+ if ENV['SLOW']
80
+ yield
81
+ else
82
+ if defined? @@slow_spots
83
+ @@slow_spots+=1
84
+ else
85
+ @@slow_spots=1
86
+ at_exit {warn "slow test code skipped in #@@slow_spots places. (set SLOW to enable)"}
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ require 'test/unit/ui/console/testrunner'
93
+ class Test::Unit::UI::Console::TestRunner
94
+ alias add_fault__no_immed_output add_fault
95
+ def add_fault fault
96
+ @fault_count||=0
97
+ output("\n%3d) %s" % [@fault_count+=1, fault.long_display])
98
+ add_fault__no_immed_output fault
99
+ end
100
+ end
101
+
102
+ class ParseTree
103
+ def put o
104
+ o=Marshal.dump o
105
+ @@out.write [o.size].pack("N")+o
106
+ end
107
+ def get
108
+ Marshal.load @@in.read(@@in.read(4).unpack("N")[0])
109
+ end
110
+ def fork_server?
111
+ return if defined? @@out
112
+ si,co=IO::pipe
113
+ ci,so=IO::pipe
114
+ fork{
115
+ begin
116
+ co.close; ci.close
117
+ @@out=so; @@in=si
118
+ warnstash=Tempfile.new "warnstash"
119
+ STDERR.reopen warnstash
120
+ while 1
121
+ str=get
122
+ exit! if str==:exit!
123
+
124
+ pos=STDERR.pos
125
+
126
+ tree=
127
+ begin
128
+ parse_tree_for_string(str) #tree
129
+ rescue Exception=>e;
130
+ tree=e
131
+ end
132
+ put tree
133
+
134
+ open(STDERR.path){|f|
135
+ f.pos=pos
136
+ put f.read.split #warnings
137
+ }
138
+ end
139
+ rescue Exception=>e; p e; raise
140
+ ensure exit!
141
+ end
142
+ }
143
+ si.close; so.close
144
+ @@out=co; @@in=ci
145
+ at_exit { put :exit! }
146
+ end
147
+
148
+ #returns +[parse_tree|Exception, +[String.*]]
149
+ def parse_tree_and_warnings str
150
+ fork_server?
151
+ put str
152
+ tree=get
153
+ warnings=get
154
+ raise tree if Exception===tree
155
+ return tree,warnings
156
+ end
157
+
158
+ #this way is bad enough, but there's a fd leak this way,
159
+ #so I have to use the even more complicated version above
160
+ def parse_tree_and_warnings_leaks_stderr(str)
161
+ oldSTDERR=STDERR.dup
162
+ warnstash=Tempfile.new "warnstash"
163
+ warnings=[]
164
+
165
+ STDERR.reopen warnstash
166
+ tree=parse_tree_for_string(str)
167
+
168
+ return tree,warnings
169
+ ensure
170
+ STDERR.reopen oldSTDERR
171
+
172
+ warnstash.rewind
173
+ warnings.replace warnstash.read.split
174
+ warnstash.close
175
+ end
31
176
  end
32
177
 
33
178
  class RedParseTest<Test::Unit::TestCase
179
+ ERROR_EXAMPLES=[
180
+ '%W"is #{x}#{"Slim #{2?"W":"S"} "}."',
181
+ '%W"is #{x}#{"Slim #{2?"W":"S"}"}#{xx}."',
182
+ '%W"is #{x}#{"Slim #{2?W: S} "}."',
183
+ '%W"is #{x}#{%Q\'Slim #{2?W: S} \'}."',
184
+ '%W"is #{x}#{%W"Slim #{2?"W":"S"}"}#{xx}."',
185
+ '%W"is #{x}#{%W\'Slim #{2?W: S} \'}."',
186
+ '%W"is #{x}#{%q\'Slim #{2?W: S} \'}."',
187
+ '%W"is #{x}#{%r\'Slim #{2?W: S} \'}."',
188
+ '%W"is #{x}#{%w\'Slim #{2?W: S} \'}."',
189
+ '%W"is #{x}#{%x\'Slim #{2?W: S} \'}."',
190
+ '%W"is #{x}#{/Slim #{2?W: S} /}."',
191
+ '%W"is #{x}#{`Slim #{2?W: S} `}."',
192
+ '%W"is_#{"Slim_#{2?"W":"S"}"}#{xx}."',
193
+ '%W"is_#{x}#{"Slim_#{2?"W":"S"}"}#{xx}."',
194
+ '%W"is_#{x}#{"Slim_#{2?"W":"S"}_"}."',
195
+ ]
196
+ FAILURE_EXAMPLES=[
197
+ ]
198
+ RUBYBUG_EXAMPLES=[
199
+ 'def foo(a=b=c={}) end',
200
+ "$11111111111111111111111111111111111111111111111111111111111111111111",
201
+ "c do p (110).m end",
202
+ "case F;when G; else;case; when j; end;end",
203
+ "p = p m %(1)",
204
+ "p = p m %(1) ,&t",
205
+ "p = p m %(1) ,*t",
206
+ "p = p m %(1) ,t",
207
+ "p = p m %(1) do end",
208
+ "p=556;p (e) /a",
209
+ "z{|| p (1).m}",
210
+ 'def sum(options = {:weights => weights = Hash.new(1)}); options.empty? or options.keys.size > 1; end',
211
+ ]
212
+
34
213
  ONELINERS=[
214
+ 'z = valueo_s rescue "?"'...'',
215
+ '"#{publi}#{}>"'...'',
216
+ 'return (@images = @old_imgs)'...'',
217
+ ' /\A#{__FILE__}tcase/n =~ i '...'',
218
+ 'doc_status, err_args = Documeh_status{fcgi_state = 3; docespond do doc_response =fcgi_state = 1; end }'...'',
219
+ 'print "coled: " + $! +" wiin #{@ray}\n";'...'',
220
+ 'class A;def b;class <<self;@@p = false end;end;end'...'',
221
+ 'def d; return (block_given? ? begin; yield f; ensure; f.close; end : f); end'...'',
222
+ 'def sum(options = {:weights => weights = Hash.new(1)}); options.empty? or options.keys.size > 1; end'...'',
223
+ 'def d;e install_dir;end'...'',
224
+ '(m).kk,(m+n).kk=3'...'',
225
+ '((m).kk,(m+n).kk)=3'...'',
226
+ '((m).kk,(m+n).kk),t=3'...'',
227
+ 's,((m).kk,(m+n).kk)=3'...'',
228
+ 's,((m).kk,(m+n).kk),t=3'...'',
229
+ 'proc{|(m).kk,(m+n).kk| }'...'',
230
+ "p p:'b'"...'', #changes semantics in 1.9
231
+ "p:'b'"...'', #but this doesn't
232
+ 't ?6e0 : 5'...'',
233
+ "super[]"...'',
234
+ 'p end=5'...'', #illegal
235
+ 'p or=5'...'', #illegal
236
+ 'p else=5'...'', #illegal
237
+ 'p if=5'...'', #illegal
238
+ "x{\x0afor i in (begin\n[44,55,66,77,88] end) do p i**Math.sqrt(i) end\n}\n"...'',
239
+ 'e { |c|; print "%02X" % c }'...'',
240
+ %[p <<-heredoc "x y z" and 5\n a b c\n heredoc]...'',
241
+ "File.open() {|f| ; }"...'',
242
+ %[ p <<-heredoc "x y z" and 5\n a b c\n heredoc]...'',
243
+ 'a rescue b until 1'...'',
244
+ 'a rescue b while 1'...'',
245
+ '%W[r\\c 3]'...'',
246
+
247
+ "%w[a\\C- b]"...'',
248
+ "%w[a\\M- b]"...'',
249
+ "%w[a\\c b]"...'',
250
+ "%W[a\\c b]"...'',
251
+ "%w[a\\\\c b]"...'',
252
+ "%W[a\\\\c b]"...'',
253
+ "%w[a\\c b]"...'',
254
+ "%W[a\\c b]"...'',
255
+ "%w[a\\\\c b]"...'',
256
+ "%W[a\\\\c b]"...'',
257
+ "module A; b; rescue C=>d; e; else g; ensure f; end"...'',
258
+ "class<<A; b; rescue C=>d; e; else g; ensure f; end"...'',
259
+ "class A; b; rescue C=>d; e; else g; ensure f; end"...'',
260
+ 'def i;"..#{@@c = 1}";end'...'',
261
+ "def wait; begin; ync; mup; end ;end"...'',
262
+ "def e; begin; y; g else t; m; end ;end"...'',
263
+ '"#{}"""'...'',
264
+ %[%W(white\\ \\ \\ \\ \\ space).should == ["white ", " ", " ", " space"]]...'',
265
+ "%w[- \\\\ ]"...'',
266
+ "%w[- \\\\ e]"...'',
267
+ "begin begin; ync; p1; end;rr end"...'',
268
+ "begin;mode;rescue;o_chmod rescue nil;end"...'',
269
+ "%w![ ] { } ( ) | - * . \\\\ ? + ^ $ #!"...'',
270
+
271
+ 'def foo(a = 1) end; def foo(a=b=c={}) end; def bar(a=b=c=1,d=2) end'...'',
272
+ '() until 1'...'',
273
+ '(a) until 1'...'',
274
+ '(a) while l 1'...'',
275
+ "module A; B='' end"...'',
276
+ "{'one' => {}}"...'',
277
+ "a[3, 2] = 'a', 'b'"...'',
278
+ 'def st; begin ire end end'...'',
279
+ 'x{k=1; return-k}'...'',
280
+ 'x{k=1; return -k}'...'',
281
+ 'x{k=1; return- k}'...'',
282
+ 'x{k=1; return - k}'...'',
283
+ 'x{k=1; return + k}'...'',
284
+ 'x{k=1; return * k}'...'',
285
+ 'x{k=1; break - k}'...'',
286
+ 'x{k=1; next - k}'...'',
287
+ "p\r44"...'',
288
+ 'yield []'...'',
289
+ 'yield [1]'...'',
290
+ 'f{a rescue b}'...'',
35
291
  '%w[- \\\\\\\\ e]'...'',
36
292
  '%w[- \\\\\\\\ ]'...'',
37
- 'a=[]; a [42] = 24'...'', #not legal unless a is a local var
293
+ 'x{a=[]; a [42] = 24}'...'', #not legal unless a is a local var
38
294
  '%w![ ] { } ( ) | - * . \\\\\\\\ ? + ^ $ #!'...'',
39
295
  '%W(white\ \ \ \ \ space).should == ["white ", " ", " ", " space"]'...'',
40
296
  'module A; b; rescue C=>d; e; else g; ensure f; end'...'',
@@ -761,6 +1017,32 @@ class RedParseTest<Test::Unit::TestCase
761
1017
  '%W"is #{"Slim #{2?"W":"S"}"}."'...'',
762
1018
  '"is #{"Slim #{2?"W":"S"}"}#{xx}."'...'',
763
1019
  '%W"is #{"Slim #{2?"W":"S"}"}#{xx}."'...'',
1020
+ '"is #{x}#{"Slim #{2?"W":"S"}"}#{xx}."'...'',
1021
+ '%W"is #{x}#{"Slim #{2?"W":"S"}"}#{xx}."'...'',
1022
+ '"is #{x}#{%W"Slim #{2?"W":"S"}"}#{xx}."'...'',
1023
+ '%W"is #{x}#{%W"Slim #{2?"W":"S"}"}#{xx}."'...'',
1024
+
1025
+ '%W"is_#{x}#{"Slim_#{2?"W":"S"}"}#{xx}."'...'',
1026
+ '%W"is_#{"Slim_#{2?"W":"S"}"}#{xx}."'...'',
1027
+ '%W"is_#{"Slim_#{2?"W":"S"}"}."'...'',
1028
+ '%W"is_#{x}#{"Slim_#{2?"W":"S"}_"}."'...'',
1029
+ '%W"is_#{"Slim_#{2?"W":"S"}_"}."'...'',
1030
+ '%W"is_#{"Slim_#{2?"W":"S"}_" "rr"}."'...'',
1031
+
1032
+ "%W\"is \#{x}\#{%W'Slim \#{2?W: S} '}.\""...'',
1033
+ "%W\"is \#{x}\#{%w'Slim \#{2?W: S} '}.\""...'',
1034
+ "%W\"is \#{x}\#{%Q'Slim \#{2?W: S} '}.\""...'',
1035
+ "%W\"is \#{x}\#{\"Slim \#{2?W: S} \"}.\""...'',
1036
+ "%W\"is \#{x}\#{%q'Slim \#{2?W: S} '}.\""...'',
1037
+ "%W\"is \#{x}\#{%x'Slim \#{2?W: S} '}.\""...'',
1038
+ "%W\"is \#{x}\#{%r'Slim \#{2?W: S} '}.\""...'',
1039
+ "%W\"is \#{x}\#{`Slim \#{2?W: S} `}.\""...'',
1040
+ "%W\"is \#{x}\#{/Slim \#{2?W: S} /}.\""...'',
1041
+ "%\"is \#{x}\#{%r'Slim \#{2?W: S} '}.\""...'',
1042
+ "\"is \#{x}\#{%r'Slim \#{2?W: S} '}.\""...'',
1043
+ "\"is \#{x}\#{%'Slim \#{2?W: S} '}.\""...'',
1044
+ "\"is \#{x}\#{'Slim \#{2?W: S} '}.\""...'',
1045
+
764
1046
  'case $1; when 0,*[2,66]: p 1; when 3; 4 else p 2 end'...'',
765
1047
  'case $1; when 0,*a: p 1; when 3; 4 else p 2 end'...'',
766
1048
  ' p(String <<- Class)'...'',
@@ -2388,7 +2670,93 @@ class RedParseTest<Test::Unit::TestCase
2388
2670
  ]
2389
2671
 
2390
2672
 
2391
- STANZAS=%q[
2673
+ PASSTHRU_BSLASHES_ENTIRE=<<'END'
2674
+ <<-'foo'.count('\\')==0
2675
+ '
2676
+ foo
2677
+
2678
+ <<-'foo'.count('\\')==1
2679
+ \'
2680
+ foo
2681
+
2682
+ <<-'foo'.count('\\')==2
2683
+ \\'
2684
+ foo
2685
+
2686
+ <<-'foo'.count('\\')==3
2687
+ \\\'
2688
+ foo
2689
+
2690
+ <<-'foo'.count('\\')==4
2691
+ \\\\'
2692
+ foo
2693
+
2694
+ <<-'foo'.count('\\')==5
2695
+ \\\\\'
2696
+ foo
2697
+
2698
+ <<-"foo".count('\\')==0
2699
+ "
2700
+ foo
2701
+
2702
+ <<-"foo".count('\\')==0
2703
+ \"
2704
+ foo
2705
+
2706
+ <<-"foo".count('\\')==1
2707
+ \\"
2708
+ foo
2709
+
2710
+ <<-"foo".count('\\')==1
2711
+ \\\"
2712
+ foo
2713
+
2714
+ <<-"foo".count('\\')==2
2715
+ \\\\"
2716
+ foo
2717
+
2718
+ <<-"foo".count('\\')==2
2719
+ \\\\\"
2720
+ foo
2721
+
2722
+ <<-`foo`
2723
+ \`
2724
+ foo
2725
+
2726
+ <<-`foo`
2727
+ \\`
2728
+ foo
2729
+
2730
+ <<-"foo"
2731
+ \"
2732
+ foo
2733
+
2734
+ <<-"foo"
2735
+ "
2736
+ foo
2737
+
2738
+ <<-"foo"
2739
+ \\"
2740
+ foo
2741
+
2742
+ END
2743
+
2744
+ STANZAS=PASSTHRU_BSLASHES_ENTIRE+%q[
2745
+ return @senders[1] =
2746
+ 2
2747
+
2748
+ case
2749
+ when 0
2750
+ guecoding
2751
+ else case
2752
+ when eucjp_match_length
2753
+ guing
2754
+ end
2755
+ end
2756
+
2757
+ %w[ ac
2758
+ df]
2759
+
2392
2760
  begin
2393
2761
  a
2394
2762
  rescue B=>c
@@ -3003,11 +3371,11 @@ end
3003
3371
  end
3004
3372
 
3005
3373
  location_display = if(location.size == 1)
3006
- location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
3374
+ location[0].sub(/\\A(.+:\\d+).*/, ' [\\1]')
3007
3375
  else
3008
- "\n#{location.join("\n")}"
3376
+ "\\n#{location.join("\\n")}"
3009
3377
  end
3010
- "Failure:\n#@test_name#{location_display}:\n#@message"
3378
+ "Failure:\\n#@test_name#{location_display}:\\n#@message"
3011
3379
 
3012
3380
  def parse_date(aString)
3013
3381
  return Time.rfc822(aString) rescue Time.parse(aString)
@@ -3138,10 +3506,15 @@ EOS
3138
3506
  end
3139
3507
 
3140
3508
  EXAMPLES=ONELINERS.map{|rng| rng.first}+STANZAS.split(/\n( *\n)+/)+TestCases::TESTCASES+
3141
- from_rubinius #+ESC_SEQS
3509
+ from_rubinius + #ESC_SEQS +
3510
+ []-ERROR_EXAMPLES-FAILURE_EXAMPLES-RUBYBUG_EXAMPLES
3511
+
3142
3512
 
3143
3513
  WRAPPERS=[ #enable at most 2 or tests take forever!!!
3144
3514
  '(...)', #normal mode, should usually be enabled
3515
+ # 'a rescue (...)',
3516
+ # "((...))",
3517
+ # 'def ((...)).foo; end',
3145
3518
  # 'a0 = (...) rescue b0',
3146
3519
  # 'a0 = ((...)) rescue b0',
3147
3520
  # '(...) #with a comment',
@@ -3160,11 +3533,10 @@ EOS
3160
3533
  # 'a=b,c=d',
3161
3534
  ]
3162
3535
  puts "warning: most data fuzzing is disabled for now"
3163
- puts "warning: unparser tests disabled for now"
3164
3536
 
3165
- RUBYIDENT=/((?:$|@@?)?[a-z_][a-z_0-9]*[?!]?)/i
3537
+ RUBYIDENT=/((?:$|@@?)?#{RubyLexer::LETTER}#{RubyLexer::LETTER_DIGIT}*[?!]?)/o
3166
3538
 
3167
- def self.snippet2testmethod(snippet)
3539
+ def self.snippet2testmethod(snippet,wrap=nil)
3168
3540
  escaped=snippet.gsub(/[\\']/){"\\"+$&}
3169
3541
  safe=escaped.gsub(/([^ -~])/){
3170
3542
  x=$1[0].to_s(16)
@@ -3173,11 +3545,13 @@ EOS
3173
3545
  }
3174
3546
  safe.gsub! /\\\\/,"__"
3175
3547
  safe[/[^ -~]|\\\\/] and fail
3548
+ cp="check_parsing '#{escaped}',pt"
3549
+ cp="#{wrap}{#{cp}}" if wrap
3176
3550
  "
3177
3551
  define_method 'test_parsing_of_#{safe}' do
3178
3552
  #puts 'test_parsing_of_#{safe}'
3179
3553
  pt=ParseTree.new
3180
- check_parsing '#{escaped}',pt
3554
+ #{cp}
3181
3555
  end
3182
3556
  "
3183
3557
  end
@@ -3190,25 +3564,83 @@ EOS
3190
3564
  /\A\s*x\s*\{(.*)\}\Z/===xmpl and xmpl=$1
3191
3565
  # xmpl= (xmpl[/\A\s*x\s*\{(.*)\}\s*(#.*)?\Z/,1] rescue xmpl)
3192
3566
 
3193
- wrapped=WRAPPERS.map{|wrap|
3194
- #apply wrapper
3195
- snippet2testmethod(wrap.gsub('(...)', xmpl))
3196
- }
3197
- injected=INJECTABLES.map{|inj|
3198
- xlist=xmpl.split(RUBYIDENT)
3199
- if xlist.size>1
3200
- i=rand(xlist.size&~1)|1
3201
- i&1==1 or fail
3202
- /\A#{RUBYIDENT}\Z/o===xlist[i] or fail
3203
- xlist[i]=inj
3204
- snippet2testmethod(xlist.to_s)
3205
- end
3206
- }
3207
- wrapped+injected
3567
+ wrapped=WRAPPERS.map{|wrap|
3568
+ #apply wrapper
3569
+ maybe_slow="slow" if xmpl.size>1000
3570
+ wrap=wrap.dup
3571
+ wrap['(...)']=xmpl
3572
+ snippet2testmethod(wrap,maybe_slow)
3573
+ }
3574
+ injected=INJECTABLES.map{|inj|
3575
+ xlist=xmpl.split(RUBYIDENT)
3576
+ if xlist.size>1
3577
+ i=rand(xlist.size&~1)|1
3578
+ i&1==1 or fail
3579
+ /\A#{RUBYIDENT}\Z/o===xlist[i] or fail
3580
+ xlist[i]=inj
3581
+ maybe_slow="slow" if xmpl.size>1000
3582
+ snippet2testmethod(xlist.to_s,maybe_slow)
3583
+ end
3584
+ }
3585
+ wrapped+injected
3208
3586
  }.to_s
3209
3587
  #puts code.split("\n")[5880..5890].join("\n")
3210
3588
  eval code
3211
3589
 
3590
+ error_code=RUBYBUG_EXAMPLES.map{|xmpl|
3591
+ #remove comment if present
3592
+ /\A(.*)\s*\Z/===xmpl and xmpl=$1
3593
+ #remove x{...} wrapper if present
3594
+ /\A\s*x\s*\{(.*)\}\Z/===xmpl and xmpl=$1
3595
+
3596
+ snippet2testmethod(xmpl, :known_ruby_bug)
3597
+ }.to_s
3598
+ eval error_code
3599
+
3600
+ error_code=ERROR_EXAMPLES.map{|xmpl|
3601
+ #remove comment if present
3602
+ /\A(.*)\s*\Z/===xmpl and xmpl=$1
3603
+ #remove x{...} wrapper if present
3604
+ /\A\s*x\s*\{(.*)\}\Z/===xmpl and xmpl=$1
3605
+
3606
+ snippet2testmethod(xmpl, :known_error)
3607
+ }.to_s
3608
+ eval error_code
3609
+
3610
+ failure_code=FAILURE_EXAMPLES.map{|xmpl|
3611
+ #remove comment if present
3612
+ /\A(.*)\s*\Z/===xmpl and xmpl=$1
3613
+ #remove x{...} wrapper if present
3614
+ /\A\s*x\s*\{(.*)\}\Z/===xmpl and xmpl=$1
3615
+
3616
+ snippet2testmethod(xmpl, :known_failure)
3617
+ }.to_s
3618
+ eval failure_code
3619
+
3620
+ def known_ruby_bug
3621
+ from=caller.first
3622
+ from=from[/ in `.*'\Z/] || from[/\A[^:]*:[^:]*/]
3623
+ yield
3624
+ rescue Test::Unit::AssertionFailedError=>e
3625
+ warn "a known bug in MRI reared its head in #{from}: #{e.message}"
3626
+ if defined? @@known_ruby_bugs
3627
+ @@known_ruby_bugs+=1
3628
+ else
3629
+ @@known_ruby_bugs=1
3630
+ at_exit {warn "unfixed bugs in MRI/ParseTree: #@@known_ruby_bugs"}
3631
+ end
3632
+ rescue Exception=>e
3633
+ raise
3634
+ else
3635
+ warn "expected bug in MRI in #{from}, but was fixed(?!)"
3636
+ if defined? @@known_ruby_bugs_fixed
3637
+ @@known_ruby_bugs_fixed+=1
3638
+ else
3639
+ @@known_ruby_bugs_fixed=1
3640
+ at_exit {warn "unexpectedly fixed known MRI/ParseTree bugs: #@@known_ruby_bugs_fixed"}
3641
+ end
3642
+ end
3643
+
3212
3644
  def test_case_that_segfaults_ruby185
3213
3645
  assert_equal \
3214
3646
  [[:op_asgn1, [:call, [:vcall, :a], :b], [:zarray], :%, [:vcall, :d]]],
@@ -3227,13 +3659,91 @@ EOS
3227
3659
  RedParse.new('Proc{|&b|}','-').parse.to_parsetree(:quirks)
3228
3660
  end
3229
3661
 
3662
+ def test_cases_misparsed_by_ruby186_slash_parsetree
3663
+ {"$11111111111111111111111111111111111111111111111111111111111111111111"=>[
3664
+ [:nth_ref, 11111111111111111111111111111111111111111111111111111111111111111111]],
3665
+ "c do p (110).m end"=>[
3666
+ [:iter, [:fcall, :c], nil, [:fcall, :p, [:array, [:call, [:lit, 110], :m]]]]],
3667
+ "case F;when G; else;case; when j; end;end"=>[
3668
+ [:case, [:const, :F], [:when, [:array, [:const, :G]], nil],
3669
+ [:case, nil, [:when, [:array, [:vcall, :j]], nil], nil]]],
3670
+ "p = p m %(1)"=>[
3671
+ [:lasgn, :p, [:fcall, :p, [:array, [:fcall, :m, [:array, [:str, "1"]]]]]]],
3672
+ "p = p m %(1) ,&t"=>[
3673
+ [:lasgn, :p, [:fcall, :p, [:array,
3674
+ [:block_pass, [:vcall, :t], [:fcall, :m, [:array, [:str, "1"]]]]]]]],
3675
+ "p = p m %(1) ,*t"=>[
3676
+ [:lasgn, :p, [:fcall, :p,
3677
+ [:array, [:fcall, :m, [:argscat, [:array, [:str, "1"]], [:vcall, :t]]]]]]],
3678
+ "p = p m %(1) ,t"=>[
3679
+ [:lasgn, :p, [:fcall, :p, [:array, [:fcall, :m,
3680
+ [:array, [:str, "1"], [:vcall, :t]]]]]]],
3681
+ "p = p m %(1) do end"=>[
3682
+ [:lasgn, :p, [:iter, [:fcall, :p, [:array,
3683
+ [:fcall, :m, [:array, [:str, "1"]]]]], nil]]],
3684
+ "p=556;p (e) /a"=>[
3685
+ [:block, [:lasgn, :p, [:lit, 556]],
3686
+ [:fcall, :p, [:array, [:call, [:vcall, :e], :/, [:array, [:vcall, :a]]]]]]],
3687
+ "z{|| p (1).m}"=>[
3688
+ [:iter, [:fcall, :z], 0, [:fcall, :p, [:array, [:call, [:lit, 1], :m]]]]],
3689
+ "
3690
+ <<-'foo'
3691
+ \\'
3692
+ foo
3693
+ "=>[[:str, " \\'\n"]],
3694
+ "
3695
+ <<-'foo'
3696
+ \\\\'
3697
+ foo
3698
+ "=>[[:str, " \\\\'\n"]],
3699
+ "
3700
+ <<-'foo'
3701
+ \\\\\\'
3702
+ foo
3703
+ "=>[[:str, " \\\\\\'\n"]],
3704
+ "
3705
+ <<-'foo'
3706
+ \\\\\\\\'
3707
+ foo
3708
+ "=>[[:str, " \\\\\\\\'\n"]],
3709
+ "
3710
+ <<-'foo'
3711
+ \\\\\\\\\\'
3712
+ foo
3713
+ "=>[[:str, " \\\\\\\\\\'\n"]],
3714
+ "
3715
+ <<-'foo'
3716
+ \\\\\\\\\\\\'
3717
+ foo
3718
+ "=>[[:str, " \\\\\\\\\\\\'\n"]],
3719
+
3720
+
3721
+ }.each_pair{|code,tree|
3722
+ assert_equal tree,RedParse.new(code,'-').parse.to_parsetree(:quirks)
3723
+ }
3724
+ end
3725
+
3726
+ POWERS_OF_2={}
3727
+ i=1
3728
+ while i<1_000_000_000
3729
+ POWERS_OF_2[i]=1
3730
+ i*=2
3731
+ end
3732
+
3230
3733
  def assert_hopefully_raises_Exception xmpl
3231
3734
  begin
3232
3735
  yield
3233
3736
  rescue Exception
3234
3737
  assert true
3235
3738
  else
3236
- puts "warning: syntax error expected, but none was seen, expression: <<< #{xmpl} >>>"
3739
+ if defined? @@missed_syntax_errors
3740
+ @@missed_syntax_errors+=1
3741
+ else
3742
+ @@missed_syntax_errors=1
3743
+ at_exit{warn "missed syntax errors: #@@missed_syntax_errors"}
3744
+ end
3745
+ #puts "warning: syntax error expected, but none was seen, expression: <<< #{xmpl} >>>" if
3746
+ # POWERS_OF_2[@@missed_syntax_errors]
3237
3747
  end
3238
3748
  end
3239
3749
 
@@ -3248,11 +3758,12 @@ EOS
3248
3758
  @problem_exprs=$stdout
3249
3759
  end
3250
3760
 
3251
- @@differed_by_nil=0
3252
-
3253
3761
  def check_parsing xmpl,pt=ParseTree.new
3762
+ pt_opts=[:quirks]
3763
+ pt_opts<<:ruby187 if ::VERSION["1.8.7"]
3254
3764
  /unparse/===xmpl and warn 'unparse in parser test data!'
3255
3765
  problem_exprs=problem_exprs()
3766
+ nodes=warnings=warnings2=nil
3256
3767
  =begin
3257
3768
  xmpl=<<-prefix+xmpl+<<-suffix
3258
3769
  BEGIN{throw :never_exec_parse_data_try1,1}
@@ -3272,31 +3783,39 @@ EOS
3272
3783
  # catch(:never_exec_parse_data_try1){
3273
3784
  # catch(:never_exec_parse_data_try2){
3274
3785
  # catch(:never_exec_parse_data_try3){
3275
- tree=pt.parse_tree_for_string(xmpl)
3786
+ tree,warnings=pt.parse_tree_and_warnings(xmpl)
3276
3787
  # }
3277
3788
  # }
3278
3789
  # }
3279
3790
  # break if loops+=1 > 3
3280
- rescue Interrupt: raise
3281
- rescue Exception=>e:
3791
+ rescue Interrupt; raise
3792
+ rescue Exception=>e
3793
+ #pp e
3794
+ #pp e.backtrace
3282
3795
  #raise "last gasp ParseTree exec catcher failed!"
3283
3796
  tree=e
3284
- tree2=nodes=nil
3797
+ tree2=nodes=h=nil
3285
3798
  assert_hopefully_raises_Exception(xmpl){
3286
3799
  nodes=RedParse.new(xmpl,"-").parse
3287
- tree2=nodes.to_parsetree(:quirks)
3800
+ h=nodes.hash
3801
+ tree2,warnings2=nodes.to_parsetree_and_warnings(*pt_opts)
3288
3802
  }
3803
+ assert_equal h,nodes.hash if h
3289
3804
  else
3290
3805
  begin
3291
3806
  nodes=RedParse.new(xmpl,"-").parse
3292
- tree2=nodes.to_parsetree(:quirks)
3293
- if tree==tree2
3294
- assert true
3295
- else
3296
- assert_equal recursive_compact!(tree), recursive_compact!(tree2)
3297
- warn "parsetree differed by nil(s), expression #{xmpl}"
3298
- @@differed_by_nil+=1
3299
- END{ puts "#@@differed_by_nil expressions differed by nil(s)" }
3807
+ h=nodes.hash
3808
+ tree2,warnings2=nodes.to_parsetree_and_warnings(*pt_opts)
3809
+ assert_equal h,nodes.hash
3810
+ assert_equal tree, tree2
3811
+ assert_equal warnings, warnings2 if ENV['WARN_PICKINESS']
3812
+ if warnings != warnings2
3813
+ if defined? @@mismatched_warnings
3814
+ @@mismatched_warnings+=1
3815
+ else
3816
+ @@mismatched_warnings=1
3817
+ at_exit{warn "mismatched warnings: #@@mismatched_warnings (set WARN_PICKINESS for details)"}
3818
+ end
3300
3819
  end
3301
3820
  rescue Exception=>e
3302
3821
  if problem_exprs
@@ -3313,26 +3832,40 @@ EOS
3313
3832
 
3314
3833
  end #until output.equal? tree
3315
3834
 
3316
- return #skip unparse tests for now
3835
+ # puts "warning: unparser tests disabled for now"
3836
+ # return #skip unparse tests for now
3317
3837
 
3318
- reparsed= RedParse.new(nodes.unparse({}),"-").parse
3319
- assert_equal nodes.delete_extraneous_ivars!,
3320
- reparsed.delete_extraneous_ivars!
3838
+ return unless nodes
3839
+ begin
3840
+ unparsed=nodes.unparse
3841
+ if unparsed==xmpl
3842
+ assert true
3843
+ return
3844
+ end
3845
+ reparsed= RedParse.new(unparsed,"-").parse
3846
+ if nodes.delete_extraneous_ivars! != reparsed.delete_extraneous_ivars!
3847
+ assert_equal nodes.delete_linenums!, reparsed.delete_linenums!
3848
+ warn "unparser doesn't preserve linenums perfectly in #{xmpl}"
3849
+ if defined? @@unparse_mismatched_linenums
3850
+ @@unparse_mismatched_linenums+=1
3851
+ else
3852
+ @@unparse_mismatched_linenums=1
3853
+ at_exit{warn "unparse mismatched linenums: #@@unparse_mismatched_linenums"}
3854
+ end
3855
+ else
3856
+ assert true
3857
+ end
3858
+ rescue Exception
3859
+ raise unless Exception===tree
3860
+ end
3321
3861
 
3322
- tree3=reparsed.to_parsetree(:quirks)
3323
- assert_equal tree, tree3
3862
+ unless Exception===tree
3863
+ tree3=reparsed.to_parsetree(*pt_opts)
3864
+ assert_equal tree, tree3
3865
+ else #missing a syntax errr, but that's been noted already
3866
+ end
3324
3867
 
3325
3868
  # rescue Exception=>e:
3326
3869
  # raise "error: #{e}:#{e.class} while testing '#{xmpl}'"
3327
3870
  end
3328
-
3329
- def recursive_compact!(tree)
3330
- return tree unless Array===tree
3331
- recursive_compact_!(tree)
3332
- end
3333
- def recursive_compact_!(tree)
3334
- tree.compact!
3335
- tree.each{|subtree| recursive_compact_!(subtree) if Array===subtree}
3336
- return tree
3337
- end
3338
3871
  end