ripper_ruby_parser 0.0.8 → 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.
- checksums.yaml +7 -0
- data/{README.rdoc → README.md} +17 -17
- data/Rakefile +3 -1
- data/lib/ripper_ruby_parser/{commenting_sexp_builder.rb → commenting_ripper_parser.rb} +22 -6
- data/lib/ripper_ruby_parser/parser.rb +3 -18
- data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +2 -1
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +6 -10
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +37 -60
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +31 -25
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +18 -8
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +22 -18
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +12 -23
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +16 -8
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +41 -15
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +40 -23
- data/lib/ripper_ruby_parser/sexp_processor.rb +38 -19
- data/lib/ripper_ruby_parser/version.rb +1 -1
- data/test/pt_testcase/pt_test.rb +15 -1
- data/test/test_helper.rb +6 -3
- data/test/unit/commenting_ripper_parser_test.rb +121 -0
- data/test/unit/parser_assignment_test.rb +23 -24
- data/test/unit/parser_blocks_test.rb +207 -35
- data/test/unit/parser_conditionals_test.rb +251 -9
- data/test/unit/parser_literals_test.rb +348 -8
- data/test/unit/parser_loops_test.rb +20 -21
- data/test/unit/parser_method_calls_test.rb +132 -8
- data/test/unit/parser_operators_test.rb +97 -7
- data/test/unit/parser_test.rb +631 -1231
- data/test/unit/sexp_processor_test.rb +26 -28
- metadata +28 -38
- data/test/unit/commenting_sexp_builder_test.rb +0 -113
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 12102f722ef4074c0f6d46d207dba7dac580d0af
|
4
|
+
data.tar.gz: edf3dc287249ae2f0ccedb39e2f3cfdae622daff
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9450f761539fbf3b3d662447497ef1fa7a220a02e9656139bb35d305863cde02a1364b9c9802dcd20883a0c6be16f7d8e80aa4529409445bf280d07e5d4a29fb
|
7
|
+
data.tar.gz: 231ced88a63860467aa18a66c37513b49e232dc9aff74c03d6ba6b7b1ac5d30bf284616ec50d05e38385b66237c3086cb78fe526aeae648b6dd1f4a8dda8a85b
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,38 +1,38 @@
|
|
1
|
-
|
1
|
+
# RipperRubyParser
|
2
2
|
|
3
3
|
by Matijs van Zuijlen
|
4
4
|
|
5
5
|
http://www.github.com/mvz/ripper_ruby_parser
|
6
6
|
|
7
|
-
|
7
|
+
## Description
|
8
8
|
|
9
9
|
Parse with Ripper, produce sexps that are compatible with RubyParser.
|
10
10
|
|
11
|
-
|
11
|
+
## Features/Notes
|
12
12
|
|
13
13
|
* Drop-in replacement for RubyParser.
|
14
|
-
* Should handle 1.9 syntax gracefully.
|
15
|
-
* Needs MRI 1.9.3
|
14
|
+
* Should handle 1.9 and later syntax gracefully.
|
15
|
+
* Needs MRI 1.9.3 or higher
|
16
16
|
|
17
|
-
|
17
|
+
## Install
|
18
18
|
|
19
19
|
* gem install ripper_ruby_parser
|
20
20
|
|
21
|
-
|
21
|
+
## Synopsis
|
22
22
|
|
23
|
-
|
23
|
+
require 'ripper_ruby_parser'
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
parser = RipperRubyParser::Parser.new
|
26
|
+
result = parser.parse "puts 'Hello World'"
|
27
|
+
p result
|
28
|
+
# => s(:call, nil, :puts, s(:arglist, s(:str, "Hello World!")))
|
29
29
|
|
30
|
-
|
30
|
+
## Requirements
|
31
31
|
|
32
|
-
* Ruby 1.9.3
|
32
|
+
* Ruby 1.9.3 or higher
|
33
33
|
* sexp_processor
|
34
34
|
|
35
|
-
|
35
|
+
## Hacking and contributing
|
36
36
|
|
37
37
|
If you want to send pull requests or patches, please:
|
38
38
|
|
@@ -45,11 +45,11 @@ If you want to send pull requests or patches, please:
|
|
45
45
|
* Try not to include changes that are irrelevant to your feature in the
|
46
46
|
same commit.
|
47
47
|
|
48
|
-
|
48
|
+
## License
|
49
49
|
|
50
50
|
(The MIT License)
|
51
51
|
|
52
|
-
Copyright (c) 2012 Matijs van Zuijlen
|
52
|
+
Copyright (c) 2012, 2014 Matijs van Zuijlen
|
53
53
|
|
54
54
|
Permission is hereby granted, free of charge, to any person obtaining
|
55
55
|
a copy of this software and associated documentation files (the
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require "bundler/gem_tasks"
|
1
3
|
require 'rake/testtask'
|
2
4
|
|
3
5
|
namespace :test do
|
@@ -20,7 +22,7 @@ namespace :test do
|
|
20
22
|
t.warning = true
|
21
23
|
end
|
22
24
|
|
23
|
-
task :run => [:unit, :end_to_end]
|
25
|
+
task :run => [:unit, :end_to_end, :pt_testcase]
|
24
26
|
end
|
25
27
|
|
26
28
|
desc 'Alias to test:run'
|
@@ -2,7 +2,9 @@ require 'ripper'
|
|
2
2
|
require 'ripper_ruby_parser/syntax_error'
|
3
3
|
|
4
4
|
module RipperRubyParser
|
5
|
-
|
5
|
+
# Variant of Ripper's SexpBuilderPP parser class that inserts comments as
|
6
|
+
# Sexps into the built parse tree.
|
7
|
+
class CommentingRipperParser < Ripper::SexpBuilderPP
|
6
8
|
def initialize *args
|
7
9
|
super
|
8
10
|
@comment = nil
|
@@ -10,6 +12,13 @@ module RipperRubyParser
|
|
10
12
|
@in_symbol = false
|
11
13
|
end
|
12
14
|
|
15
|
+
def parse
|
16
|
+
result = suppress_warnings { super }
|
17
|
+
raise "Ripper parse failed." unless result
|
18
|
+
|
19
|
+
Sexp.from_array(result)
|
20
|
+
end
|
21
|
+
|
13
22
|
def on_comment tok
|
14
23
|
@comment ||= ""
|
15
24
|
@comment += tok
|
@@ -92,14 +101,21 @@ module RipperRubyParser
|
|
92
101
|
def commentize name, exp
|
93
102
|
raise "Comment stack empty in #{name} event" if @comment_stack.empty?
|
94
103
|
tok, comment = @comment_stack.pop
|
104
|
+
@comment = nil
|
95
105
|
unless tok == name
|
96
106
|
raise "Expected on_#{tok} event, got on_#{name}"
|
97
107
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
108
|
+
[:comment, comment || "", exp]
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def suppress_warnings
|
114
|
+
old_verbose = $VERBOSE
|
115
|
+
$VERBOSE = nil
|
116
|
+
result = yield
|
117
|
+
$VERBOSE = old_verbose
|
118
|
+
result
|
103
119
|
end
|
104
120
|
end
|
105
121
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'ripper_ruby_parser/
|
1
|
+
require 'ripper_ruby_parser/commenting_ripper_parser'
|
2
2
|
require 'ripper_ruby_parser/sexp_processor'
|
3
3
|
|
4
4
|
module RipperRubyParser
|
@@ -13,13 +13,8 @@ module RipperRubyParser
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def parse source, filename='(string)', lineno=1
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
result = suppress_warnings { parser.parse }
|
20
|
-
raise "Ripper parse failed." if result.nil?
|
21
|
-
|
22
|
-
exp = Sexp.from_array(result)
|
16
|
+
parser = CommentingRipperParser.new(source, filename, lineno)
|
17
|
+
exp = parser.parse
|
23
18
|
|
24
19
|
@processor.filename = filename
|
25
20
|
@processor.extra_compatible = extra_compatible
|
@@ -31,16 +26,6 @@ module RipperRubyParser
|
|
31
26
|
result
|
32
27
|
end
|
33
28
|
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def suppress_warnings
|
38
|
-
old_verbose = $VERBOSE
|
39
|
-
$VERBOSE = nil
|
40
|
-
result = yield
|
41
|
-
$VERBOSE = old_verbose
|
42
|
-
result
|
43
|
-
end
|
44
29
|
end
|
45
30
|
end
|
46
31
|
|
@@ -3,7 +3,6 @@ module RipperRubyParser
|
|
3
3
|
module Assignment
|
4
4
|
def process_assign exp
|
5
5
|
_, lvalue, value = exp.shift 3
|
6
|
-
|
7
6
|
lvalue = process(lvalue)
|
8
7
|
value = process(value)
|
9
8
|
|
@@ -35,7 +34,7 @@ module RipperRubyParser
|
|
35
34
|
case right.sexp_type
|
36
35
|
when :fake_array
|
37
36
|
right[0] = :array
|
38
|
-
when :
|
37
|
+
when :splat
|
39
38
|
# Do nothing
|
40
39
|
else
|
41
40
|
right = s(:to_ary, right)
|
@@ -104,11 +103,7 @@ module RipperRubyParser
|
|
104
103
|
def create_valueless_assignment_sub_type(item)
|
105
104
|
item = with_line_number(item.line,
|
106
105
|
create_regular_assignment_sub_type(item, nil))
|
107
|
-
|
108
|
-
item.last.pop
|
109
|
-
else
|
110
|
-
item.pop
|
111
|
-
end
|
106
|
+
item.pop
|
112
107
|
return item
|
113
108
|
end
|
114
109
|
|
@@ -129,7 +124,7 @@ module RipperRubyParser
|
|
129
124
|
if (mapped = OPERATOR_ASSIGNMENT_MAP[operator])
|
130
125
|
s(mapped, lvalue, create_assignment_sub_type(lvalue, value))
|
131
126
|
else
|
132
|
-
operator_call = s(:call, lvalue, operator,
|
127
|
+
operator_call = s(:call, lvalue, operator, value)
|
133
128
|
create_assignment_sub_type lvalue, operator_call
|
134
129
|
end
|
135
130
|
end
|
@@ -140,10 +135,11 @@ module RipperRubyParser
|
|
140
135
|
when :aref_field
|
141
136
|
_, arr, arglist = lvalue
|
142
137
|
arglist << value
|
143
|
-
|
138
|
+
arglist.shift
|
139
|
+
s(:attrasgn, arr, :[]=, *arglist)
|
144
140
|
when :field
|
145
141
|
_, obj, _, (_, field) = lvalue
|
146
|
-
s(:attrasgn, obj, :"#{field}=",
|
142
|
+
s(:attrasgn, obj, :"#{field}=", value)
|
147
143
|
else
|
148
144
|
create_assignment_sub_type lvalue, value
|
149
145
|
end
|
@@ -19,22 +19,25 @@ module RipperRubyParser
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def process_params exp
|
22
|
-
|
22
|
+
if exp.size == 6
|
23
|
+
_, normal, defaults, splat, rest, block = exp.shift 6
|
24
|
+
else
|
25
|
+
_, normal, defaults, splat, rest, _, _, block = exp.shift 8
|
26
|
+
end
|
23
27
|
|
24
28
|
args = [*normal].map do |id|
|
25
29
|
process(id)
|
26
30
|
end
|
27
31
|
|
28
|
-
|
32
|
+
[*defaults].each do |pair|
|
29
33
|
sym = process(pair[0])
|
30
|
-
args << sym
|
31
34
|
val = process(pair[1])
|
32
|
-
s(:lasgn, sym[1], val)
|
35
|
+
args << s(:lasgn, sym[1], val)
|
33
36
|
end
|
34
37
|
|
35
|
-
args << process(
|
38
|
+
args << process(splat) unless splat.nil? || splat == 0
|
39
|
+
[*rest].each {|arg| args << process(arg)}
|
36
40
|
args << process(block) unless block.nil?
|
37
|
-
args << s(:block, *assigns) if assigns.length > 0
|
38
41
|
|
39
42
|
s(:args, *args)
|
40
43
|
end
|
@@ -44,20 +47,20 @@ module RipperRubyParser
|
|
44
47
|
|
45
48
|
names = process(args)
|
46
49
|
|
47
|
-
|
50
|
+
convert_special_args names
|
48
51
|
end
|
49
52
|
|
50
53
|
def process_begin exp
|
51
54
|
_, body = exp.shift 2
|
52
55
|
|
53
|
-
|
54
|
-
|
55
|
-
strip_wrapping_block(block.compact)
|
56
|
+
body = process(body)
|
57
|
+
strip_typeless_sexp(body)
|
56
58
|
end
|
57
59
|
|
58
60
|
def process_rescue exp
|
59
61
|
_, eclass, evar, block, after = exp.shift 5
|
60
62
|
rescue_block = map_body(block)
|
63
|
+
rescue_block << nil if rescue_block.empty?
|
61
64
|
|
62
65
|
arr = []
|
63
66
|
if eclass
|
@@ -70,13 +73,11 @@ module RipperRubyParser
|
|
70
73
|
end
|
71
74
|
|
72
75
|
if evar
|
73
|
-
|
74
|
-
easgn = s(:lasgn, evar, s(:gvar, :$!))
|
75
|
-
arr << easgn
|
76
|
+
arr << create_assignment_sub_type(process(evar), s(:gvar, :$!))
|
76
77
|
end
|
77
78
|
|
78
79
|
s(
|
79
|
-
s(:resbody, s(:array, *arr),
|
80
|
+
s(:resbody, s(:array, *arr), *rescue_block),
|
80
81
|
*process(after))
|
81
82
|
end
|
82
83
|
|
@@ -85,10 +86,6 @@ module RipperRubyParser
|
|
85
86
|
|
86
87
|
body = map_body body
|
87
88
|
|
88
|
-
#unless rescue_block or ensure_block
|
89
|
-
# return s(:scope, s(:block, *body))
|
90
|
-
#end
|
91
|
-
|
92
89
|
body = wrap_in_block(body)
|
93
90
|
|
94
91
|
body = if body.nil?
|
@@ -110,11 +107,15 @@ module RipperRubyParser
|
|
110
107
|
body = s(s(:ensure, *body))
|
111
108
|
end
|
112
109
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
110
|
+
body = wrap_in_block(body)
|
111
|
+
|
112
|
+
body = if body.nil?
|
113
|
+
s()
|
114
|
+
else
|
115
|
+
s(body)
|
116
|
+
end
|
117
|
+
|
118
|
+
body
|
118
119
|
end
|
119
120
|
|
120
121
|
def process_rescue_mod exp
|
@@ -124,7 +125,7 @@ module RipperRubyParser
|
|
124
125
|
|
125
126
|
def process_ensure exp
|
126
127
|
_, block = exp.shift 2
|
127
|
-
|
128
|
+
strip_typeless_sexp safe_wrap_in_block s(*map_body(block))
|
128
129
|
end
|
129
130
|
|
130
131
|
def process_next exp
|
@@ -147,8 +148,10 @@ module RipperRubyParser
|
|
147
148
|
|
148
149
|
def process_lambda exp
|
149
150
|
_, args, statements = exp.shift 3
|
150
|
-
|
151
|
-
|
151
|
+
args = convert_special_args(process(args))
|
152
|
+
args = 0 if args == s(:args)
|
153
|
+
make_iter(s(:call, nil, :lambda),
|
154
|
+
args,
|
152
155
|
*handle_potentially_typeless_sexp(statements))
|
153
156
|
end
|
154
157
|
|
@@ -156,57 +159,31 @@ module RipperRubyParser
|
|
156
159
|
|
157
160
|
def handle_generic_block exp
|
158
161
|
_, args, stmts = exp.shift 3
|
162
|
+
args = process(args)
|
163
|
+
args = 0 if args == s(:args)
|
159
164
|
# FIXME: Symbol :block is irrelevant.
|
160
|
-
s(:block,
|
165
|
+
s(:block, args, s(wrap_in_block(map_body(stmts))))
|
161
166
|
end
|
162
167
|
|
163
|
-
def
|
164
|
-
return block unless block.sexp_type == :block
|
168
|
+
def strip_typeless_sexp(block)
|
165
169
|
case block.length
|
166
|
-
when
|
170
|
+
when 0
|
167
171
|
s(:nil)
|
168
|
-
when
|
169
|
-
block[
|
172
|
+
when 1
|
173
|
+
block[0]
|
170
174
|
else
|
171
175
|
block
|
172
176
|
end
|
173
177
|
end
|
174
178
|
|
175
|
-
def arg_name_to_lasgn(name)
|
176
|
-
case name.sexp_type
|
177
|
-
when :lvar
|
178
|
-
s(:lasgn, name[1])
|
179
|
-
when :blockarg
|
180
|
-
s(:lasgn, :"&#{name[1][1]}")
|
181
|
-
when :splat
|
182
|
-
if name[1].nil?
|
183
|
-
s(:splat)
|
184
|
-
else
|
185
|
-
s(:splat, s(:lasgn, name[1][1]))
|
186
|
-
end
|
187
|
-
else
|
188
|
-
name
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
179
|
def make_iter call, args, stmt
|
180
|
+
args = s(:args) unless args
|
193
181
|
if stmt.nil?
|
194
182
|
s(:iter, call, args)
|
195
183
|
else
|
196
184
|
s(:iter, call, args, stmt)
|
197
185
|
end
|
198
186
|
end
|
199
|
-
|
200
|
-
def args_to_assignment names
|
201
|
-
names.shift
|
202
|
-
if names.length == 1 and names.first.sexp_type == :lvar
|
203
|
-
s(:lasgn, names.first[1])
|
204
|
-
elsif names.length == 1 and names.first.sexp_type == :masgn
|
205
|
-
names.first
|
206
|
-
else
|
207
|
-
s(:masgn, s(:array, *names.map { |name| arg_name_to_lasgn(name) }))
|
208
|
-
end
|
209
|
-
end
|
210
187
|
end
|
211
188
|
end
|
212
189
|
end
|
@@ -4,42 +4,35 @@ module RipperRubyParser
|
|
4
4
|
def process_if exp
|
5
5
|
_, cond, truepart, falsepart = exp.shift 4
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
if cond.sexp_type == :not
|
12
|
-
cond = cond[1]
|
13
|
-
truepart, falsepart = falsepart, truepart
|
14
|
-
end
|
15
|
-
|
16
|
-
s(:if, cond, truepart, falsepart)
|
7
|
+
s(:if, handle_condition(cond),
|
8
|
+
wrap_in_block(map_body(truepart)),
|
9
|
+
process(falsepart))
|
17
10
|
end
|
18
11
|
|
19
12
|
def process_elsif exp
|
20
13
|
_, cond, truepart, falsepart = exp.shift 4
|
21
14
|
|
22
15
|
s(:if, process(cond),
|
23
|
-
|
16
|
+
wrap_in_block(map_body(truepart)),
|
24
17
|
process(falsepart))
|
25
18
|
end
|
26
19
|
|
27
20
|
def process_if_mod exp
|
28
21
|
_, cond, truepart = exp.shift 3
|
29
|
-
|
22
|
+
s(:if, handle_condition(cond), process(truepart), nil)
|
30
23
|
end
|
31
24
|
|
32
25
|
def process_unless_mod exp
|
33
26
|
_, cond, truepart = exp.shift 3
|
34
|
-
s(:if,
|
27
|
+
s(:if, handle_condition(cond), nil, process(truepart))
|
35
28
|
end
|
36
29
|
|
37
30
|
def process_unless exp
|
38
31
|
_, cond, truepart, falsepart = exp.shift 4
|
39
32
|
s(:if,
|
40
|
-
|
33
|
+
handle_condition(cond),
|
41
34
|
process(falsepart),
|
42
|
-
|
35
|
+
wrap_in_block(map_body(truepart)))
|
43
36
|
end
|
44
37
|
|
45
38
|
def process_case exp
|
@@ -58,25 +51,38 @@ module RipperRubyParser
|
|
58
51
|
falsepart = s(falsepart)
|
59
52
|
end
|
60
53
|
end
|
54
|
+
falsepart = [nil] if falsepart.empty?
|
61
55
|
|
62
56
|
values = handle_array_elements values
|
63
|
-
values = values.map do |val|
|
64
|
-
if val.sexp_type == :splat
|
65
|
-
s(:when, val[1], nil)
|
66
|
-
else
|
67
|
-
val
|
68
|
-
end
|
69
|
-
end
|
70
57
|
|
71
|
-
|
72
|
-
|
58
|
+
truepart = map_body(truepart)
|
59
|
+
truepart = [nil] if truepart.empty?
|
60
|
+
|
61
|
+
s(s(:when,
|
62
|
+
s(:array, *values),
|
63
|
+
*truepart),
|
73
64
|
*falsepart)
|
74
65
|
end
|
75
66
|
|
76
67
|
def process_else exp
|
77
68
|
_, body = exp.shift 2
|
78
|
-
|
69
|
+
safe_wrap_in_block(map_body(body))
|
79
70
|
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def handle_condition(cond)
|
75
|
+
cond = process(cond)
|
76
|
+
if (cond.sexp_type == :lit) && cond[1].is_a?(Regexp)
|
77
|
+
cond = s(:match, cond)
|
78
|
+
elsif cond.sexp_type == :dot2
|
79
|
+
cond = s(:flip2, *cond[1..-1])
|
80
|
+
elsif cond.sexp_type == :dot3
|
81
|
+
cond = s(:flip3, *cond[1..-1])
|
82
|
+
end
|
83
|
+
return cond
|
84
|
+
end
|
85
|
+
|
80
86
|
end
|
81
87
|
end
|
82
88
|
end
|