ripper_ruby_parser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
1
+ require 'ripper_ruby_parser/sexp_handlers/helper_methods'
2
+
3
+ require 'ripper_ruby_parser/sexp_handlers/arguments'
4
+ require 'ripper_ruby_parser/sexp_handlers/arrays'
5
+ require 'ripper_ruby_parser/sexp_handlers/assignment'
6
+ require 'ripper_ruby_parser/sexp_handlers/blocks'
7
+ require 'ripper_ruby_parser/sexp_handlers/conditionals'
8
+ require 'ripper_ruby_parser/sexp_handlers/hashes'
9
+ require 'ripper_ruby_parser/sexp_handlers/literals'
10
+ require 'ripper_ruby_parser/sexp_handlers/loops'
11
+ require 'ripper_ruby_parser/sexp_handlers/method_calls'
12
+ require 'ripper_ruby_parser/sexp_handlers/methods'
13
+ require 'ripper_ruby_parser/sexp_handlers/operators'
14
+
15
+ module RipperRubyParser
16
+ module SexpHandlers
17
+ def self.included base
18
+ base.class_eval do
19
+ include HelperMethods
20
+
21
+ include Arguments
22
+ include Arrays
23
+ include Assignment
24
+ include Blocks
25
+ include Conditionals
26
+ include Hashes
27
+ include Literals
28
+ include Loops
29
+ include MethodCalls
30
+ include Methods
31
+ include Operators
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,150 @@
1
+ require 'sexp_processor'
2
+ require 'ripper_ruby_parser/sexp_handlers'
3
+ require 'ripper_ruby_parser/sexp_ext'
4
+
5
+ module RipperRubyParser
6
+ # Processes the sexp created by Ripper to what RubyParser would produce.
7
+ class SexpProcessor < ::SexpProcessor
8
+ def initialize
9
+ super
10
+ # TODO: Find these automatically
11
+ @processors[:@int] = :process_at_int
12
+ @processors[:@const] = :process_at_const
13
+ @processors[:@ident] = :process_at_ident
14
+ @processors[:@gvar] = :process_at_gvar
15
+ @processors[:@ivar] = :process_at_ivar
16
+ @processors[:@kw] = :process_at_kw
17
+ @processors[:@backref] = :process_at_backref
18
+
19
+ @processors[:@tstring_content] = :process_at_tstring_content
20
+ end
21
+
22
+ def process exp
23
+ return nil if exp.nil?
24
+ exp.fix_empty_type
25
+
26
+ super
27
+ end
28
+
29
+ include SexpHandlers
30
+
31
+ def process_program exp
32
+ _, content = exp.shift 2
33
+
34
+ if content.length == 1
35
+ process(content.first)
36
+ else
37
+ statements = content.map { |sub_exp| process(sub_exp) }
38
+ s(:block, *statements)
39
+ end
40
+ end
41
+
42
+ def process_module exp
43
+ _, const_ref, body = exp.shift 3
44
+ const = const_node_to_symbol const_ref[1]
45
+ s(:module, const, class_or_module_body(body))
46
+ end
47
+
48
+ def process_class exp
49
+ _, const_ref, parent, body = exp.shift 4
50
+ const = const_node_to_symbol const_ref[1]
51
+ parent = process(parent)
52
+ s(:class, const, parent, class_or_module_body(body))
53
+ end
54
+
55
+ def process_bodystmt exp
56
+ _, body, _, _, _ = exp.shift 5
57
+ body = body.
58
+ map { |sub_exp| process(sub_exp) }.
59
+ reject { |sub_exp| sub_exp.sexp_type == :void_stmt }
60
+ s(:scope, s(:block, *body))
61
+ end
62
+
63
+ def process_var_ref exp
64
+ _, contents = exp.shift 2
65
+ process(contents)
66
+ end
67
+
68
+ def process_var_field exp
69
+ _, contents = exp.shift 2
70
+ process(contents)
71
+ end
72
+
73
+ def process_const_path_ref exp
74
+ _, left, right = exp.shift 3
75
+ s(:colon2, process(left), const_node_to_symbol(right))
76
+ end
77
+
78
+ def process_top_const_ref exp
79
+ _, ref = exp.shift 2
80
+ s(:colon3, const_node_to_symbol(ref))
81
+ end
82
+
83
+ def process_paren exp
84
+ _, body = exp.shift 2
85
+ process(body)
86
+ end
87
+
88
+ def process_at_int exp
89
+ _, val, _ = exp.shift 3
90
+ s(:lit, val.to_i)
91
+ end
92
+
93
+ # symbol-like sexps
94
+ def process_at_const exp
95
+ s(:const, extract_node_symbol(exp))
96
+ end
97
+
98
+ def process_at_gvar exp
99
+ s(:gvar, extract_node_symbol(exp))
100
+ end
101
+
102
+ def process_at_ivar exp
103
+ s(:ivar, extract_node_symbol(exp))
104
+ end
105
+
106
+ def process_at_ident exp
107
+ s(:lvar, extract_node_symbol(exp))
108
+ end
109
+
110
+ def process_at_kw exp
111
+ sym = extract_node_symbol(exp)
112
+ if sym == :__FILE__
113
+ s(:str, "(string)")
114
+ else
115
+ s(sym)
116
+ end
117
+ end
118
+
119
+ def process_at_backref exp
120
+ _, str, _ = exp.shift 3
121
+ s(:nth_ref, str[1..-1].to_i)
122
+ end
123
+
124
+ private
125
+
126
+ def const_node_to_symbol exp
127
+ assert_type exp, :@const
128
+ _, ident, _ = exp.shift 3
129
+
130
+ ident.to_sym
131
+ end
132
+
133
+ def extract_node_symbol exp
134
+ _, ident, _ = exp.shift 3
135
+
136
+ ident.to_sym
137
+ end
138
+
139
+ def class_or_module_body exp
140
+ scope = process exp
141
+ block = scope[1]
142
+ block.shift
143
+ if block.length <= 1
144
+ s(:scope, *block)
145
+ else
146
+ s(:scope, s(:block, *block))
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,3 @@
1
+ module RipperRubyParser
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'ripper_ruby_parser/version'
2
+ require 'ripper_ruby_parser/parser'
3
+
4
+ module RipperRubyParser
5
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+ require 'ruby_parser'
3
+
4
+ describe "Using RipperRubyParser and RubyParser" do
5
+ let :newparser do
6
+ RipperRubyParser::Parser.new
7
+ end
8
+
9
+ let :oldparser do
10
+ RubyParser.new
11
+ end
12
+
13
+ describe "for a simple well known program" do
14
+ let :program do
15
+ "puts 'Hello World'"
16
+ end
17
+
18
+ it "gives the same result" do
19
+ original = oldparser.parse program
20
+ imitation = newparser.parse program
21
+
22
+ imitation.must_equal original
23
+ end
24
+ end
25
+
26
+ describe "for a more complex program" do
27
+ let :program do
28
+ <<-END
29
+ module Quux
30
+ class Foo
31
+ def bar
32
+ baz = 3
33
+ qux baz
34
+ end
35
+ def qux it
36
+ if it == 3
37
+ [1,2,3].map {|i| 2*i}
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ Quux::Foo.new.bar
44
+ END
45
+ end
46
+
47
+ it "gives the same result" do
48
+ original = oldparser.parse program
49
+ imitation = newparser.parse program
50
+
51
+ imitation.must_equal original
52
+ end
53
+ end
54
+
55
+ end
56
+
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+ require 'ruby_parser'
3
+
4
+ describe "Using RipperRubyParser and RubyParser" do
5
+ let :newparser do
6
+ RipperRubyParser::Parser.new
7
+ end
8
+
9
+ let :oldparser do
10
+ RubyParser.new
11
+ end
12
+
13
+ Dir.glob("lib/**/*.rb").each do |file|
14
+ describe "for #{file}" do
15
+ let :program do
16
+ File.read file
17
+ end
18
+
19
+ it "gives the same result" do
20
+ original = oldparser.parse program
21
+ imitation = newparser.parse program
22
+
23
+ formatted(imitation).must_equal formatted(original)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+
@@ -0,0 +1,33 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+ require 'ruby_parser'
3
+
4
+ describe "Using RipperRubyParser and RubyParser" do
5
+ let :newparser do
6
+ RipperRubyParser::Parser.new
7
+ end
8
+
9
+ let :oldparser do
10
+ RubyParser.new
11
+ end
12
+
13
+ Dir.glob("test/**/*.rb").each do |file|
14
+ describe "for #{file}" do
15
+ let :program do
16
+ File.read file
17
+ end
18
+
19
+ it "gives the same result" do
20
+ # Clone string because ruby_parser destroys it when there's a heredoc
21
+ # inside.
22
+ copy = program.clone
23
+ original = oldparser.parse program
24
+ imitation = newparser.parse copy
25
+
26
+ formatted(imitation).must_equal formatted(original)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+
@@ -0,0 +1,12 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+ require 'minitest/spec'
4
+ require 'minitest/autorun'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+
8
+ require 'ripper_ruby_parser'
9
+
10
+ def formatted exp
11
+ exp.to_s.gsub /\), /, "),\n"
12
+ end