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
@@ -1,3 +1,20 @@
1
+ =begin
2
+ redparse - a ruby parser written in ruby
3
+ Copyright (C) 2012, 2016 Caleb Clausen
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
1
18
  require 'tempfile'
2
19
  #require 'yaml'
3
20
  #require 'marshal'
@@ -57,6 +74,7 @@ class ParseTreeServer
57
74
  end
58
75
 
59
76
  def main
77
+ Process.setsid
60
78
  si=STDIN
61
79
  so=STDOUT
62
80
  @out=so; @in=si
@@ -78,14 +96,14 @@ class ParseTreeServer
78
96
  tree=
79
97
  begin
80
98
  instance.parse_tree_for_string(str) #tree
81
- rescue Exception=>e;
99
+ rescue Exception=>e
82
100
  tree=e
83
101
  end
84
102
  put tree
85
103
 
86
104
  open(STDERR.path){|f|
87
105
  f.pos=pos
88
- put warnings=f.read.split #warnings
106
+ put warnings=f.read.split("\n") #warnings
89
107
  }
90
108
  end
91
109
  rescue Exception=>e; put e; raise
@@ -1,6 +1,6 @@
1
1
  =begin
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,3 +1,20 @@
1
+ =begin
2
+ redparse - a ruby parser written in ruby
3
+ Copyright (C) 2012, 2016 Caleb Clausen
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
1
18
  class RedParse
2
19
  def self.remove_silly_begins(pt)
3
20
  pt.each_with_index{|x,i|
@@ -10,34 +27,3 @@ class RedParse
10
27
  }
11
28
  end
12
29
  end
13
-
14
- __END__
15
- begin require 'rubygems'
16
- rescue LoadError; #do nothing
17
- end
18
-
19
- have_graphwalk=true
20
- begin require 'ron/graphedge'
21
- rescue LoadError;
22
- warn 'Ron::GraphWalk not found; some tests will be too strict'
23
- have_graphwalk=false
24
- end
25
-
26
- unless have_graphwalk
27
- class RedParse
28
- def self.remove_silly_begins(pt) pt end
29
- end
30
- else
31
- class RedParse
32
- def self.remove_silly_begins(pt)
33
- munger=proc{|cntr,o,i,ty,useit|
34
- if Array===o and o.size==2 and o.first==:begin
35
- useit[0]=true
36
- Ron::GraphWalk.graphcopy(o.last,&munger)
37
- end
38
- }
39
- Ron::GraphWalk.graphcopy(pt,&munger)
40
- end
41
- end
42
- end
43
-
@@ -1,6 +1,6 @@
1
1
  =begin
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 program is free software: you can redistribute it and/or modify
6
6
  it under the terms of the GNU Lesser General Public License as published by
