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