redparse 0.8.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -0
  2. data/COPYING.LGPL +503 -158
  3. data/History.txt +192 -0
  4. data/Makefile +9 -0
  5. data/README.txt +72 -39
  6. data/bin/redparse +108 -14
  7. data/lib/miniredparse.rb +1543 -0
  8. data/lib/redparse.rb +971 -105
  9. data/lib/redparse/ReduceWithsFor_RedParse_1_8.rb +17412 -0
  10. data/lib/redparse/ReduceWithsFor_RedParse_1_9.rb +17633 -0
  11. data/lib/redparse/babynodes.rb +17 -0
  12. data/lib/redparse/babyparser.rb +17 -0
  13. data/lib/redparse/cache.rb +290 -6
  14. data/lib/redparse/compile.rb +6 -97
  15. data/lib/redparse/decisiontree.rb +1 -1
  16. data/lib/redparse/float_accurate_to_s.rb +30 -6
  17. data/lib/redparse/generate.rb +18 -0
  18. data/lib/redparse/node.rb +415 -124
  19. data/lib/redparse/parse_tree_server.rb +20 -2
  20. data/lib/redparse/problemfiles.rb +1 -1
  21. data/lib/redparse/pthelper.rb +17 -31
  22. data/lib/redparse/reg_more_sugar.rb +1 -1
  23. data/lib/redparse/replacing/parse_tree.rb +30 -0
  24. data/lib/redparse/replacing/ripper.rb +20 -0
  25. data/lib/redparse/replacing/ruby_parser.rb +28 -0
  26. data/lib/redparse/ripper.rb +393 -0
  27. data/lib/redparse/ripper_sexp.rb +153 -0
  28. data/lib/redparse/stackableclasses.rb +113 -0
  29. data/lib/redparse/version.rb +18 -1
  30. data/redparse.gemspec +29 -9
  31. data/rplt.txt +31 -0
  32. data/test/data/hd_with_blank_string.rb +3 -0
  33. data/test/data/pt_known_output.rb +13273 -0
  34. data/test/data/wp.pp +0 -0
  35. data/test/generate_parse_tree_server_rc.rb +17 -0
  36. data/test/rp-locatetest.rb +2 -2
  37. data/test/test_1.9.rb +338 -35
  38. data/test/test_all.rb +22 -3
  39. data/test/test_part.rb +32 -0
  40. data/test/test_redparse.rb +396 -74
  41. data/test/test_xform_tree.rb +18 -0
  42. data/test/unparse_1.9_exceptions.txt +85 -0
  43. data/test/unparse_1.9_exceptions.txt.old +81 -0
  44. metadata +71 -46
  45. data/Rakefile +0 -35
File without changes
@@ -1,4 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
+ =begin copyright
3
+ redparse - a ruby parser written in ruby
4
+ Copyright (C) 2008,2009, 2012, 2016 Caleb Clausen
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ =end
2
19
  require 'rubygems'
3
20
  require 'parse_tree'
4
21
 
@@ -1,6 +1,6 @@
1
- =begin
1
+ =begin copyright
2
2
  redparse - a ruby parser written in ruby
3
- Copyright (C) 2008 Caleb Clausen
3
+ Copyright (C) 2008, 2012, 2016 Caleb Clausen
4
4
 
5
5
  This library is free software; you can redistribute it and/or
6
6
  modify it under the terms of the GNU Lesser General Public
@@ -1,16 +1,34 @@
1
+ #encoding: utf-8
2
+ =begin copyright
3
+ redparse - a ruby parser written in ruby
4
+ Copyright (C) 2008,2009, 2012, 2016 Caleb Clausen
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ =end
1
19
  require 'test/unit'
2
20
  require 'rubylexer/test/oneliners_1.9'
3
21
  require "redparse"
4
22
 
5
23
  class TestsFor1_9 < Test::Unit::TestCase
24
+ include Ruby1_9OneLiners
25
+
6
26
  RUBY_1_9_TO_1_8_EQUIVALENCES=[
7
27
  '{a: b}'...'{:a=>b}',
8
28
  '{a: b, c: d}'...'{:a=>b, :c=>d}',
9
29
  "a ? b\n : c"..."a ? b : \n c",
10
-
11
- 'not(true)'...'not true',
12
- 'not(+1)'...'not +1',
13
- 'not (true).to_s'...'not (true).to_s', #equivalent, but parser gets there different ways
30
+ '{a: 1,b: 2,c=>3}'...'{:a=>1,:b=>2,c=>3}',
31
+ 'a b {p 1} do p 2 end'...'a(b {p 1}) do p 2 end',
14
32
  ]
