ripper_ruby_parser 1.6.0 → 1.8.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 +4 -4
- data/CHANGELOG.md +86 -0
- data/README.md +8 -25
- data/lib/ripper_ruby_parser.rb +2 -2
- data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +54 -23
- data/lib/ripper_ruby_parser/parser.rb +3 -3
- data/lib/ripper_ruby_parser/sexp_handlers.rb +11 -9
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +10 -11
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +48 -63
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +17 -19
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +35 -2
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +15 -242
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +4 -2
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +1 -1
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +24 -24
- data/lib/ripper_ruby_parser/sexp_handlers/string_literals.rb +266 -0
- data/lib/ripper_ruby_parser/sexp_processor.rb +47 -78
- data/lib/ripper_ruby_parser/unescape.rb +79 -50
- data/lib/ripper_ruby_parser/version.rb +1 -1
- metadata +115 -78
- data/Rakefile +0 -33
- data/test/end_to_end/comments_test.rb +0 -59
- data/test/end_to_end/comparison_test.rb +0 -104
- data/test/end_to_end/lib_comparison_test.rb +0 -29
- data/test/end_to_end/line_numbering_test.rb +0 -64
- data/test/end_to_end/samples_comparison_test.rb +0 -13
- data/test/end_to_end/test_comparison_test.rb +0 -32
- data/test/pt_testcase/pt_test.rb +0 -44
- data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +0 -190
- data/test/ripper_ruby_parser/parser_test.rb +0 -469
- data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +0 -649
- data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +0 -661
- data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +0 -536
- data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +0 -1117
- data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +0 -209
- data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +0 -267
- data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +0 -427
- data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +0 -399
- data/test/ripper_ruby_parser/sexp_processor_test.rb +0 -303
- data/test/ripper_ruby_parser/version_test.rb +0 -7
- data/test/samples/assignment.rb +0 -17
- data/test/samples/comments.rb +0 -13
- data/test/samples/conditionals.rb +0 -23
- data/test/samples/loops.rb +0 -36
- data/test/samples/misc.rb +0 -278
- data/test/samples/number.rb +0 -7
- data/test/samples/operators.rb +0 -18
- data/test/samples/strings.rb +0 -140
- data/test/test_helper.rb +0 -79
@@ -47,33 +47,20 @@ module RipperRubyParser
|
|
47
47
|
|
48
48
|
def process_case(exp)
|
49
49
|
_, expr, clauses = exp.shift 3
|
50
|
-
s(:case, process(expr), *process(clauses))
|
50
|
+
s(:case, process(expr), *process(clauses).sexp_body)
|
51
51
|
end
|
52
52
|
|
53
53
|
def process_when(exp)
|
54
54
|
_, values, truepart, falsepart = exp.shift 4
|
55
55
|
|
56
|
-
falsepart
|
57
|
-
falsepart = unwrap_nil falsepart if falsepart
|
58
|
-
|
59
|
-
if falsepart.nil?
|
60
|
-
falsepart = [nil]
|
61
|
-
elsif falsepart.first.is_a? Symbol
|
62
|
-
falsepart = s(falsepart)
|
63
|
-
end
|
56
|
+
falsepart ||= s(:void_stmt)
|
64
57
|
|
58
|
+
falsepart = unwrap_case_body process(falsepart)
|
65
59
|
values = process(values).sexp_body
|
60
|
+
truepart = unwrap_block process(truepart)
|
66
61
|
|
67
|
-
|
68
|
-
|
69
|
-
[nil]
|
70
|
-
else
|
71
|
-
unwrap_block(truepart.shift) + truepart
|
72
|
-
end
|
73
|
-
|
74
|
-
s(s(:when,
|
75
|
-
s(:array, *values),
|
76
|
-
*truepart),
|
62
|
+
s(:case_body,
|
63
|
+
s(:when, s(:array, *values), *truepart),
|
77
64
|
*falsepart)
|
78
65
|
end
|
79
66
|
|
@@ -109,6 +96,17 @@ module RipperRubyParser
|
|
109
96
|
s(:if, cond, truepart, falsepart)
|
110
97
|
end
|
111
98
|
end
|
99
|
+
|
100
|
+
def unwrap_case_body(exp)
|
101
|
+
case exp.sexp_type
|
102
|
+
when :case_body
|
103
|
+
exp.sexp_body
|
104
|
+
when :void_stmt
|
105
|
+
[nil]
|
106
|
+
else
|
107
|
+
[exp]
|
108
|
+
end
|
109
|
+
end
|
112
110
|
end
|
113
111
|
end
|
114
112
|
end
|
@@ -41,7 +41,7 @@ module RipperRubyParser
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def integer_literal?(exp)
|
44
|
-
exp.sexp_type == :lit && exp[1].is_a?(Integer)
|
44
|
+
exp && exp.sexp_type == :lit && exp[1].is_a?(Integer)
|
45
45
|
end
|
46
46
|
|
47
47
|
def reject_void_stmt(body)
|
@@ -81,13 +81,46 @@ module RipperRubyParser
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def unwrap_block(exp)
|
84
|
-
|
84
|
+
case exp.sexp_type
|
85
|
+
when :block
|
85
86
|
exp.sexp_body
|
87
|
+
when :void_stmt
|
88
|
+
[nil]
|
86
89
|
else
|
87
90
|
[exp]
|
88
91
|
end
|
89
92
|
end
|
90
93
|
|
94
|
+
def wrap_in_block(statements, line)
|
95
|
+
case statements.length
|
96
|
+
when 0
|
97
|
+
s(:void_stmt).line(line)
|
98
|
+
when 1
|
99
|
+
statements.first
|
100
|
+
else
|
101
|
+
first = statements.shift
|
102
|
+
s(:block, *unwrap_block(first), *statements)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def convert_void_stmt_to_nil_symbol(block)
|
107
|
+
case block.sexp_type
|
108
|
+
when :void_stmt
|
109
|
+
s(:nil)
|
110
|
+
else
|
111
|
+
block
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def convert_empty_to_nil_symbol(block)
|
116
|
+
case block.length
|
117
|
+
when 0
|
118
|
+
s(:nil)
|
119
|
+
else
|
120
|
+
block
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
91
124
|
def handle_return_argument_list(arglist)
|
92
125
|
args = process(arglist).sexp_body
|
93
126
|
|
@@ -4,132 +4,10 @@ module RipperRubyParser
|
|
4
4
|
module SexpHandlers
|
5
5
|
# Sexp handlers for literals
|
6
6
|
module Literals
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def process_string_content(exp)
|
13
|
-
_, *rest = shift_all exp
|
14
|
-
string, rest = extract_string_parts(rest)
|
15
|
-
|
16
|
-
if rest.empty?
|
17
|
-
s(:str, string)
|
18
|
-
else
|
19
|
-
s(:dstr, string, *rest)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
alias process_word process_string_content
|
24
|
-
|
25
|
-
def process_string_embexpr(exp)
|
26
|
-
_, list = exp.shift 2
|
27
|
-
|
28
|
-
val = process(list.sexp_body.first)
|
29
|
-
|
30
|
-
case val.sexp_type
|
31
|
-
when :str, :dstr
|
32
|
-
val
|
33
|
-
when :void_stmt
|
34
|
-
s(:dstr, '', s(:evstr))
|
35
|
-
else
|
36
|
-
s(:dstr, '', s(:evstr, val))
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def process_string_dvar(exp)
|
41
|
-
_, list = exp.shift 2
|
42
|
-
val = process(list)
|
43
|
-
s(:dstr, '', s(:evstr, val))
|
44
|
-
end
|
45
|
-
|
46
|
-
def process_string_concat(exp)
|
47
|
-
_, left, right = exp.shift 3
|
48
|
-
|
49
|
-
left = process(left)
|
50
|
-
right = process(right)
|
51
|
-
|
52
|
-
if left.sexp_type == :str
|
53
|
-
merge_left_into_right(left, right)
|
54
|
-
else
|
55
|
-
merge_right_into_left(left, right)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def process_xstring_literal(exp)
|
60
|
-
_, content = exp.shift 2
|
61
|
-
process(content)
|
62
|
-
end
|
63
|
-
|
64
|
-
def process_xstring(exp)
|
65
|
-
_, *rest = shift_all exp
|
66
|
-
string, rest = extract_string_parts(rest)
|
67
|
-
if rest.empty?
|
68
|
-
s(:xstr, string)
|
69
|
-
else
|
70
|
-
s(:dxstr, string, *rest)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def process_regexp_literal(exp)
|
75
|
-
_, content, (_, flags,) = exp.shift 3
|
76
|
-
|
77
|
-
content = process(content)
|
78
|
-
numflags = character_flags_to_numerical flags
|
79
|
-
|
80
|
-
return s(:lit, Regexp.new(content.last, numflags)) if content.length == 2
|
81
|
-
|
82
|
-
content.sexp_type = :dregx_once if flags =~ /o/
|
83
|
-
content << numflags unless numflags == 0
|
84
|
-
content
|
85
|
-
end
|
86
|
-
|
87
|
-
def process_regexp(exp)
|
88
|
-
_, *rest = shift_all exp
|
89
|
-
string, rest = extract_string_parts(rest)
|
90
|
-
s(:dregx, string, *rest)
|
91
|
-
end
|
92
|
-
|
93
|
-
def process_symbol_literal(exp)
|
94
|
-
_, symbol = exp.shift 2
|
95
|
-
handle_symbol_content(symbol)
|
96
|
-
end
|
97
|
-
|
98
|
-
def process_symbol(exp)
|
99
|
-
_, node = exp.shift 2
|
100
|
-
handle_symbol_content(node)
|
101
|
-
end
|
102
|
-
|
103
|
-
def process_dyna_symbol(exp)
|
104
|
-
_, node = exp.shift 2
|
105
|
-
handle_dyna_symbol_content(node)
|
106
|
-
end
|
107
|
-
|
108
|
-
def process_qsymbols(exp)
|
109
|
-
_, *items = shift_all(exp)
|
110
|
-
items = items.map { |item| handle_symbol_content(item) }
|
111
|
-
s(:qsymbols, *items)
|
112
|
-
end
|
113
|
-
|
114
|
-
def process_symbols(exp)
|
115
|
-
_, *items = shift_all(exp)
|
116
|
-
items = items.map { |item| handle_dyna_symbol_content(item) }
|
117
|
-
s(:symbols, *items)
|
118
|
-
end
|
119
|
-
|
120
|
-
INTERPOLATING_HEREDOC = /^<<[-~]?[^-~']/.freeze
|
121
|
-
NON_INTERPOLATING_HEREDOC = /^<<[-~]?'/.freeze
|
122
|
-
INTERPOLATING_STRINGS = ['"', '`', ':"', /^%Q.$/, /^%.$/].freeze
|
123
|
-
NON_INTERPOLATING_STRINGS = ["'", ":'", /^%q.$/].freeze
|
124
|
-
INTERPOLATING_WORD_LIST = /^%[WI].$/.freeze
|
125
|
-
NON_INTERPOLATING_WORD_LIST = /^%[wi].$/.freeze
|
126
|
-
REGEXP_LITERALS = ['/', /^%r.$/].freeze
|
127
|
-
|
128
|
-
def process_at_tstring_content(exp)
|
129
|
-
_, content, _, delim = exp.shift 4
|
130
|
-
string = handle_string_unescaping(content, delim)
|
131
|
-
string = handle_string_encoding(string, delim)
|
132
|
-
s(:str, string)
|
7
|
+
# character literals
|
8
|
+
def process_at_CHAR(exp)
|
9
|
+
_, val, pos = exp.shift 3
|
10
|
+
with_position(pos, s(:str, unescape(val[1..-1])))
|
133
11
|
end
|
134
12
|
|
135
13
|
def process_array(exp)
|
@@ -161,136 +39,31 @@ module RipperRubyParser
|
|
161
39
|
s(:kwsplat, process(param))
|
162
40
|
end
|
163
41
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
return '', [] if list.empty?
|
168
|
-
|
169
|
-
list = merge_raw_string_literals list
|
170
|
-
list = map_process_list list
|
171
|
-
|
172
|
-
parts = list.flat_map do |item|
|
173
|
-
type, val, *rest = item
|
174
|
-
if type == :dstr
|
175
|
-
if val.empty?
|
176
|
-
rest
|
177
|
-
else
|
178
|
-
[s(:str, val), *rest]
|
179
|
-
end
|
180
|
-
else
|
181
|
-
[item]
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
string = ''
|
186
|
-
while parts.first&.sexp_type == :str
|
187
|
-
str = parts.shift
|
188
|
-
string += str.last
|
189
|
-
end
|
190
|
-
|
191
|
-
return string, parts
|
192
|
-
end
|
193
|
-
|
194
|
-
def merge_raw_string_literals(list)
|
195
|
-
chunks = list.chunk { |it| it.sexp_type == :@tstring_content }
|
196
|
-
chunks.flat_map do |is_simple, items|
|
197
|
-
if is_simple && items.count > 1
|
198
|
-
head = items.first
|
199
|
-
contents = items.map { |it| it[1] }.join
|
200
|
-
[s(:@tstring_content, contents, head[2], head[3])]
|
201
|
-
else
|
202
|
-
items
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def character_flags_to_numerical(flags)
|
208
|
-
numflags = 0
|
209
|
-
|
210
|
-
numflags = Regexp::MULTILINE if flags =~ /m/
|
211
|
-
numflags |= Regexp::EXTENDED if flags =~ /x/
|
212
|
-
numflags |= Regexp::IGNORECASE if flags =~ /i/
|
213
|
-
|
214
|
-
numflags |= Regexp::NOENCODING if flags =~ /n/
|
215
|
-
numflags |= Regexp::FIXEDENCODING if flags =~ /[ues]/
|
216
|
-
|
217
|
-
numflags
|
218
|
-
end
|
219
|
-
|
220
|
-
def handle_dyna_symbol_content(node)
|
221
|
-
type, *body = *process(node)
|
222
|
-
case type
|
223
|
-
when :str, :xstr
|
224
|
-
s(:lit, body.first.to_sym)
|
225
|
-
when :dstr, :dxstr
|
226
|
-
s(:dsym, *body)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def handle_symbol_content(node)
|
231
|
-
if node.sexp_type == :'@kw'
|
232
|
-
symbol, position = extract_node_symbol_with_position(node)
|
233
|
-
else
|
234
|
-
processed = process(node)
|
235
|
-
symbol = processed.last.to_sym
|
236
|
-
position = processed.line
|
237
|
-
end
|
238
|
-
with_line_number(position, s(:lit, symbol))
|
42
|
+
# number literals
|
43
|
+
def process_at_int(exp)
|
44
|
+
make_literal(exp) { |val| Integer(val) }
|
239
45
|
end
|
240
46
|
|
241
|
-
def
|
242
|
-
|
243
|
-
right
|
47
|
+
def process_at_float(exp)
|
48
|
+
make_literal(exp, &:to_f)
|
244
49
|
end
|
245
50
|
|
246
|
-
def
|
247
|
-
|
248
|
-
left.push right
|
249
|
-
else
|
250
|
-
_, first, *rest = right
|
251
|
-
left.push s(:str, first) unless first.empty?
|
252
|
-
left.push(*rest)
|
253
|
-
end
|
51
|
+
def process_at_rational(exp)
|
52
|
+
make_literal(exp, &:to_r)
|
254
53
|
end
|
255
54
|
|
256
|
-
def
|
257
|
-
|
258
|
-
when INTERPOLATING_HEREDOC
|
259
|
-
if extra_compatible
|
260
|
-
unescape(content).delete("\r")
|
261
|
-
else
|
262
|
-
unescape(content)
|
263
|
-
end
|
264
|
-
when *INTERPOLATING_STRINGS
|
265
|
-
unescape(content)
|
266
|
-
when INTERPOLATING_WORD_LIST
|
267
|
-
unescape_wordlist_word(content)
|
268
|
-
when *NON_INTERPOLATING_STRINGS
|
269
|
-
simple_unescape(content)
|
270
|
-
when *REGEXP_LITERALS
|
271
|
-
unescape_regexp(content)
|
272
|
-
when NON_INTERPOLATING_WORD_LIST
|
273
|
-
simple_unescape_wordlist_word(content)
|
274
|
-
else
|
275
|
-
content
|
276
|
-
end
|
55
|
+
def process_at_imaginary(exp)
|
56
|
+
make_literal(exp, &:to_c)
|
277
57
|
end
|
278
58
|
|
279
|
-
|
280
|
-
case delim
|
281
|
-
when INTERPOLATING_HEREDOC, INTERPOLATING_WORD_LIST, *INTERPOLATING_STRINGS
|
282
|
-
fix_encoding string
|
283
|
-
else
|
284
|
-
string
|
285
|
-
end
|
286
|
-
end
|
59
|
+
private
|
287
60
|
|
288
61
|
# Process list of items that can be either :assoc_new or :assoc_splat
|
289
62
|
def make_hash_items(elems)
|
290
63
|
result = s()
|
291
64
|
elems.each do |sub_exp|
|
292
65
|
if sub_exp.sexp_type == :assoc_new
|
293
|
-
|
66
|
+
result += process(sub_exp).sexp_body
|
294
67
|
else # :assoc_splat
|
295
68
|
result << process(sub_exp)
|
296
69
|
end
|
@@ -52,10 +52,12 @@ module RipperRubyParser
|
|
52
52
|
def handle_conditional_loop_mod(type, negated_type, exp)
|
53
53
|
_, cond, body = exp.shift 3
|
54
54
|
|
55
|
+
cond = process(cond)
|
56
|
+
body = process(body)
|
55
57
|
check_at_start = check_at_start?(body)
|
56
58
|
construct_conditional_loop(type, negated_type,
|
57
|
-
unwrap_begin(
|
58
|
-
unwrap_begin(
|
59
|
+
unwrap_begin(cond),
|
60
|
+
unwrap_begin(body),
|
59
61
|
check_at_start)
|
60
62
|
end
|
61
63
|
|
@@ -5,9 +5,9 @@ module RipperRubyParser
|
|
5
5
|
# Sexp handers for method definitions and related constructs
|
6
6
|
module Methods
|
7
7
|
def process_def(exp)
|
8
|
-
_, ident, params, body = exp.shift
|
8
|
+
_, ident, params, body, pos = exp.shift 5
|
9
9
|
|
10
|
-
ident,
|
10
|
+
ident, = extract_node_symbol_with_position ident
|
11
11
|
|
12
12
|
in_method do
|
13
13
|
params = convert_arguments(process(params))
|
@@ -19,7 +19,7 @@ module RipperRubyParser
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def process_defs(exp)
|
22
|
-
_, receiver, _, ident, params, body = exp.shift
|
22
|
+
_, receiver, _, ident, params, body, = exp.shift 7
|
23
23
|
|
24
24
|
ident, = extract_node_symbol_with_position ident
|
25
25
|
|
@@ -83,36 +83,36 @@ module RipperRubyParser
|
|
83
83
|
|
84
84
|
def method_body(exp)
|
85
85
|
block = process exp
|
86
|
-
case block.
|
87
|
-
when
|
88
|
-
[s(:nil)]
|
86
|
+
case block.sexp_type
|
87
|
+
when :void_stmt
|
88
|
+
[s(:nil).line(block.line)]
|
89
89
|
else
|
90
90
|
unwrap_block block
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
94
|
SPECIAL_ARG_MARKER = {
|
95
|
-
splat:
|
96
|
-
dsplat:
|
97
|
-
blockarg:
|
95
|
+
splat: "*",
|
96
|
+
dsplat: "**",
|
97
|
+
blockarg: "&"
|
98
98
|
}.freeze
|
99
99
|
|
100
100
|
def convert_arguments(args)
|
101
|
-
args.
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
101
|
+
args.line ||= args.sexp_body.first&.line
|
102
|
+
args.sexp_body = args.sexp_body.map { |item| convert_argument item }
|
103
|
+
args
|
104
|
+
end
|
105
|
+
|
106
|
+
def convert_argument(item)
|
107
|
+
case item.sexp_type
|
108
|
+
when :lvar
|
109
|
+
item.last
|
110
|
+
when *SPECIAL_ARG_MARKER.keys
|
111
|
+
convert_marked_argument(item)
|
112
|
+
when :masgn
|
113
|
+
convert_masgn_argument(item)
|
114
|
+
else
|
115
|
+
item
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|