ripper_ruby_parser 0.0.8 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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))
|