15
33
 
16
34
  RUBY_1_9_TO_1_8_EQUIVALENCES_BUT_FOR_STRESC=[
@@ -31,84 +49,369 @@ class TestsFor1_9 < Test::Unit::TestCase
31
49
  '/bb/m'...'/bb/m',
32
50
  '/b b/x'...'/b b/x',
33
51
  '/b#{b}/o'...'/b#{b}/o',
52
+ '
53
+ a
54
+ .b'...
55
+ '
56
+ a\
57
+ .b',
58
+ ]
59
+ RUBY_1_9_TO_1_9_EQUIVALENCES=[
60
+ '"♥"'...'?♥',
61
+ '"\u2666"'...'?\u2666',
34
62
  ]
35
63
 
36
64
 
37
65
  RUBY_1_9_VALID=[
66
+ "__ENCODING__",
38
67
  'not (true).to_s',
68
+ '"\u2665"',
69
+ '"♥"',
70
+ '"\u{2665 2666}"',
71
+ '"♥♦"',
72
+ '"\u{10fffd}"',
73
+ '"􏿽"' ,
74
+ '?\u2665','?♥',
75
+ '?\u{10fffd}','?􏿽' ,
76
+
77
+
78
+ 'def !=(x); end',
79
+ 'def !~(x); end',
80
+ 'alias x !=',
81
+ 'alias != x',
82
+ 'alias x !~',
83
+ 'alias !~ x',
84
+ 'alias !~ !=',
85
+ 'alias != !~',
86
+ 'alias != `',
87
+ 'undef !=',
88
+ 'undef !~',
89
+ ':!=',
90
+ ':!~',
91
+
92
+ 'def !@; end',
93
+ 'alias x !@',
94
+ 'alias !@ x',
95
+ 'alias !@ `',
96
+ 'undef !@',
97
+ ':!@',
98
+
99
+ 'z=*a,b,c',
100
+ 'z=a,*b,c',
101
+ 'z=a,*b,*c',
102
+ 'z=a,*b,c,*d',
103
+ 'z=*a,*b,*c,*d',
104
+ 'z=*a,*b,*c,*d,e',
105
+
106
+
107
+ 'proc{|a,*b,c|d}',
108
+ 'proc{|a,*b,(c1,*c2,c3)|d}',
109
+ 'proc{|*a,b,c|d}',
110
+ 'proc{|&a| x}',
111
+ 'proc{|a,&b| x}',
112
+ 'proc{|a,b=10| x}',
113
+ 'proc{|a=10,b| x}',
114
+
115
+ 'z(*a,b,c)',
116
+ 'z(a,*b,c)',
117
+ 'z(a,*b,*c)',
118
+ 'z(a,*b,c,*d)',
119
+ 'z(*a,*b,*c,*d)',
120
+ 'z(*a,*b,*c,*d,e)',
121
+ 'z[*a,b,c]',
122
+ 'z[a,*b,c]',
123
+ 'z[a,*b,*c]',
124
+ 'z[a,*b,c,*d]',
125
+ 'z[*a,*b,*c,*d]',
126
+ 'z[*a,*b,*c,*d,e]',
127
+
128
+ 'z[*a,b,c]=1',
129
+ 'z[a,*b,c]=1',
130
+ 'z[a,*b,*c]=1',
131
+ 'z[a,*b,c,*d]=1',
132
+ 'z[*a,*b,*c,*d]=1',
133
+ 'z[*a,*b,*c,*d,e]=1',
134
+
135
+ '[*a,b,c]',
136
+ '[a,*b,c]',
137
+ '[a,*b,*c]',
138
+ '[a,*b,c,*d]',
139
+ '[*a,*b,*c,*d]',
140
+ '[*a,*b,*c,*d,e]',
141
+
142
+ 'not(true)','not true',
143
+ 'not(+1)','not +1',
144
+ 'not (true).to_s','not (true).to_s',
145
+
146
+
39
147
  ]
40
148
 
