ripper_ruby_parser 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +19 -0
- data/README.md +2 -2
- data/Rakefile +1 -1
- data/lib/ripper_ruby_parser.rb +0 -7
- data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +112 -34
- data/lib/ripper_ruby_parser/parser.rb +26 -12
- data/lib/ripper_ruby_parser/sexp_handlers.rb +4 -1
- data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +7 -6
- data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +4 -2
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +39 -43
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +93 -69
- data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +30 -24
- data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +7 -9
- data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +51 -71
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +72 -56
- data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +14 -13
- data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +19 -13
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +19 -22
- data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +47 -35
- data/lib/ripper_ruby_parser/sexp_processor.rb +72 -85
- data/lib/ripper_ruby_parser/version.rb +1 -1
- data/test/end_to_end/line_numbering_test.rb +1 -1
- data/test/end_to_end/samples_comparison_test.rb +0 -1
- data/test/pt_testcase/pt_test.rb +4 -6
- data/test/{unit → ripper_ruby_parser}/commenting_ripper_parser_test.rb +82 -25
- data/test/{unit → ripper_ruby_parser}/parser_test.rb +37 -170
- data/test/{unit/parser_assignment_test.rb → ripper_ruby_parser/sexp_handlers/assignment_test.rb} +1 -1
- data/test/{unit/parser_blocks_test.rb → ripper_ruby_parser/sexp_handlers/blocks_test.rb} +267 -2
- data/test/{unit/parser_conditionals_test.rb → ripper_ruby_parser/sexp_handlers/conditionals_test.rb} +125 -17
- data/test/{unit/parser_literals_test.rb → ripper_ruby_parser/sexp_handlers/literals_test.rb} +10 -12
- data/test/{unit/parser_loops_test.rb → ripper_ruby_parser/sexp_handlers/loops_test.rb} +1 -1
- data/test/{unit/parser_method_calls_test.rb → ripper_ruby_parser/sexp_handlers/method_calls_test.rb} +10 -10
- data/test/{unit/parser_operators_test.rb → ripper_ruby_parser/sexp_handlers/operators_test.rb} +22 -2
- data/test/{unit → ripper_ruby_parser}/sexp_processor_test.rb +49 -48
- data/test/{unit → ripper_ruby_parser}/version_test.rb +0 -0
- data/test/samples/misc.rb +4 -0
- data/test/test_helper.rb +4 -4
- metadata +28 -42
- data/test/end_to_end/error_conditions_test.rb +0 -51
@@ -1,14 +1,13 @@
|
|
1
1
|
module RipperRubyParser
|
2
2
|
module SexpHandlers
|
3
|
+
# Sexp handlers for literals, except hash and array literals
|
3
4
|
module Literals
|
4
|
-
def process_string_literal
|
5
|
+
def process_string_literal(exp)
|
5
6
|
_, content = exp.shift 2
|
6
7
|
process(content)
|
7
8
|
end
|
8
9
|
|
9
|
-
def process_string_content
|
10
|
-
exp.shift
|
11
|
-
|
10
|
+
def process_string_content(exp)
|
12
11
|
string, rest = extract_unescaped_string_parts exp
|
13
12
|
|
14
13
|
if rest.empty?
|
@@ -18,9 +17,13 @@ module RipperRubyParser
|
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
|
20
|
+
alias process_word process_string_content
|
21
|
+
|
22
|
+
def process_string_embexpr(exp)
|
22
23
|
_, list = exp.shift 2
|
23
|
-
|
24
|
+
|
25
|
+
val = process(list.sexp_body.first)
|
26
|
+
|
24
27
|
case val.sexp_type
|
25
28
|
when :str
|
26
29
|
val
|
@@ -31,30 +34,26 @@ module RipperRubyParser
|
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
34
|
-
def process_string_dvar
|
37
|
+
def process_string_dvar(exp)
|
35
38
|
_, list = exp.shift 2
|
36
39
|
val = process(list)
|
37
40
|
s(:dstr, '', s(:evstr, val))
|
38
41
|
end
|
39
42
|
|
40
|
-
def process_string_concat
|
43
|
+
def process_string_concat(exp)
|
41
44
|
_, left, right = exp.shift 3
|
42
45
|
|
43
46
|
left = process(left)
|
44
47
|
right = process(right)
|
45
48
|
|
46
49
|
if left.sexp_type == :str
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
_, first, *rest = right
|
51
|
-
left.push s(:str, first) if !first.empty? || rest.empty?
|
52
|
-
left.push(*rest)
|
53
|
-
left
|
50
|
+
merge_left_into_right(left, right)
|
51
|
+
else
|
52
|
+
merge_right_into_left(left, right)
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
def process_xstring_literal
|
56
|
+
def process_xstring_literal(exp)
|
58
57
|
_, content = exp.shift 2
|
59
58
|
string, rest = extract_unescaped_string_parts content
|
60
59
|
if rest.empty?
|
@@ -64,8 +63,8 @@ module RipperRubyParser
|
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
67
|
-
def process_regexp_literal
|
68
|
-
_, content, (_, flags,
|
66
|
+
def process_regexp_literal(exp)
|
67
|
+
_, content, (_, flags,) = exp.shift 3
|
69
68
|
|
70
69
|
string, rest = extract_string_parts content
|
71
70
|
numflags = character_flags_to_numerical flags
|
@@ -83,39 +82,41 @@ module RipperRubyParser
|
|
83
82
|
end
|
84
83
|
end
|
85
84
|
|
86
|
-
def process_symbol_literal
|
85
|
+
def process_symbol_literal(exp)
|
87
86
|
_, symbol = exp.shift 2
|
88
87
|
process(symbol)
|
89
88
|
end
|
90
89
|
|
91
|
-
def process_symbol
|
90
|
+
def process_symbol(exp)
|
92
91
|
_, node = exp.shift 2
|
93
|
-
|
92
|
+
handle_symbol_content(node)
|
94
93
|
end
|
95
94
|
|
96
|
-
def process_dyna_symbol
|
97
|
-
_,
|
95
|
+
def process_dyna_symbol(exp)
|
96
|
+
_, node = exp.shift 2
|
97
|
+
handle_dyna_symbol_content(node)
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
end
|
104
|
-
if rest.empty?
|
105
|
-
s(:lit, string.to_sym)
|
106
|
-
else
|
107
|
-
s(:dsym, string, *rest)
|
108
|
-
end
|
100
|
+
def process_qsymbols(exp)
|
101
|
+
_, *items = shift_all(exp)
|
102
|
+
items = items.map { |item| handle_symbol_content(item) }
|
103
|
+
s(:qsymbols, *items)
|
109
104
|
end
|
110
105
|
|
111
|
-
def
|
112
|
-
_,
|
106
|
+
def process_symbols(exp)
|
107
|
+
_, *items = shift_all(exp)
|
108
|
+
items = items.map { |item| handle_dyna_symbol_content(item) }
|
109
|
+
s(:symbols, *items)
|
110
|
+
end
|
111
|
+
|
112
|
+
def process_at_tstring_content(exp)
|
113
|
+
_, string, = exp.shift 3
|
113
114
|
s(:str, string)
|
114
115
|
end
|
115
116
|
|
116
117
|
private
|
117
118
|
|
118
|
-
def extract_string_parts
|
119
|
+
def extract_string_parts(exp)
|
119
120
|
parts = internal_process_string_parts(exp)
|
120
121
|
|
121
122
|
string = ''
|
@@ -129,31 +130,18 @@ module RipperRubyParser
|
|
129
130
|
return string, rest
|
130
131
|
end
|
131
132
|
|
132
|
-
def internal_process_string_parts
|
133
|
-
rest =
|
134
|
-
|
135
|
-
until exp.empty?
|
136
|
-
part = exp.shift
|
137
|
-
result = if part.is_a? String
|
138
|
-
# FIXME: Extract escaping into separate method
|
139
|
-
s(:str, part.inspect[1..-2])
|
140
|
-
else
|
141
|
-
process(part)
|
142
|
-
end
|
143
|
-
rest << result
|
144
|
-
end
|
145
|
-
rest
|
133
|
+
def internal_process_string_parts(exp)
|
134
|
+
_, *rest = shift_all exp
|
135
|
+
map_process_list rest
|
146
136
|
end
|
147
137
|
|
148
|
-
def extract_unescaped_string_parts
|
138
|
+
def extract_unescaped_string_parts(exp)
|
149
139
|
string, rest = extract_string_parts exp
|
150
140
|
|
151
141
|
string = unescape(string)
|
152
142
|
|
153
143
|
rest.each do |sub_exp|
|
154
|
-
if sub_exp.sexp_type == :str
|
155
|
-
sub_exp[1] = unescape(sub_exp[1])
|
156
|
-
end
|
144
|
+
sub_exp[1] = unescape(sub_exp[1]) if sub_exp.sexp_type == :str
|
157
145
|
end
|
158
146
|
|
159
147
|
return string, rest
|
@@ -174,7 +162,7 @@ module RipperRubyParser
|
|
174
162
|
SINGLE_LETTER_ESCAPES_REGEXP =
|
175
163
|
Regexp.new("^[#{SINGLE_LETTER_ESCAPES.keys.join}]$")
|
176
164
|
|
177
|
-
def unescape
|
165
|
+
def unescape(string)
|
178
166
|
string.gsub(/\\(
|
179
167
|
[0-7]{1,3} | # octal character
|
180
168
|
x[0-9a-fA-F]{1,2} | # hex byte
|
@@ -210,7 +198,7 @@ module RipperRubyParser
|
|
210
198
|
end
|
211
199
|
end
|
212
200
|
|
213
|
-
def character_flags_to_numerical
|
201
|
+
def character_flags_to_numerical(flags)
|
214
202
|
numflags = 0
|
215
203
|
|
216
204
|
flags =~ /m/ and numflags |= Regexp::MULTILINE
|
@@ -222,6 +210,34 @@ module RipperRubyParser
|
|
222
210
|
|
223
211
|
numflags
|
224
212
|
end
|
213
|
+
|
214
|
+
def handle_dyna_symbol_content(list)
|
215
|
+
string, rest = extract_unescaped_string_parts list
|
216
|
+
if rest.empty?
|
217
|
+
s(:lit, string.to_sym)
|
218
|
+
else
|
219
|
+
s(:dsym, string, *rest)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def handle_symbol_content(node)
|
224
|
+
with_position_from_node_symbol(node) { |sym| s(:lit, sym) }
|
225
|
+
end
|
226
|
+
|
227
|
+
def merge_left_into_right(left, right)
|
228
|
+
right[1] = left[1] + right[1]
|
229
|
+
right
|
230
|
+
end
|
231
|
+
|
232
|
+
def merge_right_into_left(left, right)
|
233
|
+
if right.sexp_type == :str
|
234
|
+
left.push right
|
235
|
+
else
|
236
|
+
_, first, *rest = right
|
237
|
+
left.push s(:str, first) unless first.empty?
|
238
|
+
left.push(*rest)
|
239
|
+
end
|
240
|
+
end
|
225
241
|
end
|
226
242
|
end
|
227
243
|
end
|
@@ -1,50 +1,51 @@
|
|
1
1
|
module RipperRubyParser
|
2
2
|
module SexpHandlers
|
3
|
+
# Sexp handlers for loops
|
3
4
|
module Loops
|
4
|
-
def process_until
|
5
|
+
def process_until(exp)
|
5
6
|
handle_conditional_loop :until, :while, exp
|
6
7
|
end
|
7
8
|
|
8
|
-
def process_until_mod
|
9
|
+
def process_until_mod(exp)
|
9
10
|
handle_conditional_loop_mod :until, :while, exp
|
10
11
|
end
|
11
12
|
|
12
|
-
def process_while
|
13
|
+
def process_while(exp)
|
13
14
|
handle_conditional_loop :while, :until, exp
|
14
15
|
end
|
15
16
|
|
16
|
-
def process_while_mod
|
17
|
+
def process_while_mod(exp)
|
17
18
|
handle_conditional_loop_mod :while, :until, exp
|
18
19
|
end
|
19
20
|
|
20
|
-
def process_for
|
21
|
+
def process_for(exp)
|
21
22
|
_, var, coll, block = exp.shift 4
|
22
23
|
coll = process(coll)
|
23
24
|
assgn = s(:lasgn, process(var)[1])
|
24
|
-
block =
|
25
|
-
if block
|
26
|
-
s(:for, coll, assgn)
|
27
|
-
else
|
25
|
+
block = unwrap_nil process(block)
|
26
|
+
if block
|
28
27
|
s(:for, coll, assgn, block)
|
28
|
+
else
|
29
|
+
s(:for, coll, assgn)
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
33
|
private
|
33
34
|
|
34
|
-
def check_at_start?
|
35
|
+
def check_at_start?(block)
|
35
36
|
block.sexp_type != :begin
|
36
37
|
end
|
37
38
|
|
38
|
-
def handle_conditional_loop
|
39
|
+
def handle_conditional_loop(type, negated_type, exp)
|
39
40
|
_, cond, body = exp.shift 3
|
40
41
|
|
41
42
|
construct_conditional_loop(type, negated_type,
|
42
43
|
process(cond),
|
43
|
-
|
44
|
+
unwrap_nil(process(body)),
|
44
45
|
true)
|
45
46
|
end
|
46
47
|
|
47
|
-
def handle_conditional_loop_mod
|
48
|
+
def handle_conditional_loop_mod(type, negated_type, exp)
|
48
49
|
_, cond, body = exp.shift 3
|
49
50
|
|
50
51
|
check_at_start = check_at_start?(body)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module RipperRubyParser
|
2
2
|
module SexpHandlers
|
3
|
+
# Sexp handlers for method calls
|
3
4
|
module MethodCalls
|
4
|
-
def process_method_add_arg
|
5
|
+
def process_method_add_arg(exp)
|
5
6
|
_, call, parens = exp.shift 3
|
6
7
|
call = process(call)
|
7
8
|
unless parens.empty?
|
@@ -15,20 +16,25 @@ module RipperRubyParser
|
|
15
16
|
end
|
16
17
|
|
17
18
|
CALL_OP_MAP = {
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
}
|
19
|
+
'.': :call,
|
20
|
+
'::': :call,
|
21
|
+
'&.': :safe_call
|
22
|
+
}.freeze
|
22
23
|
|
23
|
-
def process_call
|
24
|
+
def process_call(exp)
|
24
25
|
_, receiver, op, ident = exp.shift 4
|
25
26
|
type = CALL_OP_MAP.fetch op
|
26
|
-
|
27
|
-
|
27
|
+
case ident
|
28
|
+
when :call
|
29
|
+
s(type, process(receiver), :call)
|
30
|
+
else
|
31
|
+
with_position_from_node_symbol(ident) do |method|
|
32
|
+
s(type, process(receiver), method)
|
33
|
+
end
|
28
34
|
end
|
29
35
|
end
|
30
36
|
|
31
|
-
def process_command
|
37
|
+
def process_command(exp)
|
32
38
|
_, ident, arglist = exp.shift 3
|
33
39
|
with_position_from_node_symbol(ident) do |method|
|
34
40
|
args = handle_argument_list(arglist)
|
@@ -36,7 +42,7 @@ module RipperRubyParser
|
|
36
42
|
end
|
37
43
|
end
|
38
44
|
|
39
|
-
def process_command_call
|
45
|
+
def process_command_call(exp)
|
40
46
|
_, receiver, op, ident, arguments = exp.shift 5
|
41
47
|
type = CALL_OP_MAP.fetch op
|
42
48
|
with_position_from_node_symbol(ident) do |method|
|
@@ -45,21 +51,21 @@ module RipperRubyParser
|
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
48
|
-
def process_vcall
|
54
|
+
def process_vcall(exp)
|
49
55
|
_, ident = exp.shift 2
|
50
56
|
with_position_from_node_symbol(ident) do |method|
|
51
57
|
s(:call, nil, method)
|
52
58
|
end
|
53
59
|
end
|
54
60
|
|
55
|
-
def process_fcall
|
61
|
+
def process_fcall(exp)
|
56
62
|
_, ident = exp.shift 2
|
57
63
|
with_position_from_node_symbol(ident) do |method|
|
58
64
|
s(:call, nil, method)
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
|
-
def process_super
|
68
|
+
def process_super(exp)
|
63
69
|
_, args = exp.shift 2
|
64
70
|
args = process(args)
|
65
71
|
args.shift
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module RipperRubyParser
|
2
2
|
module SexpHandlers
|
3
|
+
# Sexp handers for method definitions and related constructs
|
3
4
|
module Methods
|
4
|
-
def process_def
|
5
|
+
def process_def(exp)
|
5
6
|
_, ident, params, body = exp.shift 4
|
6
7
|
ident, pos = extract_node_symbol_with_position ident
|
7
8
|
params = convert_special_args(process(params))
|
@@ -9,7 +10,7 @@ module RipperRubyParser
|
|
9
10
|
s(:defn, ident, params, *method_body(body)))
|
10
11
|
end
|
11
12
|
|
12
|
-
def process_defs
|
13
|
+
def process_defs(exp)
|
13
14
|
_, receiver, _, method, params, body = exp.shift 6
|
14
15
|
params = convert_special_args(process(params))
|
15
16
|
|
@@ -19,31 +20,27 @@ module RipperRubyParser
|
|
19
20
|
params, *method_body(body))
|
20
21
|
end
|
21
22
|
|
22
|
-
def process_return
|
23
|
+
def process_return(exp)
|
23
24
|
_, arglist = exp.shift 2
|
24
25
|
s(:return, handle_return_argument_list(arglist))
|
25
26
|
end
|
26
27
|
|
27
|
-
def process_return0
|
28
|
+
def process_return0(exp)
|
28
29
|
_ = exp.shift
|
29
30
|
s(:return)
|
30
31
|
end
|
31
32
|
|
32
|
-
def process_yield
|
33
|
+
def process_yield(exp)
|
33
34
|
_, arglist = exp.shift 2
|
34
|
-
|
35
|
-
if args.sexp_type == :arglist
|
36
|
-
args = args[1..-1]
|
37
|
-
end
|
38
|
-
s(:yield, *args)
|
35
|
+
s(:yield, *handle_argument_list(arglist))
|
39
36
|
end
|
40
37
|
|
41
|
-
def process_yield0
|
38
|
+
def process_yield0(exp)
|
42
39
|
_ = exp.shift
|
43
40
|
s(:yield)
|
44
41
|
end
|
45
42
|
|
46
|
-
def process_undef
|
43
|
+
def process_undef(exp)
|
47
44
|
_, args = exp.shift 2
|
48
45
|
|
49
46
|
args.map! do |sub_exp|
|
@@ -57,7 +54,7 @@ module RipperRubyParser
|
|
57
54
|
end
|
58
55
|
end
|
59
56
|
|
60
|
-
def process_alias
|
57
|
+
def process_alias(exp)
|
61
58
|
_, left, right = exp.shift 3
|
62
59
|
|
63
60
|
s(:alias,
|
@@ -74,22 +71,22 @@ module RipperRubyParser
|
|
74
71
|
result
|
75
72
|
end
|
76
73
|
|
77
|
-
def make_method_name_literal
|
74
|
+
def make_method_name_literal(exp)
|
78
75
|
process(exp).tap { |it| it[0] = :lit }
|
79
76
|
end
|
80
77
|
|
81
|
-
def method_body
|
78
|
+
def method_body(exp)
|
82
79
|
block = in_method { process exp }
|
83
80
|
case block.length
|
84
81
|
when 0
|
85
|
-
|
86
|
-
|
87
|
-
if block.
|
88
|
-
block
|
89
|
-
|
82
|
+
[s(:nil)]
|
83
|
+
else
|
84
|
+
if block.sexp_type == :block
|
85
|
+
block.sexp_body
|
86
|
+
else
|
87
|
+
[block]
|
90
88
|
end
|
91
89
|
end
|
92
|
-
block
|
93
90
|
end
|
94
91
|
|
95
92
|
SPECIAL_ARG_MARKER = {
|
@@ -98,7 +95,7 @@ module RipperRubyParser
|
|
98
95
|
blockarg: '&'
|
99
96
|
}.freeze
|
100
97
|
|
101
|
-
def convert_special_args
|
98
|
+
def convert_special_args(args)
|
102
99
|
args.map! do |item|
|
103
100
|
if item.is_a? Symbol
|
104
101
|
item
|