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
@@ -13,7 +13,7 @@ module RipperRubyParser
|
|
13
13
|
|
14
14
|
def handle_potentially_typeless_sexp_with_fallback_type type, exp
|
15
15
|
if exp.nil?
|
16
|
-
s()
|
16
|
+
s(type)
|
17
17
|
elsif exp.first.is_a? Symbol
|
18
18
|
process(exp)
|
19
19
|
else
|
@@ -23,14 +23,10 @@ module RipperRubyParser
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def handle_statement_list exp
|
27
|
-
statements = map_body exp
|
28
|
-
|
29
|
-
wrap_in_block(statements)
|
30
|
-
end
|
31
|
-
|
32
26
|
def extract_node_symbol_with_position exp
|
33
27
|
return nil if exp.nil?
|
28
|
+
return exp if exp.is_a? Symbol
|
29
|
+
|
34
30
|
_, ident, pos = exp.shift 3
|
35
31
|
return ident.to_sym, pos
|
36
32
|
end
|
@@ -61,6 +57,9 @@ module RipperRubyParser
|
|
61
57
|
_, args, splatarg = exp.shift 3
|
62
58
|
items = handle_potentially_typeless_sexp args
|
63
59
|
items << s(:splat, process(splatarg))
|
60
|
+
until exp.empty?
|
61
|
+
items << process(exp.shift)
|
62
|
+
end
|
64
63
|
items
|
65
64
|
end
|
66
65
|
|
@@ -81,10 +80,21 @@ module RipperRubyParser
|
|
81
80
|
when 1
|
82
81
|
statements.first
|
83
82
|
else
|
84
|
-
|
83
|
+
first = statements.shift
|
84
|
+
if first.sexp_type == :block
|
85
|
+
first.shift
|
86
|
+
s(:block, *first, *statements)
|
87
|
+
else
|
88
|
+
s(:block, first, *statements)
|
89
|
+
end
|
85
90
|
end
|
86
91
|
end
|
87
92
|
|
93
|
+
def safe_wrap_in_block statements
|
94
|
+
result = wrap_in_block statements
|
95
|
+
result ? result : s()
|
96
|
+
end
|
97
|
+
|
88
98
|
def handle_return_argument_list arglist
|
89
99
|
arglist = process(arglist)
|
90
100
|
args = arglist[1..-1]
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
module RipperRubyParser
|
2
3
|
module SexpHandlers
|
3
4
|
module Literals
|
@@ -21,17 +22,20 @@ module RipperRubyParser
|
|
21
22
|
def process_string_embexpr exp
|
22
23
|
_, list = exp.shift 2
|
23
24
|
val = process(list.first)
|
24
|
-
|
25
|
+
case val.sexp_type
|
26
|
+
when :str
|
25
27
|
val
|
28
|
+
when :void_stmt
|
29
|
+
s(:dstr, "", s(:evstr))
|
26
30
|
else
|
27
|
-
s(:evstr, val)
|
31
|
+
s(:dstr, "", s(:evstr, val))
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
35
|
def process_string_dvar exp
|
32
36
|
_, list = exp.shift 2
|
33
37
|
val = process(list)
|
34
|
-
s(:evstr, val)
|
38
|
+
s(:dstr, "", s(:evstr, val))
|
35
39
|
end
|
36
40
|
|
37
41
|
def process_string_concat exp
|
@@ -45,7 +49,7 @@ module RipperRubyParser
|
|
45
49
|
right
|
46
50
|
else # Expecting left.sexp_type == :dstr
|
47
51
|
_, first, *rest = right
|
48
|
-
left.push s(:str, first)
|
52
|
+
left.push s(:str, first) unless first.empty?
|
49
53
|
left.push(*rest)
|
50
54
|
left
|
51
55
|
end
|
@@ -109,20 +113,9 @@ module RipperRubyParser
|
|
109
113
|
private
|
110
114
|
|
111
115
|
def extract_string_parts exp
|
112
|
-
|
113
|
-
|
114
|
-
string = process(inner)
|
116
|
+
string = ""
|
115
117
|
rest = []
|
116
118
|
|
117
|
-
if string.nil?
|
118
|
-
string = ""
|
119
|
-
elsif string.sexp_type == :str
|
120
|
-
string = string[1]
|
121
|
-
else
|
122
|
-
rest << string
|
123
|
-
string = ""
|
124
|
-
end
|
125
|
-
|
126
119
|
until exp.empty? do
|
127
120
|
result = process(exp.shift)
|
128
121
|
rest << result
|
@@ -133,6 +126,8 @@ module RipperRubyParser
|
|
133
126
|
string += str[1]
|
134
127
|
end
|
135
128
|
|
129
|
+
rest = rest.map { |se| se.sexp_type == :dstr ? se.last : se }
|
130
|
+
|
136
131
|
return string, rest
|
137
132
|
end
|
138
133
|
|
@@ -170,8 +165,13 @@ module RipperRubyParser
|
|
170
165
|
[0-7]{1,3} | # octal character
|
171
166
|
x[0-9a-fA-F]{1,2} | # hex byte
|
172
167
|
u[0-9a-fA-F]{4} | # unicode character
|
168
|
+
M-\\C-. | # meta-ctrl
|
169
|
+
C-\\M-. | # ctrl-meta
|
170
|
+
M-\\c. | # meta-ctrl (shorthand)
|
171
|
+
c\\M-. | # ctrl-meta (shorthand)
|
173
172
|
C-. | # control (regular)
|
174
173
|
c. | # control (shorthand)
|
174
|
+
M-. | # meta
|
175
175
|
. # single-character
|
176
176
|
)/x) do
|
177
177
|
bare = $1
|
@@ -182,8 +182,12 @@ module RipperRubyParser
|
|
182
182
|
bare[1..-1].to_i(16).chr
|
183
183
|
when /^u/
|
184
184
|
bare[1..-1].to_i(16).chr(Encoding::UTF_8)
|
185
|
-
when /^(c|C-)(.)$/
|
186
|
-
($
|
185
|
+
when /^(?:c|C-)(.)$/
|
186
|
+
($1.ord & 0b1001_1111).chr
|
187
|
+
when /^M-(.)$/
|
188
|
+
($1.ord | 0b1000_0000).chr
|
189
|
+
when /^(?:M-\\C-|C-\\M-|M-\\c|c\\M-)(.)$/
|
190
|
+
($1.ord & 0b1001_1111 | 0b1000_0000).chr
|
187
191
|
when /^[0-7]+/
|
188
192
|
bare.to_i(8).chr
|
189
193
|
else
|
@@ -4,7 +4,7 @@ module RipperRubyParser
|
|
4
4
|
def process_until exp
|
5
5
|
_, cond, block = exp.shift 3
|
6
6
|
|
7
|
-
|
7
|
+
s(:until, process(cond), wrap_in_block(map_body(block)), true)
|
8
8
|
end
|
9
9
|
|
10
10
|
def process_until_mod exp
|
@@ -12,13 +12,13 @@ module RipperRubyParser
|
|
12
12
|
|
13
13
|
check_at_start = check_at_start?(block)
|
14
14
|
|
15
|
-
|
15
|
+
s(:until, process(cond), process(block), check_at_start)
|
16
16
|
end
|
17
17
|
|
18
18
|
def process_while exp
|
19
19
|
_, cond, block = exp.shift 3
|
20
20
|
|
21
|
-
|
21
|
+
s(:while, process(cond), wrap_in_block(map_body(block)), true)
|
22
22
|
end
|
23
23
|
|
24
24
|
def process_while_mod exp
|
@@ -26,33 +26,22 @@ module RipperRubyParser
|
|
26
26
|
|
27
27
|
check_at_start = check_at_start?(block)
|
28
28
|
|
29
|
-
|
29
|
+
s(:while, process(cond), process(block), check_at_start)
|
30
30
|
end
|
31
31
|
|
32
32
|
def process_for exp
|
33
33
|
_, var, coll, block = exp.shift 4
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def make_guarded_block(type, inverse, cond, block, check_at_start)
|
42
|
-
if cond.sexp_type == :not
|
43
|
-
type = inverse
|
44
|
-
cond = cond[1]
|
34
|
+
coll = process(coll)
|
35
|
+
assgn = s(:lasgn, process(var)[1])
|
36
|
+
block = wrap_in_block(map_body(block))
|
37
|
+
if block.nil?
|
38
|
+
s(:for, coll, assgn)
|
39
|
+
else
|
40
|
+
s(:for, coll, assgn, block)
|
45
41
|
end
|
46
|
-
s(type, cond, block, check_at_start)
|
47
42
|
end
|
48
43
|
|
49
|
-
|
50
|
-
make_guarded_block(:until, :while, cond, block, check_at_start)
|
51
|
-
end
|
52
|
-
|
53
|
-
def make_while(cond, block, check_at_start)
|
54
|
-
make_guarded_block(:while, :until, cond, block, check_at_start)
|
55
|
-
end
|
44
|
+
private
|
56
45
|
|
57
46
|
def check_at_start?(block)
|
58
47
|
block.sexp_type != :begin
|
@@ -4,42 +4,50 @@ module RipperRubyParser
|
|
4
4
|
def process_method_add_arg exp
|
5
5
|
_, call, parens = exp.shift 3
|
6
6
|
call = process(call)
|
7
|
-
|
7
|
+
unless parens.empty?
|
8
|
+
parens = process(parens)
|
9
|
+
parens.shift
|
10
|
+
end
|
11
|
+
parens.each do |arg|
|
12
|
+
call << arg
|
13
|
+
end
|
8
14
|
call
|
9
15
|
end
|
10
16
|
|
11
17
|
def process_call exp
|
12
18
|
_, receiver, _, ident = exp.shift 4
|
13
19
|
with_position_from_node_symbol(ident) {|method|
|
14
|
-
s(:call, process(receiver), method
|
20
|
+
s(:call, process(receiver), method) }
|
15
21
|
end
|
16
22
|
|
17
23
|
def process_command exp
|
18
24
|
_, ident, arglist = exp.shift 3
|
19
25
|
with_position_from_node_symbol(ident) {|method|
|
20
|
-
|
21
|
-
|
26
|
+
args = handle_potentially_typeless_sexp_with_fallback_type(:arglist, arglist)
|
27
|
+
args.shift
|
28
|
+
s(:call, nil, method, *args)
|
22
29
|
}
|
23
30
|
end
|
24
31
|
|
25
32
|
def process_command_call exp
|
26
33
|
_, receiver, _, ident, arguments = exp.shift 5
|
27
34
|
with_position_from_node_symbol(ident) {|method|
|
28
|
-
|
29
|
-
|
35
|
+
args = handle_potentially_typeless_sexp_with_fallback_type(:arglist, arguments)
|
36
|
+
args.shift
|
37
|
+
s(:call, process(receiver), method, *args)
|
30
38
|
}
|
31
39
|
end
|
32
40
|
|
33
41
|
def process_vcall exp
|
34
42
|
_, ident = exp.shift 2
|
35
43
|
with_position_from_node_symbol(ident) {|method|
|
36
|
-
s(:call, nil, method
|
44
|
+
s(:call, nil, method) }
|
37
45
|
end
|
38
46
|
|
39
47
|
def process_fcall exp
|
40
48
|
_, ident = exp.shift 2
|
41
49
|
with_position_from_node_symbol(ident) {|method|
|
42
|
-
s(:call, nil, method
|
50
|
+
s(:call, nil, method) }
|
43
51
|
end
|
44
52
|
|
45
53
|
def process_super exp
|
@@ -6,15 +6,26 @@ module RipperRubyParser
|
|
6
6
|
ident, pos = extract_node_symbol_with_position ident
|
7
7
|
params = convert_special_args(process(params))
|
8
8
|
with_position(pos,
|
9
|
-
s(:defn, ident, params, method_body(body)))
|
9
|
+
s(:defn, ident, params, *method_body(body)))
|
10
10
|
end
|
11
11
|
|
12
12
|
def process_defs exp
|
13
13
|
_, receiver, _, method, params, body = exp.shift 6
|
14
14
|
params = convert_special_args(process(params))
|
15
|
-
|
15
|
+
|
16
|
+
body = in_method do
|
17
|
+
process(body)
|
18
|
+
end
|
19
|
+
|
20
|
+
if body.length == 1 && body.first.sexp_type == :block
|
21
|
+
body = body.first
|
22
|
+
body.shift
|
23
|
+
end
|
24
|
+
|
25
|
+
s(:defs,
|
26
|
+
process(receiver),
|
16
27
|
extract_node_symbol(method),
|
17
|
-
params,
|
28
|
+
params, *body)
|
18
29
|
end
|
19
30
|
|
20
31
|
def process_return exp
|
@@ -53,13 +64,11 @@ module RipperRubyParser
|
|
53
64
|
end
|
54
65
|
|
55
66
|
def process_alias exp
|
56
|
-
_,
|
67
|
+
_, left, right = exp.shift 3
|
57
68
|
|
58
|
-
|
59
|
-
make_method_name_literal
|
60
|
-
|
61
|
-
|
62
|
-
s(:alias, *args)
|
69
|
+
s(:alias,
|
70
|
+
make_method_name_literal(left),
|
71
|
+
make_method_name_literal(right))
|
63
72
|
end
|
64
73
|
|
65
74
|
private
|
@@ -76,12 +85,17 @@ module RipperRubyParser
|
|
76
85
|
end
|
77
86
|
|
78
87
|
def method_body exp
|
79
|
-
|
80
|
-
block
|
81
|
-
|
88
|
+
block = in_method { process exp }
|
89
|
+
case block.length
|
90
|
+
when 0
|
82
91
|
block.push s(:nil)
|
92
|
+
when 1
|
93
|
+
if block.first.sexp_type == :block
|
94
|
+
block = block.first
|
95
|
+
block.shift
|
96
|
+
end
|
83
97
|
end
|
84
|
-
|
98
|
+
block
|
85
99
|
end
|
86
100
|
|
87
101
|
SPECIAL_ARG_MARKER = {
|
@@ -94,11 +108,23 @@ module RipperRubyParser
|
|
94
108
|
if item.is_a? Symbol
|
95
109
|
item
|
96
110
|
else
|
97
|
-
|
111
|
+
case item.sexp_type
|
112
|
+
when *SPECIAL_ARG_MARKER.keys
|
113
|
+
marker = SPECIAL_ARG_MARKER[item.sexp_type]
|
98
114
|
name = extract_node_symbol item[1]
|
99
115
|
:"#{marker}#{name}"
|
100
|
-
|
116
|
+
when :lvar
|
101
117
|
item[1]
|
118
|
+
when :masgn
|
119
|
+
args = item[1]
|
120
|
+
args.shift
|
121
|
+
s(:masgn, *convert_special_args(args))
|
122
|
+
when :lasgn
|
123
|
+
if item.length == 2
|
124
|
+
item[1]
|
125
|
+
else
|
126
|
+
item
|
127
|
+
end
|
102
128
|
else
|
103
129
|
item
|
104
130
|
end
|
@@ -2,54 +2,60 @@ module RipperRubyParser
|
|
2
2
|
module SexpHandlers
|
3
3
|
module Operators
|
4
4
|
BINARY_OPERATOR_MAP = {
|
5
|
-
"&&"
|
6
|
-
"||"
|
5
|
+
:"&&" => :and,
|
6
|
+
:"||" => :or,
|
7
7
|
:and => :and,
|
8
8
|
:or => :or
|
9
9
|
}
|
10
10
|
|
11
11
|
UNARY_OPERATOR_MAP = {
|
12
|
-
:
|
13
|
-
:not => :not
|
12
|
+
:not => :!
|
14
13
|
}
|
15
14
|
|
16
15
|
NEGATED_BINARY_OPERATOR_MAP = {
|
17
16
|
:"!~" => :=~,
|
18
|
-
:"!=" => :==
|
19
17
|
}
|
20
18
|
|
21
19
|
def process_binary exp
|
22
20
|
_, left, op, right = exp.shift 4
|
23
21
|
|
24
22
|
if op == :=~
|
25
|
-
|
26
|
-
s(:match2, process(left), process(right))
|
27
|
-
elsif right.sexp_type == :regexp_literal
|
28
|
-
s(:match3, process(right), process(left))
|
29
|
-
else
|
30
|
-
s(:call, process(left), op, s(:arglist, process(right)))
|
31
|
-
end
|
23
|
+
make_regexp_match_operator(op, left, right)
|
32
24
|
elsif (mapped = NEGATED_BINARY_OPERATOR_MAP[op])
|
33
|
-
s(:not,
|
25
|
+
s(:not, make_regexp_match_operator(mapped, left, right))
|
34
26
|
elsif (mapped = BINARY_OPERATOR_MAP[op])
|
35
|
-
|
27
|
+
make_boolean_operator(mapped, left, right)
|
36
28
|
else
|
37
|
-
s(:call, process(left), op,
|
29
|
+
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
|
+
else
|
47
|
+
s(:call, process(left), op, process(right))
|
38
48
|
end
|
39
49
|
end
|
40
50
|
|
41
51
|
def process_unary exp
|
42
52
|
_, op, arg = exp.shift 3
|
43
53
|
arg = process(arg)
|
44
|
-
|
45
|
-
if
|
46
|
-
s(
|
54
|
+
op = UNARY_OPERATOR_MAP[op] || op
|
55
|
+
if is_literal?(arg) && op != :!
|
56
|
+
s(:lit, arg[1].send(op))
|
47
57
|
else
|
48
|
-
|
49
|
-
s(:lit, arg[1].send(op))
|
50
|
-
else
|
51
|
-
s(:call, arg, op, s(:arglist))
|
52
|
-
end
|
58
|
+
s(:call, arg, op)
|
53
59
|
end
|
54
60
|
end
|
55
61
|
|
@@ -64,6 +70,17 @@ module RipperRubyParser
|
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
73
|
+
def process_dot3 exp
|
74
|
+
_, left, right = exp.shift 3
|
75
|
+
left = process(left)
|
76
|
+
right = process(right)
|
77
|
+
if is_literal?(left) && is_literal?(right)
|
78
|
+
s(:lit, Range.new(left[1], right[1], true))
|
79
|
+
else
|
80
|
+
s(:dot3, left, right)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
67
84
|
def process_ifop exp
|
68
85
|
_, cond, truepart, falsepart = exp.shift 4
|
69
86
|
s(:if, process(cond), process(truepart), process(falsepart))
|