149
+ RUBY_1_9_INVALID=[
150
+ '{1,2,3,4}',
151
+ 'if a: b; end',
152
+ 'unless a: b; end',
153
+ 'while a: b; end',
154
+ 'until a: b; end',
155
+ 'case z; when a: b; end',
156
+ 'proc{|a,b;c| d e f }',
157
+ ]
158
+
159
+ EXPECT_1_METHOD.concat [
160
+ '1.!=2',
161
+ '1.!~2',
162
+ 'a,*b,c=d',
163
+ 'a,*b,(c1,*c2,c3)=d',
164
+ '*a,b,c=d',
165
+ 'proc{|a=1,*b,(c1,*c2,c3),d=2,&e;f,g,h| [ b,c3,d,e,f,g,h ]}',
166
+ #'def z(a=1,*b,(c1,*c2,c3),d=2,&e;f,g,h) [ b,f,g,h ] end',
167
+ '$f.($x,$y)',
168
+ '$f::($x,$y)',
169
+ '$f.($x,$y){}',
170
+ '$f.($x,$y) do |stuff| $yada-$yada end',
171
+ '$f.($x,$y) do |stuff;nonsense| $yada-$yada end',
172
+ 'proc{|a=1,*b,d| b}',
173
+ 'proc{|&e;f| e }',
174
+ 'proc{|aa,a=1,az,*b,(c1,*c2,c3),da,d=2,dz,(e1=1,*e2,e3=3),&m;f,g,h| [ b,c3,d,e1,e2,e3,f,g,h,m ]}',
175
+ 'def z(aa,a=1,az,*b,(c1,*c2,c3),da,d=2,dz,(e1=1,*e2,e3=3),&m) [ b,c3,d,e1,e2,e3,m ] end',
176
+ 'aa,a,az,*b,(c1,*c2,c3),da,d,dz,(e1,*e2,e3)=k + [b,c3,d,e1,e2,e3] ',
177
+ '->(aa,a=1,az,*b,(c1,*c2,c3),da,d=2,dz,(e1=1,*e2,e3=3),&m;f,g,h){[ b,c3,d,e1,e2,e3,f,g,h,m ]}',
178
+ '->(a=1,*b,(c1,*c2,c3),d=2,&e;f,g,h){ [ b,c3,d,e,f,g,h ]}',
179
+ '->(a=1,*b,(c1,*c2,c3),d=2,&e;f,g,h) do [ b,c3,d,e,f,g,h ] end',
180
+ '->a=1,*b,(c1,*c2,c3),d=2,&e;f,g,h{ [ b,c3,d,e,f,g,h ]}',
181
+ ]
182
+ EXPECT_2_METHODS=EXPECT_1_METHOD.grep( /foo=1/ )
183
+ EXPECT_1_METHOD.replace(EXPECT_1_METHOD-EXPECT_2_METHODS)
184
+
185
+ EXPECT_1_METHOD.concat( EXPECT_NO_METHODS.grep( /->/ ) )
186
+ # EXPECT_NO_METHODS.concat [
187
+ # ]
188
+ EXPECT_NO_METHODS.replace(EXPECT_NO_METHODS-EXPECT_1_METHOD)
189
+
190
+ EXPECT_NO_MULTIASSIGNS= EXPECT_NO_METHODS+EXPECT_1_METHOD
191
+ EXPECT_NO_SEQUENCES= EXPECT_NO_MULTIASSIGNS.dup#.reject{|x| /; foo \+1/===x }
192
+
193
+ WEAK=RUBY_1_9_VALID+EXPECT_NO_METHODS+EXPECT_1_METHOD+RUBY_1_9_TO_1_9_EQUIVALENCES.map{|r| [r.first,r.last]}.flatten
194
+
195
+ warn "do something more with WEAK cases"
196
+
41
197
  include RedParse::Nodes
42
198
  RUBY_1_9_PATTERNS={
43
- 'not(true).to_s'=>+CallNode[+UnOpNode["not", +VarLikeNode["true"]], "to_s"],
199
+ 'not(true).to_s'=>+CallNode[+KWCallNode[nil, "not", +[+VarLikeNode["true"]], nil,nil,nil], "to_s" ,nil,nil,nil,nil],
200
+ 'f.(a=1,2,3)'=>+CallNode[_,"()",-{:size=>3},nil,nil,nil]
44
201
  }
45
202
 
