ripper_ruby_parser 1.1.2 → 1.2.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 +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
|