redparse 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +33 -2
- data/Manifest.txt +2 -3
- data/README.txt +157 -265
- data/Rakefile +13 -4
- data/bin/redparse +3 -2
- data/lib/redparse.rb +2423 -489
- data/lib/redparse/generate.rb +378 -0
- data/lib/redparse/node.rb +1497 -620
- data/lib/redparse/reg_more_sugar.rb +21 -0
- data/lib/redparse/version.rb +1 -1
- data/test/data/def_spec.rb +2 -0
- data/test/rp-locatetest.rb +2 -1
- data/test/test_redparse.rb +594 -61
- metadata +17 -8
- data/nurli/test_control.nurli +0 -261
- data/redparse.vpj +0 -92
- data/redparse.vpw +0 -8
@@ -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
|
data/lib/redparse/version.rb
CHANGED
data/test/rp-locatetest.rb
CHANGED
@@ -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\.
|
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
|
data/test/test_redparse.rb
CHANGED
@@ -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
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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(
|
3374
|
+
location[0].sub(/\\A(.+:\\d+).*/, ' [\\1]')
|
3007
3375
|
else
|
3008
|
-
"
|
3376
|
+
"\\n#{location.join("\\n")}"
|
3009
3377
|
end
|
3010
|
-
"Failure
|
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
|
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=/((?:$|@@?)
|
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
|
-
|
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
|
-
|
3194
|
-
|
3195
|
-
|
3196
|
-
|
3197
|
-
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3204
|
-
|
3205
|
-
|
3206
|
-
|
3207
|
-
|
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
|
-
|
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.
|
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
|
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
|
-
|
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
|
-
|
3293
|
-
|
3294
|
-
|
3295
|
-
|
3296
|
-
|
3297
|
-
|
3298
|
-
@@
|
3299
|
-
|
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
|
-
|
3835
|
+
# puts "warning: unparser tests disabled for now"
|
3836
|
+
# return #skip unparse tests for now
|
3317
3837
|
|
3318
|
-
|
3319
|
-
|
3320
|
-
|
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
|
-
|
3323
|
-
|
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
|