203
+ def parser src,name
204
+ RedParse.new(src,name,1,[],:rubyversion=>1.9,:cache_mode=>:none,:encoding=>:utf8)
205
+ end
206
+
207
+ EXCEPTIONS={}
208
+ File.open("test/unparse_1.9_exceptions.txt"){|f|
209
+ until f.eof?
210
+ l=f.readline
211
+ l<<f.readline until l.chomp!"\\\\\\///\n"
212
+ input,output=*l.split(' ====> ',2)
213
+ EXCEPTIONS[input]||=[]
214
+ EXCEPTIONS[input]<<output
215
+ end
216
+ } if File.exist?("test/unparse_1.9_exceptions.txt")
217
+
218
+ def confirm_error?(code,code2)
219
+ puts 'unparse didn`t match. original:'
220
+ puts code
221
+ puts 'unparsed:'
222
+ puts code2
223
+ answer=nil
224
+ while true
225
+ puts 'is this difference an error? (y/n)'
226
+ answer=gets
227
+ return true if /\Ay/i===answer
228
+ return false if /\An/i===answer
229
+ end
230
+ return answer
231
+ end
232
+
233
+ def assert_unparses_to pt,code
234
+ code2=pt.unparse
235
+ if code==code2 or (EXCEPTIONS[code] and EXCEPTIONS[code].include? code2)
236
+ assert true
237
+ elsif confirm_error?(code,code2)
238
+ assert_equal code,code2
239
+ else
240
+ assert true
241
+ fail if %r{ ====> |\\\\\\///\n}===code2+code
242
+ File.open("test/unparse_1.9_exceptions.txt","a"){|fd| fd.print code,' ====> ', code2,"\\\\\\///\n" }
243
+ end
244
+ end
245
+
46
246
  def test_ruby19_equivs
47
247
  RUBY_1_9_TO_1_8_EQUIVALENCES.each{|pair|
48
248
  new,old=pair.first,pair.last
49
- pt19=RedParse.new(new,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
249
+ pt19=parser(new,'(eval)').parse
50
250
  pt18=RedParse.new(old,'(eval)',1,[],:cache_mode=>:none).parse
51
251
  assert_equal pt18,pt19
252
+ assert_unparses_to pt19,new
253
+ }
254
+ end
255
+
256
+ def test_ruby19_19_equivs_but_for_open_close
257
+ RUBY_1_9_TO_1_9_EQUIVALENCES.each{|pair|
258
+ new,old=pair.first,pair.last
259
+ pt1=parser(new,'(eval)').parse
260
+ pt2=parser(old,'(eval)').parse
261
+ assert_unparses_to pt1,new
262
+ assert_unparses_to pt2,old
263
+ pt1.instance_eval{@open=@close=nil if @open}
264
+ pt2.instance_eval{@open=@close=nil if @open}
265
+ assert_equal pt1,pt2
52
266
  }
53
267
  end
54
268
 
55
269
  def test_ruby19_equivs_but_for_stresc
56
270
  RUBY_1_9_TO_1_8_EQUIVALENCES_BUT_FOR_STRESC.each{|pair|
57
271
  new,old=pair.first,pair.last
58
- pt19=RedParse.new(new,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
272
+ pt19=parser(new,'(eval)').parse
59
273
  pt18=RedParse.new(old,'(eval)',1,[],:cache_mode=>:none).parse
60
- if pt18.instance_variable_get(:@bs_handler)==:dquote_esc_seq
61
- pt18.instance_variable_set :@bs_handler,:dquote19_esc_seq
62
- else
63
- pt18.instance_variable_set :@bs_handler,:Wquote19_esc_seq
64
- pt18.instance_variable_get(:@parses_like).each{|x|
65
- x.instance_variable_set :@bs_handler,:Wquote19_esc_seq if x.instance_variable_get :@bs_handler
66
- }
67
- end
274
+ [pt18,*pt18].each{|node|
275
+ case node.instance_variable_get(:@bs_handler)
276
+ when :dquote_esc_seq
277
+ node.instance_variable_set :@bs_handler,:dquote19_esc_seq
278
+ when :regex_esc_seq,nil #do nothing
279
+ else
280
+ node.instance_variable_set :@bs_handler,:Wquote19_esc_seq
281
+ pl=node.instance_variable_get(:@parses_like)
282
+ pl.each{|x|
283
+ x.instance_variable_set :@bs_handler,:Wquote19_esc_seq if x.instance_variable_get :@bs_handler
284
+ } if pl
285
+ end
286
+ }
68
287
  assert_equal pt18,pt19
288
+ assert_unparses_to pt19,new
69
289
  }
70
290
  end
71
291
 
72
- def test_ruby19_valid
73
- RUBY_1_9_VALID.each{|xmpl|
74
- pt19=RedParse.new(xmpl,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
292
+ RUBY_1_9_VALID.each{|xmpl|
293
+ define_method("test_1_9_valid_#{xmpl}") do
294
+ pt19=parser(xmpl,'(eval)').parse
75
295
  assert_nil pt19.errors
296
+ assert_unparses_to pt19,xmpl
297
+ end
298
+ }
299
+
300
+ def test_ruby19_invalid
301
+ RUBY_1_9_INVALID.each{|xmpl|
302
+ begin
303
+ pt19=parser(xmpl,'(eval)').parse
304
+ rescue Exception
305
+ assert true
306
+ next
307
+ end
308
+ warn "1.9error expected, but not seen in '#{xmpl}'" unless pt19.errors
76
309
  }
77
310
  end
78
311
 
79
312
  def test_ruby19_patterns
80
313
  RUBY_1_9_PATTERNS.each_pair{|code,pattern|
81
- pt=RedParse.new(code,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
82
- assert_match pattern, pt
314
+ pt=parser(code,'(eval)').parse
315
+ assert pattern === pt, code
316
+ assert_unparses_to pt,code
83
317
  }
84
318
  end
85
319
 
86
-
87
-
88
-
89
- include Ruby1_9OneLiners
90
-
91
320
  def count_methods(tree)
92
321
  count=0
93
- tree.walk{|node|
322
+ tree.walk{|parent,i,subi,node|
94
323
  case node
95
324
  when CallSiteNode, MethodNode; count+=1
96
325
  end
326
+ true
97
327
  }
98
328
  return count
99
329
  end
100
330
 
101
- def test_1_9
102
- EXPECT_NO_METHODS.each{|snippet|
103
- tree=RedParse.new(snippet,"-e").parse
104
- count=count_methods(tree)
105
- assert_equal count,0
331
+ def count_sequences(tree)
332
+ count=0
333
+ tree.walk{|parent,i,subi,node|
334
+ case node
335
+ when SequenceNode; count+=1
336
+ end unless CallSiteNode===parent and 5===i and nil===subi #skip block slot in Call and KWCall
337
+ true
106
338
  }
339
+ return count
340
+ end
107
341
 
108
- EXPECT_1_METHOD.each{|snippet|
109
- tree=RedParse.new(snippet,"-e").parse
110
- count=count_methods(tree)
111
- assert_equal count,1
342
+ def count_multiassigns(tree)
343
+ count=0
344
+ tree.walk{|parent,i,subi,node|
345
+ case node
346
+ when MultiAssign; count+=1
347
+ end
348
+ true
112
349
  }
350
+ return count
113
351
  end
352
+
353
+ EXPECT_NO_METHODS.each{|snippet|
354
+ define_method "test_1_9_no_methods_in_#{snippet}" do
355
+ tree=parser(snippet,"-e")
356
+ begin
357
+ tree=tree.parse
358
+ rescue Exception=>e
359
+ raise e,e.message+"during parsing of #{snippet}\n",e.backtrace
360
+ end
361
+ count=count_methods(tree)
362
+ assert_equal 0,count,snippet
363
+ end
364
+ }
365
+
366
+ EXPECT_1_METHOD.each{|snippet|
367
+ define_method "test_1_9_one_method_in_#{snippet}" do
368
+ tree=parser(snippet,"-e")
369
+ begin
370
+ tree=tree.parse
371
+ rescue Exception=>e
372
+ raise e,e.message+"during parsing of #{snippet}\n",e.backtrace
373
+ end
374
+ count=count_methods(tree)
375
+ assert_equal 1,count,snippet
376
+ end
377
+ }
378
+
379
+ EXPECT_2_METHODS.each{|snippet|
380
+ define_method "test_1_9_two_methods_in_#{snippet}" do
381
+ tree=parser(snippet,"-e")
382
+ begin
383
+ tree=tree.parse
384
+ rescue Exception=>e
385
+ raise e,e.message+"during parsing of #{snippet}\n",e.backtrace
386
+ end
387
+ count=count_methods(tree)
388
+ assert_equal 2,count,snippet
389
+ end
390
+ }
391
+
392
+ EXPECT_NO_SEQUENCES.each{|snippet|
393
+ define_method "test_1_9_no_sequence_in_#{snippet}" do
394
+ tree=parser(snippet,"-e")
395
+ begin
396
+ tree=tree.parse
397
+ rescue Exception=>e
398
+ raise e,e.message+"during parsing of #{snippet}\n",e.backtrace
399
+ end
400
+ count=count_sequences(tree)
401
+ assert_equal 0,count,snippet
402
+ end
403
+ }
404
+ EXPECT_NO_MULTIASSIGNS.each{|snippet|
405
+ define_method "test_1_9_no_multiassign_in_#{snippet}" do
406
+ tree=parser(snippet,"-e")
407
+ begin
408
+ tree=tree.parse
409
+ rescue Exception=>e
410
+ raise e,e.message+"during parsing of #{snippet}\n",e.backtrace
411
+ end
412
+ return if AssignNode===tree
413
+ count=count_multiassigns(tree)
414
+ assert_equal 0,count,snippet
415
+ end
416
+ }
114
417
  end