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