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,11 +1,12 @@
|
|
1
1
|
module RipperRubyParser
|
2
2
|
module SexpHandlers
|
3
|
+
# Sexp handlers for operators
|
3
4
|
module Operators
|
4
5
|
BINARY_OPERATOR_MAP = {
|
5
|
-
:
|
6
|
-
:
|
7
|
-
:
|
8
|
-
:
|
6
|
+
'&&': :and,
|
7
|
+
'||': :or,
|
8
|
+
and: :and,
|
9
|
+
or: :or
|
9
10
|
}.freeze
|
10
11
|
|
11
12
|
UNARY_OPERATOR_MAP = {
|
@@ -13,10 +14,12 @@ module RipperRubyParser
|
|
13
14
|
}.freeze
|
14
15
|
|
15
16
|
NEGATED_BINARY_OPERATOR_MAP = {
|
16
|
-
:
|
17
|
+
'!~': :=~
|
17
18
|
}.freeze
|
18
19
|
|
19
|
-
|
20
|
+
SHIFT_OPERATORS = [:<<, :>>].freeze
|
21
|
+
|
22
|
+
def process_binary(exp)
|
20
23
|
_, left, op, right = exp.shift 4
|
21
24
|
|
22
25
|
if op == :=~
|
@@ -25,37 +28,21 @@ module RipperRubyParser
|
|
25
28
|
s(:not, make_regexp_match_operator(mapped, left, right))
|
26
29
|
elsif (mapped = BINARY_OPERATOR_MAP[op])
|
27
30
|
make_boolean_operator(mapped, left, right)
|
28
|
-
|
31
|
+
elsif SHIFT_OPERATORS.include? op
|
29
32
|
s(:call, process(left), op, process(right))
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def make_boolean_operator op, left, right
|
34
|
-
if left.first == :paren
|
35
|
-
s(op, process(left), process(right))
|
36
|
-
else
|
37
|
-
rebalance_binary(s(op, process(left), process(right)))
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def make_regexp_match_operator op, left, right
|
42
|
-
if left.sexp_type == :regexp_literal
|
43
|
-
s(:match2, process(left), process(right))
|
44
|
-
elsif right.sexp_type == :regexp_literal
|
45
|
-
s(:match3, process(right), process(left))
|
46
33
|
else
|
47
|
-
s(:call,
|
34
|
+
s(:call, handle_operator_argument(left), op, handle_operator_argument(right))
|
48
35
|
end
|
49
36
|
end
|
50
37
|
|
51
|
-
def process_unary
|
38
|
+
def process_unary(exp)
|
52
39
|
_, op, arg = exp.shift 3
|
53
|
-
arg =
|
40
|
+
arg = handle_operator_argument(arg)
|
54
41
|
op = UNARY_OPERATOR_MAP[op] || op
|
55
42
|
s(:call, arg, op)
|
56
43
|
end
|
57
44
|
|
58
|
-
def process_dot2
|
45
|
+
def process_dot2(exp)
|
59
46
|
_, left, right = exp.shift 3
|
60
47
|
left = process(left)
|
61
48
|
right = process(right)
|
@@ -66,7 +53,7 @@ module RipperRubyParser
|
|
66
53
|
end
|
67
54
|
end
|
68
55
|
|
69
|
-
def process_dot3
|
56
|
+
def process_dot3(exp)
|
70
57
|
_, left, right = exp.shift 3
|
71
58
|
left = process(left)
|
72
59
|
right = process(right)
|
@@ -77,20 +64,45 @@ module RipperRubyParser
|
|
77
64
|
end
|
78
65
|
end
|
79
66
|
|
80
|
-
def process_ifop
|
67
|
+
def process_ifop(exp)
|
81
68
|
_, cond, truepart, falsepart = exp.shift 4
|
82
|
-
s(:if,
|
69
|
+
s(:if,
|
70
|
+
handle_operator_argument(cond),
|
71
|
+
handle_operator_argument(truepart),
|
72
|
+
handle_operator_argument(falsepart))
|
83
73
|
end
|
84
74
|
|
85
75
|
private
|
86
76
|
|
87
|
-
def
|
88
|
-
|
77
|
+
def make_boolean_operator(op, left, right)
|
78
|
+
_, left, _, right = rebalance_binary(s(:binary, left, op, right))
|
79
|
+
s(op, process(left), handle_operator_argument(right))
|
80
|
+
end
|
81
|
+
|
82
|
+
def make_regexp_match_operator(op, left, right)
|
83
|
+
if left.sexp_type == :regexp_literal
|
84
|
+
s(:match2, process(left), process(right))
|
85
|
+
elsif right.sexp_type == :regexp_literal
|
86
|
+
s(:match3, process(right), process(left))
|
87
|
+
else
|
88
|
+
s(:call, process(left), op, process(right))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def rebalance_binary(exp)
|
93
|
+
_, left, op, right = exp
|
94
|
+
if left.sexp_type == :binary && BINARY_OPERATOR_MAP[op] == BINARY_OPERATOR_MAP[left[2]]
|
95
|
+
_, left, _, middle = rebalance_binary(left)
|
96
|
+
right = rebalance_binary(s(:binary, middle, op, right))
|
97
|
+
end
|
98
|
+
s(:binary, left, op, right)
|
99
|
+
end
|
89
100
|
|
90
|
-
|
91
|
-
|
101
|
+
def handle_operator_argument(exp)
|
102
|
+
if exp.sexp_type == :begin
|
103
|
+
s(:begin, process(exp))
|
92
104
|
else
|
93
|
-
|
105
|
+
process(exp)
|
94
106
|
end
|
95
107
|
end
|
96
108
|
end
|
@@ -3,12 +3,13 @@ require 'ripper_ruby_parser/sexp_handlers'
|
|
3
3
|
|
4
4
|
module RipperRubyParser
|
5
5
|
# Processes the sexp created by Ripper to what RubyParser would produce.
|
6
|
+
#
|
7
|
+
# @api private
|
6
8
|
class SexpProcessor < ::SexpProcessor
|
7
|
-
|
8
|
-
attr_accessor :extra_compatible
|
9
|
+
attr_reader :filename
|
9
10
|
|
10
|
-
def initialize
|
11
|
-
super
|
11
|
+
def initialize(filename: nil)
|
12
|
+
super()
|
12
13
|
|
13
14
|
# TODO: Find these automatically
|
14
15
|
|
@@ -28,36 +29,29 @@ module RipperRubyParser
|
|
28
29
|
|
29
30
|
@processors[:@tstring_content] = :process_at_tstring_content
|
30
31
|
|
32
|
+
@filename = filename
|
33
|
+
|
31
34
|
@errors = []
|
32
35
|
|
33
36
|
@in_method_body = false
|
34
37
|
end
|
35
38
|
|
36
|
-
def process exp
|
37
|
-
return nil if exp.nil?
|
38
|
-
|
39
|
-
result = super
|
40
|
-
trickle_up_line_numbers result
|
41
|
-
trickle_down_line_numbers result
|
42
|
-
end
|
43
|
-
|
44
39
|
include SexpHandlers
|
45
40
|
|
46
|
-
def process_program
|
41
|
+
def process_program(exp)
|
47
42
|
_, content = exp.shift 2
|
48
43
|
|
49
|
-
|
50
|
-
safe_wrap_in_block statements
|
44
|
+
process content
|
51
45
|
end
|
52
46
|
|
53
|
-
def process_module
|
47
|
+
def process_module(exp)
|
54
48
|
_, const_ref, body = exp.shift 3
|
55
49
|
const, line = const_ref_to_const_with_line_number const_ref
|
56
50
|
with_line_number(line,
|
57
51
|
s(:module, const, *class_or_module_body(body)))
|
58
52
|
end
|
59
53
|
|
60
|
-
def process_class
|
54
|
+
def process_class(exp)
|
61
55
|
_, const_ref, parent, body = exp.shift 4
|
62
56
|
const, line = const_ref_to_const_with_line_number const_ref
|
63
57
|
parent = process(parent)
|
@@ -65,125 +59,144 @@ module RipperRubyParser
|
|
65
59
|
s(:class, const, parent, *class_or_module_body(body)))
|
66
60
|
end
|
67
61
|
|
68
|
-
def process_sclass
|
62
|
+
def process_sclass(exp)
|
69
63
|
_, klass, block = exp.shift 3
|
70
64
|
s(:sclass, process(klass), *class_or_module_body(block))
|
71
65
|
end
|
72
66
|
|
73
|
-
def
|
67
|
+
def process_stmts(exp)
|
68
|
+
_, *statements = shift_all(exp)
|
69
|
+
statements = reject_void_stmt map_process_list statements
|
70
|
+
case statements.count
|
71
|
+
when 0
|
72
|
+
s(:void_stmt)
|
73
|
+
when 1
|
74
|
+
statements.first
|
75
|
+
else
|
76
|
+
first = statements.shift
|
77
|
+
if first.sexp_type == :block
|
78
|
+
first.shift
|
79
|
+
s(:block, *first, *statements)
|
80
|
+
else
|
81
|
+
s(:block, first, *statements)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def process_var_ref(exp)
|
74
87
|
_, contents = exp.shift 2
|
75
88
|
process(contents)
|
76
89
|
end
|
77
90
|
|
78
|
-
def process_var_field
|
91
|
+
def process_var_field(exp)
|
79
92
|
_, contents = exp.shift 2
|
80
93
|
process(contents)
|
81
94
|
end
|
82
95
|
|
83
|
-
def process_var_alias
|
96
|
+
def process_var_alias(exp)
|
84
97
|
_, left, right = exp.shift 3
|
85
98
|
s(:valias, left[1].to_sym, right[1].to_sym)
|
86
99
|
end
|
87
100
|
|
88
|
-
def process_const_path_ref
|
101
|
+
def process_const_path_ref(exp)
|
89
102
|
_, left, right = exp.shift 3
|
90
103
|
s(:colon2, process(left), extract_node_symbol(right))
|
91
104
|
end
|
92
105
|
|
93
|
-
def process_const_path_field
|
106
|
+
def process_const_path_field(exp)
|
94
107
|
s(:const, process_const_path_ref(exp))
|
95
108
|
end
|
96
109
|
|
97
|
-
def process_const_ref
|
110
|
+
def process_const_ref(exp)
|
98
111
|
_, ref = exp.shift 3
|
99
112
|
process(ref)
|
100
113
|
end
|
101
114
|
|
102
|
-
def process_top_const_ref
|
115
|
+
def process_top_const_ref(exp)
|
103
116
|
_, ref = exp.shift 2
|
104
117
|
s(:colon3, extract_node_symbol(ref))
|
105
118
|
end
|
106
119
|
|
107
|
-
def process_top_const_field
|
120
|
+
def process_top_const_field(exp)
|
108
121
|
s(:const, process_top_const_ref(exp))
|
109
122
|
end
|
110
123
|
|
111
|
-
def process_paren
|
124
|
+
def process_paren(exp)
|
112
125
|
_, body = exp.shift 2
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
process body
|
126
|
+
result = process body
|
127
|
+
if result.sexp_type == :void_stmt
|
128
|
+
s(:nil)
|
117
129
|
else
|
118
|
-
|
119
|
-
safe_wrap_in_block body
|
130
|
+
result
|
120
131
|
end
|
121
132
|
end
|
122
133
|
|
123
|
-
def process_comment
|
134
|
+
def process_comment(exp)
|
124
135
|
_, comment, inner = exp.shift 3
|
125
136
|
sexp = process(inner)
|
126
137
|
sexp.comments = comment
|
127
138
|
sexp
|
128
139
|
end
|
129
140
|
|
130
|
-
def process_BEGIN
|
141
|
+
def process_BEGIN(exp)
|
131
142
|
_, body = exp.shift 2
|
132
|
-
s(:iter, s(:preexe), s(:args), *
|
143
|
+
s(:iter, s(:preexe), s(:args), *map_process_sexp_body_compact(body))
|
133
144
|
end
|
134
145
|
|
135
|
-
def process_END
|
146
|
+
def process_END(exp)
|
136
147
|
_, body = exp.shift 2
|
137
|
-
s(:iter, s(:postexe), 0, *
|
148
|
+
s(:iter, s(:postexe), 0, *map_process_sexp_body_compact(body))
|
138
149
|
end
|
139
150
|
|
140
151
|
# number literals
|
141
|
-
def process_at_int
|
152
|
+
def process_at_int(exp)
|
142
153
|
make_literal(exp) { |val| Integer(val) }
|
143
154
|
end
|
144
155
|
|
145
|
-
def process_at_float
|
156
|
+
def process_at_float(exp)
|
146
157
|
make_literal(exp, &:to_f)
|
147
158
|
end
|
148
159
|
|
149
160
|
# character literals
|
150
|
-
def process_at_CHAR
|
161
|
+
def process_at_CHAR(exp)
|
151
162
|
_, val, pos = exp.shift 3
|
152
163
|
with_position(pos, s(:str, unescape(val[1..-1])))
|
153
164
|
end
|
154
165
|
|
155
|
-
def process_at_label
|
166
|
+
def process_at_label(exp)
|
156
167
|
make_literal(exp) { |val| val.chop.to_sym }
|
157
168
|
end
|
158
169
|
|
159
170
|
# symbol-like sexps
|
160
|
-
def process_at_const
|
171
|
+
def process_at_const(exp)
|
161
172
|
make_identifier(:const, exp)
|
162
173
|
end
|
163
174
|
|
164
|
-
def process_at_cvar
|
175
|
+
def process_at_cvar(exp)
|
165
176
|
make_identifier(:cvar, exp)
|
166
177
|
end
|
167
178
|
|
168
|
-
def process_at_gvar
|
179
|
+
def process_at_gvar(exp)
|
169
180
|
make_identifier(:gvar, exp)
|
170
181
|
end
|
171
182
|
|
172
|
-
def process_at_ivar
|
183
|
+
def process_at_ivar(exp)
|
173
184
|
make_identifier(:ivar, exp)
|
174
185
|
end
|
175
186
|
|
176
|
-
def process_at_ident
|
187
|
+
def process_at_ident(exp)
|
177
188
|
make_identifier(:lvar, exp)
|
178
189
|
end
|
179
190
|
|
180
|
-
def process_at_op
|
191
|
+
def process_at_op(exp)
|
181
192
|
make_identifier(:op, exp)
|
182
193
|
end
|
183
194
|
|
184
|
-
def process_at_kw
|
195
|
+
def process_at_kw(exp)
|
185
196
|
sym, pos = extract_node_symbol_with_position(exp)
|
186
197
|
result = case sym
|
198
|
+
when :__ENCODING__
|
199
|
+
s(:colon2, s(:const, :Encoding), :UTF_8)
|
187
200
|
when :__FILE__
|
188
201
|
s(:str, @filename)
|
189
202
|
when :__LINE__
|
@@ -194,7 +207,7 @@ module RipperRubyParser
|
|
194
207
|
with_position(pos, result)
|
195
208
|
end
|
196
209
|
|
197
|
-
def process_at_backref
|
210
|
+
def process_at_backref(exp)
|
198
211
|
_, str, pos = exp.shift 3
|
199
212
|
name = str[1..-1]
|
200
213
|
with_position pos do
|
@@ -208,59 +221,33 @@ module RipperRubyParser
|
|
208
221
|
|
209
222
|
private
|
210
223
|
|
211
|
-
def const_ref_to_const_with_line_number
|
224
|
+
def const_ref_to_const_with_line_number(const_ref)
|
212
225
|
const = process(const_ref)
|
213
226
|
line = const.line
|
214
227
|
const = const[1] if const.sexp_type == :const
|
215
228
|
return const, line
|
216
229
|
end
|
217
230
|
|
218
|
-
def class_or_module_body
|
231
|
+
def class_or_module_body(exp)
|
219
232
|
body = process(exp)
|
220
233
|
|
221
|
-
|
222
|
-
|
223
|
-
body.
|
234
|
+
return body if body.empty?
|
235
|
+
if body.sexp_type == :block
|
236
|
+
body.sexp_body
|
237
|
+
else
|
238
|
+
[body]
|
224
239
|
end
|
225
|
-
|
226
|
-
body
|
227
240
|
end
|
228
241
|
|
229
|
-
def make_identifier
|
242
|
+
def make_identifier(type, exp)
|
230
243
|
with_position_from_node_symbol(exp) do |ident|
|
231
244
|
s(type, ident)
|
232
245
|
end
|
233
246
|
end
|
234
247
|
|
235
|
-
def make_literal
|
248
|
+
def make_literal(exp)
|
236
249
|
_, val, pos = exp.shift 3
|
237
250
|
with_position(pos, s(:lit, yield(val)))
|
238
251
|
end
|
239
|
-
|
240
|
-
def trickle_up_line_numbers exp
|
241
|
-
exp.each do |sub_exp|
|
242
|
-
if sub_exp.is_a? Sexp
|
243
|
-
trickle_up_line_numbers sub_exp
|
244
|
-
exp.line ||= sub_exp.line
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def trickle_down_line_numbers exp
|
250
|
-
exp.each do |sub_exp|
|
251
|
-
if sub_exp.is_a? Sexp
|
252
|
-
sub_exp.line ||= exp.line
|
253
|
-
trickle_down_line_numbers sub_exp
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
def convert_void_stmt_to_nil sexp
|
259
|
-
if sexp == s(:void_stmt)
|
260
|
-
s(:nil)
|
261
|
-
else
|
262
|
-
sexp
|
263
|
-
end
|
264
|
-
end
|
265
252
|
end
|
266
253
|
end
|