redparse 0.8.4 → 1.0.0

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