ripper_ruby_parser 0.0.1
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.
- data/README.rdoc +76 -0
- data/Rakefile +24 -0
- data/lib/ripper_ruby_parser/parser.rb +18 -0
- data/lib/ripper_ruby_parser/sexp_ext.rb +14 -0
- data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +23 -0
- data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +15 -0
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +80 -0
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +49 -0
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +64 -0
- data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +27 -0
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +49 -0
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +83 -0
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +11 -0
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +47 -0
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +38 -0
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +41 -0
- data/lib/ripper_ruby_parser/sexp_handlers.rb +35 -0
- data/lib/ripper_ruby_parser/sexp_processor.rb +150 -0
- data/lib/ripper_ruby_parser/version.rb +3 -0
- data/lib/ripper_ruby_parser.rb +5 -0
- data/test/end_to_end/comparison_test.rb +56 -0
- data/test/end_to_end/lib_comparison_test.rb +29 -0
- data/test/end_to_end/test_comparison_test.rb +33 -0
- data/test/test_helper.rb +12 -0
- data/test/unit/parser_test.rb +623 -0
- data/test/unit/sexp_processor_test.rb +309 -0
- data/test/unit/version_test.rb +5 -0
- metadata +137 -0
data/README.rdoc
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
= RipperRubyParser
|
2
|
+
|
3
|
+
by Matijs van Zuijlen
|
4
|
+
|
5
|
+
http://www.github.com/mvz/ripper_ruby_parser
|
6
|
+
|
7
|
+
== Description
|
8
|
+
|
9
|
+
Parse with Ripper, produce sexps that are compatible with RubyParser.
|
10
|
+
|
11
|
+
== Features/Notes
|
12
|
+
|
13
|
+
* Drop-in replacement for RubyParser.
|
14
|
+
* Should handle 1.9 syntax gracefully.
|
15
|
+
* Only tested with MRI 1.9.3. Definitely does not work with the ripper gem for
|
16
|
+
MRI 1.8.
|
17
|
+
* Many edge cases are surely not yet taken care of (but hey, it's version
|
18
|
+
0.0.1).
|
19
|
+
|
20
|
+
== Install
|
21
|
+
|
22
|
+
* gem install ripper_ruby_parser
|
23
|
+
|
24
|
+
== Synopsis
|
25
|
+
|
26
|
+
Basic usage:
|
27
|
+
|
28
|
+
require 'ripper_ruby_parser'
|
29
|
+
|
30
|
+
parser = RipperRubyParser::Parser.new
|
31
|
+
result = parser.parse "puts 'Hello World'"
|
32
|
+
p result
|
33
|
+
# => s(:call, nil, :puts, s(:arglist, s(:str, "Hello World!")))
|
34
|
+
|
35
|
+
== Requirements
|
36
|
+
|
37
|
+
* Ruby 1.9.3. It may work with lower 1.9 versions. Let me know if it does.
|
38
|
+
* sexp_processor
|
39
|
+
|
40
|
+
== Hacking and contributing
|
41
|
+
|
42
|
+
If you want to send pull requests or patches, please:
|
43
|
+
|
44
|
+
* Make sure `rake test` runs without reporting any failures. If your code
|
45
|
+
breaks existing stuff, it won't get merged in.
|
46
|
+
* Add tests for your feature. Otherwise, I can't see if it works or if I
|
47
|
+
break it later.
|
48
|
+
* Make sure latest master merges cleanly with your branch. Things might
|
49
|
+
have moved around since you forked.
|
50
|
+
* Try not to include changes that are irrelevant to your feature in the
|
51
|
+
same commit.
|
52
|
+
|
53
|
+
== License
|
54
|
+
|
55
|
+
(The MIT License)
|
56
|
+
|
57
|
+
Copyright (c) 2012 Matijs van Zuijlen
|
58
|
+
|
59
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
60
|
+
a copy of this software and associated documentation files (the
|
61
|
+
'Software'), to deal in the Software without restriction, including
|
62
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
63
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
64
|
+
permit persons to whom the Software is furnished to do so, subject to
|
65
|
+
the following conditions:
|
66
|
+
|
67
|
+
The above copyright notice and this permission notice shall be
|
68
|
+
included in all copies or substantial portions of the Software.
|
69
|
+
|
70
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
71
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
72
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
73
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
74
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
75
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
76
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
namespace :test do
|
4
|
+
|
5
|
+
Rake::TestTask.new(:unit) do |t|
|
6
|
+
t.libs = ['lib']
|
7
|
+
t.test_files = FileList['test/unit/*_test.rb']
|
8
|
+
t.ruby_opts += ["-w"]
|
9
|
+
end
|
10
|
+
|
11
|
+
Rake::TestTask.new(:end_to_end) do |t|
|
12
|
+
t.libs = ['lib']
|
13
|
+
t.test_files = FileList['test/end_to_end/*_test.rb']
|
14
|
+
t.ruby_opts += ["-w"]
|
15
|
+
end
|
16
|
+
|
17
|
+
task :run => [:unit, :end_to_end]
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Alias to test:run'
|
22
|
+
task :test => 'test:run'
|
23
|
+
|
24
|
+
task :default => :test
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'ripper'
|
2
|
+
require 'ripper_ruby_parser/sexp_processor'
|
3
|
+
|
4
|
+
module RipperRubyParser
|
5
|
+
# Main parser class. Brings together Ripper and our
|
6
|
+
# RipperRubyParser::SexpProcessor.
|
7
|
+
class Parser
|
8
|
+
def initialize processor=SexpProcessor.new
|
9
|
+
@processor = processor
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse source
|
13
|
+
exp = Sexp.from_array(Ripper.sexp source)
|
14
|
+
@processor.process exp
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Arguments
|
4
|
+
def process_args_add_block exp
|
5
|
+
_, content, _ = exp.shift 3
|
6
|
+
s(:arglist, *handle_list_with_optional_splat(content))
|
7
|
+
end
|
8
|
+
|
9
|
+
def process_args_add_star exp
|
10
|
+
generic_add_star exp
|
11
|
+
end
|
12
|
+
|
13
|
+
def process_arg_paren exp
|
14
|
+
_, args = exp.shift 2
|
15
|
+
args = s() if args.nil?
|
16
|
+
unless args.first.is_a? Symbol
|
17
|
+
args.unshift :arglist
|
18
|
+
end
|
19
|
+
process(args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Arrays
|
4
|
+
def process_array exp
|
5
|
+
_, elems = exp.shift 2
|
6
|
+
s(:array, *handle_list_with_optional_splat(elems))
|
7
|
+
end
|
8
|
+
|
9
|
+
def process_aref exp
|
10
|
+
_, item, idx = exp.shift 3
|
11
|
+
s(:call, process(item), :[], process(idx))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Assignment
|
4
|
+
def process_assign exp
|
5
|
+
_, lvalue, value = exp.shift 3
|
6
|
+
|
7
|
+
lvalue = process(lvalue)
|
8
|
+
value = process(value)
|
9
|
+
|
10
|
+
create_assignment_sub_type lvalue, value
|
11
|
+
end
|
12
|
+
|
13
|
+
def process_massign exp
|
14
|
+
_, left, right = exp.shift 3
|
15
|
+
|
16
|
+
left = handle_list_with_optional_splat left
|
17
|
+
|
18
|
+
left.each do |item|
|
19
|
+
case item.sexp_type
|
20
|
+
when :splat
|
21
|
+
item[1][0] = :lasgn
|
22
|
+
else
|
23
|
+
item[0] = :lasgn
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
right = process(right)
|
28
|
+
|
29
|
+
unless right.sexp_type == :array
|
30
|
+
right = s(:to_ary, right)
|
31
|
+
end
|
32
|
+
|
33
|
+
s(:masgn, s(:array, *left), right)
|
34
|
+
end
|
35
|
+
|
36
|
+
def process_mrhs_new_from_args exp
|
37
|
+
_, inner, last = exp.shift 3
|
38
|
+
inner.map! {|item| process(item)}
|
39
|
+
inner.push process(last)
|
40
|
+
s(:array, *inner)
|
41
|
+
end
|
42
|
+
|
43
|
+
def process_mlhs_add_star exp
|
44
|
+
generic_add_star exp
|
45
|
+
end
|
46
|
+
|
47
|
+
def process_opassign exp
|
48
|
+
_, lvalue, operator, value = exp.shift 4
|
49
|
+
|
50
|
+
lvalue = process(lvalue)
|
51
|
+
value = process(value)
|
52
|
+
operator = operator[1].gsub(/=/, '').to_sym
|
53
|
+
operator_call = s(:call, lvalue, operator, s(:arglist, value))
|
54
|
+
|
55
|
+
case lvalue.sexp_type
|
56
|
+
when :ivar
|
57
|
+
s(:iasgn, lvalue[1], operator_call)
|
58
|
+
when :aref_field
|
59
|
+
s(:op_asgn1, lvalue[1], s(:arglist, lvalue[2][1]), operator, value)
|
60
|
+
else
|
61
|
+
s(:lasgn, lvalue[1], operator_call)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_assignment_sub_type lvalue, value
|
66
|
+
case lvalue.sexp_type
|
67
|
+
when :ivar
|
68
|
+
s(:iasgn, lvalue[1], value)
|
69
|
+
when :aref_field
|
70
|
+
s(:attrasgn, lvalue[1], :[]=, s(:arglist, lvalue[2][1], value))
|
71
|
+
when :const
|
72
|
+
s(:cdecl, lvalue[1], value)
|
73
|
+
else
|
74
|
+
s(:lasgn, lvalue[1], value)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Blocks
|
4
|
+
def process_method_add_block exp
|
5
|
+
_, call, block = exp.shift 3
|
6
|
+
block = process(block)
|
7
|
+
args = convert_block_args(block[1])
|
8
|
+
stmt = block[2].first
|
9
|
+
s(:iter, process(call), args, stmt)
|
10
|
+
end
|
11
|
+
|
12
|
+
def process_brace_block exp
|
13
|
+
handle_generic_block exp
|
14
|
+
end
|
15
|
+
|
16
|
+
def process_do_block exp
|
17
|
+
handle_generic_block exp
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_params exp
|
21
|
+
_, normal, defaults, *_ = exp.shift 6
|
22
|
+
|
23
|
+
args = [*normal].map do |id|
|
24
|
+
identifier_node_to_symbol id
|
25
|
+
end
|
26
|
+
|
27
|
+
assigns = [*defaults].map do |pair|
|
28
|
+
sym = identifier_node_to_symbol pair[0]
|
29
|
+
val = process pair[1]
|
30
|
+
s(:lasgn, sym, val)
|
31
|
+
end
|
32
|
+
|
33
|
+
if assigns.length > 0
|
34
|
+
args += assigns.map {|lasgn| lasgn[1]}
|
35
|
+
args << s(:block, *assigns)
|
36
|
+
end
|
37
|
+
|
38
|
+
s(:args, *args)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def handle_generic_block exp
|
44
|
+
_, args, stmts = exp.shift 3
|
45
|
+
s(:block, process(args), s(handle_statement_list(stmts)))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Conditionals
|
4
|
+
def process_if exp
|
5
|
+
_, cond, truepart, falsepart = exp.shift 4
|
6
|
+
s(:if,
|
7
|
+
process(cond),
|
8
|
+
handle_statement_list(truepart),
|
9
|
+
process(falsepart))
|
10
|
+
end
|
11
|
+
|
12
|
+
def process_elsif exp
|
13
|
+
process_if exp
|
14
|
+
end
|
15
|
+
|
16
|
+
def process_if_mod exp
|
17
|
+
_, cond, truepart = exp.shift 3
|
18
|
+
s(:if, process(cond), process(truepart), nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
def process_unless_mod exp
|
22
|
+
_, cond, truepart = exp.shift 3
|
23
|
+
s(:if, process(cond), nil, process(truepart))
|
24
|
+
end
|
25
|
+
|
26
|
+
def process_unless exp
|
27
|
+
_, cond, truepart, falsepart = exp.shift 4
|
28
|
+
s(:if,
|
29
|
+
process(cond),
|
30
|
+
process(falsepart),
|
31
|
+
handle_statement_list(truepart))
|
32
|
+
end
|
33
|
+
|
34
|
+
def process_case exp
|
35
|
+
_, expr, clauses = exp.shift 3
|
36
|
+
s(:case, process(expr), *process(clauses))
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_when exp
|
40
|
+
_, values, truepart, falsepart = exp.shift 4
|
41
|
+
|
42
|
+
if falsepart.nil?
|
43
|
+
falsepart = [nil]
|
44
|
+
else
|
45
|
+
falsepart = process(falsepart)
|
46
|
+
if falsepart.first.is_a? Symbol
|
47
|
+
falsepart = s(falsepart)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
s(s(:when,
|
52
|
+
process(s(:array, values)),
|
53
|
+
handle_statement_list(truepart)),
|
54
|
+
*falsepart)
|
55
|
+
end
|
56
|
+
|
57
|
+
def process_else exp
|
58
|
+
_, body = exp.shift 2
|
59
|
+
handle_statement_list body
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Hashes
|
4
|
+
def process_hash exp
|
5
|
+
_, elems = exp.shift 2
|
6
|
+
s(:hash, *process(elems))
|
7
|
+
end
|
8
|
+
|
9
|
+
def process_assoclist_from_args exp
|
10
|
+
_, elems = exp.shift 2
|
11
|
+
result = s()
|
12
|
+
elems.each {|sub_exp|
|
13
|
+
process(sub_exp).each {|elm|
|
14
|
+
result << elm
|
15
|
+
}
|
16
|
+
}
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_assoc_new exp
|
21
|
+
_, left, right = exp.shift 3
|
22
|
+
s(process(left), process(right))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module HelperMethods
|
4
|
+
def handle_list_with_optional_splat exp
|
5
|
+
if exp.nil?
|
6
|
+
[]
|
7
|
+
elsif exp.first.is_a? Symbol
|
8
|
+
process(exp)
|
9
|
+
else
|
10
|
+
exp.map { |sub_exp| process(sub_exp) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def convert_block_args(args)
|
15
|
+
args && s(:lasgn, args[1][1])
|
16
|
+
end
|
17
|
+
|
18
|
+
def handle_statement_list exp
|
19
|
+
statements = exp.
|
20
|
+
map { |sub_exp| process(sub_exp) }.
|
21
|
+
reject { |sub_exp| sub_exp.sexp_type == :void_stmt }
|
22
|
+
|
23
|
+
if statements.length == 1
|
24
|
+
statements.first
|
25
|
+
else
|
26
|
+
s(:block, *statements)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def identifier_node_to_symbol exp
|
31
|
+
assert_type exp, :@ident
|
32
|
+
_, ident, _ = exp.shift 3
|
33
|
+
|
34
|
+
ident.to_sym
|
35
|
+
end
|
36
|
+
|
37
|
+
def generic_add_star exp
|
38
|
+
_, args, splatarg = exp.shift 3
|
39
|
+
items = args.map { |sub| process(sub) }
|
40
|
+
items << s(:splat, process(splatarg))
|
41
|
+
s(*items)
|
42
|
+
end
|
43
|
+
|
44
|
+
def is_literal? exp
|
45
|
+
exp.sexp_type == :lit
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Literals
|
4
|
+
def process_string_literal exp
|
5
|
+
_, content = exp.shift 2
|
6
|
+
process(content)
|
7
|
+
end
|
8
|
+
|
9
|
+
def process_string_content exp
|
10
|
+
_, inner = exp.shift 2
|
11
|
+
|
12
|
+
string = extract_inner_string(inner)
|
13
|
+
rest = []
|
14
|
+
|
15
|
+
if string.sexp_type == :str
|
16
|
+
string = string[1]
|
17
|
+
else
|
18
|
+
rest << string
|
19
|
+
string = ""
|
20
|
+
end
|
21
|
+
|
22
|
+
string = unescape(string)
|
23
|
+
|
24
|
+
until exp.empty? do
|
25
|
+
result = process(exp.shift)
|
26
|
+
if result.sexp_type == :str
|
27
|
+
result[1] = unescape(result[1])
|
28
|
+
end
|
29
|
+
rest << result
|
30
|
+
end
|
31
|
+
|
32
|
+
if rest.empty?
|
33
|
+
s(:str, string)
|
34
|
+
else
|
35
|
+
s(:dstr, string, *rest)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_string_embexpr exp
|
40
|
+
_, list = exp.shift 2
|
41
|
+
s(:evstr, process(list.first))
|
42
|
+
end
|
43
|
+
|
44
|
+
def process_regexp_literal exp
|
45
|
+
_, content, _ = exp.shift 3
|
46
|
+
|
47
|
+
string = extract_inner_string content[0]
|
48
|
+
|
49
|
+
s(:lit, Regexp.new(string[1]))
|
50
|
+
end
|
51
|
+
|
52
|
+
def process_symbol_literal exp
|
53
|
+
_, symbol = exp.shift 2
|
54
|
+
sym = symbol[1]
|
55
|
+
s(:lit, extract_node_symbol(sym))
|
56
|
+
end
|
57
|
+
|
58
|
+
def process_dyna_symbol exp
|
59
|
+
_, list = exp.shift 2
|
60
|
+
|
61
|
+
string = process list[0]
|
62
|
+
s(:lit, string[1].to_sym)
|
63
|
+
end
|
64
|
+
|
65
|
+
def process_at_tstring_content exp
|
66
|
+
_, string, _ = exp.shift 3
|
67
|
+
s(:str, string)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def extract_inner_string exp
|
73
|
+
process(exp) || s(:str, "")
|
74
|
+
end
|
75
|
+
|
76
|
+
def unescape string
|
77
|
+
string.gsub /(\\[n\\"])/ do
|
78
|
+
eval "\"#{$1}\""
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module MethodCalls
|
4
|
+
def process_method_add_arg exp
|
5
|
+
_, call, parens = exp.shift 3
|
6
|
+
call = process call
|
7
|
+
s(:call, call[1], call[2], process(parens))
|
8
|
+
end
|
9
|
+
|
10
|
+
def process_call exp
|
11
|
+
_, receiver, _, method = exp.shift 4
|
12
|
+
s(:call, process(receiver), identifier_node_to_symbol(method), s(:arglist))
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_command exp
|
16
|
+
_, ident, arglist = exp.shift 3
|
17
|
+
|
18
|
+
ident = identifier_node_to_symbol ident
|
19
|
+
arglist = process arglist
|
20
|
+
|
21
|
+
s(:call, nil, ident, arglist)
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_command_call exp
|
25
|
+
_, receiver, _, method, arguments = exp.shift 5
|
26
|
+
s(:call,
|
27
|
+
process(receiver),
|
28
|
+
identifier_node_to_symbol(method),
|
29
|
+
process(arguments))
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_vcall exp
|
33
|
+
_, ident = exp.shift 3
|
34
|
+
|
35
|
+
ident = identifier_node_to_symbol ident
|
36
|
+
|
37
|
+
s(:call, nil, ident, s(:arglist))
|
38
|
+
end
|
39
|
+
|
40
|
+
def process_fcall exp
|
41
|
+
_, method = exp.shift 2
|
42
|
+
s(:call, nil, identifier_node_to_symbol(method), s(:arglist))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Methods
|
4
|
+
def process_def exp
|
5
|
+
_, ident, params, body = exp.shift 4
|
6
|
+
ident = identifier_node_to_symbol ident
|
7
|
+
s(:defn, ident, process(params), method_body(body))
|
8
|
+
end
|
9
|
+
|
10
|
+
def process_defs exp
|
11
|
+
_, receiver, _, method, args, body = exp.shift 6
|
12
|
+
s(:defs, process(receiver),
|
13
|
+
identifier_node_to_symbol(method),
|
14
|
+
process(args), process(body))
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_return exp
|
18
|
+
_, arglist = exp.shift 2
|
19
|
+
arglist = process(arglist)
|
20
|
+
s(:return, arglist[1])
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_return0 exp
|
24
|
+
_ = exp.shift
|
25
|
+
s(:return)
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_body exp
|
29
|
+
scope = process exp
|
30
|
+
block = scope[1]
|
31
|
+
if block.length == 1
|
32
|
+
block.push s(:nil)
|
33
|
+
end
|
34
|
+
scope
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RipperRubyParser
|
2
|
+
module SexpHandlers
|
3
|
+
module Operators
|
4
|
+
OPERATOR_MAP = {
|
5
|
+
"&&".to_sym => :and,
|
6
|
+
"||".to_sym => :or
|
7
|
+
}
|
8
|
+
|
9
|
+
def process_binary exp
|
10
|
+
_, left, op, right = exp.shift 4
|
11
|
+
mapped = OPERATOR_MAP[op]
|
12
|
+
if mapped
|
13
|
+
s(mapped, process(left), process(right))
|
14
|
+
else
|
15
|
+
s(:call, process(left), op, s(:arglist, process(right)))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def process_unary exp
|
20
|
+
_, _, arg = exp.shift 3
|
21
|
+
arg = process(arg)
|
22
|
+
if is_literal? arg
|
23
|
+
s(:lit, -arg[1])
|
24
|
+
else
|
25
|
+
s(:call, arg, :-@, s(:arglist))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_dot2 exp
|
30
|
+
_, left, right = exp.shift 3
|
31
|
+
left = process(left)
|
32
|
+
right = process(right)
|
33
|
+
if is_literal?(left) && is_literal?(right)
|
34
|
+
s(:lit, Range.new(left[1], right[1]))
|
35
|
+
else
|
36
|
+
s(:dot2, left, right)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|