@@ -0,0 +1,30 @@
1
+ =begin
2
+ redparse - a ruby parser written in ruby
3
+ Copyright (C) 2012, 2016 Caleb Clausen
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
18
+ require 'redparse'
19
+
20
+ class ParseTree
21
+ def initialize
22
+
23
+ end
24
+
25
+ def parse_tree_for_string(source,
26
+ filename = '(string)', line = 1, verbose = true)
27
+ @parser=RedParse.new(source,filename,line)
28
+ @parser.parse.to_parsetree
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ =begin
2
+ redparse - a ruby parser written in ruby
3
+ Copyright (C) 2012, 2016 Caleb Clausen
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
18
+ require 'redparse/ripper'
19
+ class Ripper<RedParse::Ripper; end
20
+
@@ -0,0 +1,28 @@
1
+ =begin
2
+ redparse - a ruby parser written in ruby
3
+ Copyright (C) 2012, 2016 Caleb Clausen
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
18
+ class RubyParser
19
+ def initialize
20
+
21
+ end
22
+
23
+ def parse code,file="(eval)",line=1
24
+ huh #should translate to unified format here too
25
+ @parser=RedParse.new(code,file,line)
26
+ @parser.parse.to_parsetree
27
+ end
28
+ end
@@ -0,0 +1,393 @@
1
+ =begin
2
+ redparse - a ruby parser written in ruby
3
+ Copyright (C) 2012, 2016 Caleb Clausen
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ =end
18
+ require 'redparse'
19
+ class RedParse
20
+ class Ripper
21
+ def initialize(text,file="(eval)",line=1,options={})
22
+ options[:rubyversion]||=1.9
23
+ @lineno=@column=0 #hack, for now. fix this later
24
+ @parser=RedParse.new(text,file,line,options)
25
+ end
26
+ attr_accessor :lineno,:column,:parser
27
+
28
+ alias [] instance_variable_get
29
+ alias []= instance_variable_set
30
+
31
+ def parse options={}
32
+ @quirks=options[:quirks]
33
+ tree=@parser
34
+ tree=tree.parse if tree.respond_to? :parse
35
+ on_program tree.rip(self)
36
+ end
37
+
38
+ def quirks?; @quirks end
39
+
40
+ def self.instrumentSexpBuilder k
41
+ events=k.instance_methods.grep(/\Aon_/)
42
+ events.map!{|e| <<-"endcode" }
43
+ alias noinst_#{e} #{e}
44
+ def #{e}(*a)
45
+ @record<<a.dup.unshift(:#{e})
46
+ noinst_#{e}(*a)
47
+ end
48
+ endcode
49
+ events<<<<-"endcode"
50
+ alias noinst_parse parse
51
+ def parse *a
52
+ @record=[]
53
+ result=[@record,(noinst_parse *a)]
54
+ @record=nil
55
+ return result
56
+ end
57
+ endcode
58
+ k.module_eval events.join
59
+ end
60
+ end
61
+
62
+ class LiteralNode
63
+ def rip p
64
+ if Symbol===val
65
+ #p.pos huh
66
+ p.on_symbol_literal \
67
+ p.on_symbol \
68
+ p.on_ident(val.to_s)
69
+ elsif Integer===val
70
+ p.on_int(val.to_s)
71
+ else fail
72
+ end
73
+ end
74
+ end
75
+
76
+ class SequenceNode
77
+ def rip p
78
+ stmts_rip self,p
79
+ end
80
+ end
81
+
82
+ class CallNode
83
+ def rip p
84
+ receiver=receiver()
85
+ name=p.on_ident(name().dup)
86
+ return p.on_var_ref(name) if p.quirks? and !receiver and !params and !block and @not_real_parens
87
+ if receiver
88
+ result=[@not_real_parens ? :on_command_call : :on_call, receiver.rip(p), :".", name]
89
+ else
90
+ result=[@not_real_parens ? :on_command : :on_fcall, name]
91
+ end
92
+
93
+ result=p.send(*result)
94
+ result=p.on_method_add_arg(
95
+ result,
96
+ p.on_arg_paren(
97
+ p.on_args_add_block(
98
+ args_rip(params,p),
99
+ false
100
+ ))) if params
101
+
102
+ result=p.on_method_add_block(result,p.on_brace_block(nil,block.rip(p))) if block
103
+
104
+ return result
105
+ end
106
+ end
107
+
108
+ class OpNode
109
+ def rip p
110
+ p.on_binary(left.rip(p), op.to_sym, right.rip(p))
111
+ end
112
+ end
113
+ class AndNode
114
+ def rip p
115
+ p.on_binary(left.rip(p), op.to_sym, right.rip(p))
116
+ end
117
+ end
118
+ class OrNode
119
+ def rip p
120
+ p.on_binary(left.rip(p), op.to_sym, right.rip(p))
121
+ end
122
+ end
123
+
124
+ class UnOpNode
125
+ def rip p
126
+ p.on_unary(op.to_sym, val.rip(p))
127
+ end
128
+ end
129
+
130
+ class RescueOpNode
131
+ def rip p
132
+ p.send( "on_#{op}_mod", rescue_with.rip(p), body.rip(p) )
133
+ end
134
+ end
135
+
136
+ class WhileOpNode
137
+ def rip p
138
+ if BeginNode===consequent
139
+ if @quirks
140
+ #this is WRONG!!!, but it's how ripper works... urk
141
+ #if expression modified by a while operator is a begin node,
142
+ #ruby always executes the loop at least once,
143
+ #and doesn't check the condition til after the first execution.
144
+ #Ripper reverses the order of condition and consequent to signal
145
+ #an execute-at-least-once loop. But, that's not good enough.
146
+ #because 'begin a end while b' now parses the same as 'b while begin a end'
147
+ p.on_while_mod( condition.rip(p), consequent.rip(p) )
148
+ else
149
+ p.on_while_mod( consequent.rip(p), condition.rip(p), :loop_first )
150
+ end
151
+ else
152
+ p.on_while_mod( consequent.rip(p), condition.rip(p) )
153
+ end
154
+ end
155
+ end
156
+
157
+ class UntilOpNode
158
+ def rip p
159
+ if BeginNode===consequent
160
+ if @quirks
161
+ #this is WRONG!!!, but it's how ripper works... urk
162
+ #if expression modified by a until operator is a begin node,
163
+ #ruby always executes the loop at least once,
164
+ #and doesn't check the condition til after the first execution.
165
+ #Ripper reverses the order of condition and consequent to signal
166
+ #an execute-at-least-once loop. But, that's not good enough.
167
+ #because 'begin a end until b' now parses the same as 'b until begin a end'
168
+ p.on_until_mod( condition.rip(p), consequent.rip(p) )
169
+ else
170
+ p.on_until_mod( consequent.rip(p), condition.rip(p), :loop_first )
171
+ end
172
+ else
173
+ p.on_until_mod( consequent.rip(p), condition.rip(p) )
174
+ end
175
+ end
176
+ end
177
+
178
+ class IfOpNode
179
+ def rip p
180
+ p.on_if_mod( condition.rip(p), consequent.rip(p) )
181
+ end
182
+ end
183
+
184
+ class UnlessOpNode
185
+ def rip p
186
+ p.on_unless_mod( condition.rip(p), consequent.rip(p) )
187
+ end
188
+ end
189
+
190
+ class VarNode
191
+ def rip p
192
+ p.on_var_ref(
193
+ case name[0]
194
+ when ?$; p.on_gvar(name)
195
+ when ?@; name[1]==?@ ? p.on_cvar(name) : p.on_ivar(name)
196
+ when ?A..?Z; p.on_const(name)
197
+ else p.on_ident(name)
198
+ end
199
+ )
200
+ end
201
+ end
202
+
203
+ class ConstantNode
204
+ def rip p
205
+ if first
206
+ start=p.on_var_ref \
207
+ p.on_const(first)
208
+ start_i=1
209
+ else
210
+ start=p.on_top_const_ref \
211
+ p.on_const(self[1])
212
+ start_i=2
213
+ end
214
+ (start_i...size).inject(start){|sum,i|
215
+ p.on_const_path_ref(sum,p.on_const(self[i]))
216
+ }
217
+ end
218
+ end
219
+
220
+ class StringNode
221
+ def rip p
222
+ list=self.dup
223
+ list.shift if String===list.first and list.first.empty?
224
+ p.on_string_literal \
225
+ list.inject(p.on_string_content){|sum,chunk|
226
+ p.on_string_add sum,
227
+ if String===chunk
228
+ p.on_tstring_content chunk
229
+ else
230
+ p.on_string_embexpr chunk.rip(p)
231
+ end
232
+ }
233
+ end
234
+ end
235
+
236
+ class Node
237
+ def rip_and_rescues p
238
+ unless rescues.empty?
239
+ r=rescues.map{|resc| resc.rip(p)}
240
+ r.each_with_index{|x,i| x<<r[i+1] unless i+1==r.size }
241
+ r=r.first
242
+ end
243
+ p.on_bodystmt(
244
+ force_stmt_list_rip(body,p),
245
+ r,
246
+ else_&&else_.rip(p),
247
+ ensure_&&p.on_ensure(force_stmt_list_rip(ensure_,p))
248
+ )
249
+ end
250
+ def rip_explode! init,receiver=self,&block
251
+ receiver.inject(init,&block)
252
+ end
253
+ def stmts_rip list,p
254
+ list.inject(p.on_stmts_new){|sum,expr| p.on_stmts_add(sum,expr.rip(p)) }
255
+ end
256
+ def force_stmt_list_rip expr,p
257
+ if SequenceNode===expr
258
+ expr.rip(p)
259
+ else
260
+ stmts_rip [expr],p
261
+ end
262
+ end
263
+ def args_rip list,p
264
+ list.inject(p.on_args_new){|sum,param|
265
+ p.on_args_add(sum,param.rip(p))
266
+ }
267
+ end
268
+ end
269
+
270
+ class ClassNode
271
+ def rip p
272
+ p.on_class( name.rip(p), parent&&parent.rip(p), rip_and_rescues(p) )
273
+ end
274
+ end
275
+
276
+ class ModuleNode
277
+ def rip p
278
+ p.on_module( name.rip(p), rip_and_rescues(p) )
279
+ end
280
+ end
281
+
282
+ class MetaClassNode
283
+ def rip p
284
+ p.on_sclass( object.rip(p), rip_and_rescues(p) )
285
+ end
286
+ end
287
+
288
+ class MethodNode
289
+ def get_while params,should_be
290
+ param=nil
291
+ result=[]
292
+ result<<yield( param )while should_be===params.first and param=params.shift
293
+ ensure
294
+ return result unless result.empty?
295
+ end
296
+
297
+ def rip p
298
+ params=args ? args.dup : []
299
+ params2=[]
300
+ #param=nil
301
+
302
+ params2.push get_while(params,VarNode){|param| p.on_ident param.name}
303
+ params2.push get_while(params,AssignNode){|param| [p.on_ident(param.left.name), param.right.rip(p)]}
304
+ get_while(params,UnaryStarNode){|param| params2.push p.on_rest_param p.on_ident param.val.name; break }
305
+ params2.push get_while(params,VarNode){|param| p.on_ident param.name}
306
+ get_while(params,UnaryAmpNode){|param| params2.push p.on_blockarg p.on_ident param.val.name; break }
307
+
308
+ params=p.on_params( *params2 )
309
+ params=p.on_paren( params ) if has_parens?
310
+
311
+ result=[p.on_ident(name), params, rip_and_rescues(p)]
312
+ result.unshift receiver.rip(p), p.on_period(".") if receiver
313
+ p.on_def( *result )
314
+ end
315
+ end
316
+
317
+ class BeginNode
318
+ def rip p
319
+ p.on_begin rip_and_rescues(p)
320
+ end
321
+ end
322
+
323
+ class RescueNode
324
+ def rip p
325
+ p.on_rescue(
326
+ exceptions.empty??nil:exceptions.map{|ex| ex.rip(p)},
327
+ name&&p.on_var_field(p.on_ident(name.name)),
328
+ force_stmt_list_rip(action,p)
329
+ )
330
+ end
331
+ end
332
+
333
+ class IfNode
334
+ def rip p
335
+ elses=p.on_else(force_stmt_list_rip(otherwise,p)) if otherwise
336
+ elsifs.reverse_each{|ei|
337
+ elses=p.on_elsif(
338
+ ei.condition.rip(p),
339
+ force_stmt_list_rip(ei.consequent,p),
340
+ elses
341
+ )
342
+ }
343
+ p.on_if(
344
+ condition.rip(p),
345
+ force_stmt_list_rip(consequent,p),
346
+ elses
347
+ )
348
+ end
349
+ end
350
+
351
+ class LoopNode
352
+ def rip p
353
+ event= @reverse ? :on_until : :on_while
354
+ p.send(event, condition.rip(p), force_stmt_list_rip(body,p))
355
+ end
356
+ end
357
+
358
+ class ParenedNode
359
+ def rip p
360
+ list= SequenceNode===val ? val : [val]
361
+ p.on_paren stmts_rip list,p
362
+ end
363
+ end
364
+
365
+ class TernaryNode
366
+ def rip p
367
+ p.on_ifop condition.rip(p), consequent.rip(p), otherwise.rip(p)
368
+ end
369
+ end
370
+
371
+ class RangeNode
372
+ def rip p
373
+ dots= exclude_end? ? :on_dot3 : :on_dot2
374
+ p.send dots, left.rip(p), right.rip(p)
375
+ end
376
+ end
377
+
378
+
379
+ class ArrayLiteralNode
380
+ def rip p
381
+ p.on_array(args_rip(self,p))
382
+ end
383
+ end
384
+
385
+ class HashLiteralNode
386
+ def rip p
387
+ list=[]
388
+ (0...size).step(2){|i| list.push p.on_assoc_new(self[i].rip(p),self[i+1].rip(p)) }
389
+ p.on_hash((p.on_assoclist_from_args(list) unless empty?))
390
+ end
391
+ end
392
+
393
+ end