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.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/{README.rdoc → README.md} +17 -17
  3. data/Rakefile +3 -1
  4. data/lib/ripper_ruby_parser/{commenting_sexp_builder.rb → commenting_ripper_parser.rb} +22 -6
  5. data/lib/ripper_ruby_parser/parser.rb +3 -18
  6. data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +2 -1
  7. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +6 -10
  8. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +37 -60
  9. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +31 -25
  10. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +18 -8
  11. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +22 -18
  12. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +12 -23
  13. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +16 -8
  14. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +41 -15
  15. data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +40 -23
  16. data/lib/ripper_ruby_parser/sexp_processor.rb +38 -19
  17. data/lib/ripper_ruby_parser/version.rb +1 -1
  18. data/test/pt_testcase/pt_test.rb +15 -1
  19. data/test/test_helper.rb +6 -3
  20. data/test/unit/commenting_ripper_parser_test.rb +121 -0
  21. data/test/unit/parser_assignment_test.rb +23 -24
  22. data/test/unit/parser_blocks_test.rb +207 -35
  23. data/test/unit/parser_conditionals_test.rb +251 -9
  24. data/test/unit/parser_literals_test.rb +348 -8
  25. data/test/unit/parser_loops_test.rb +20 -21
  26. data/test/unit/parser_method_calls_test.rb +132 -8
  27. data/test/unit/parser_operators_test.rb +97 -7
  28. data/test/unit/parser_test.rb +631 -1231
  29. data/test/unit/sexp_processor_test.rb +26 -28
  30. metadata +28 -38
  31. 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
- s(:block, *statements)
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
- if val.sexp_type == :str
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
- inner = exp.shift
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
- ($2.ord & 0b1001_1111).chr
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
- make_until(process(cond), handle_statement_list(block), true)
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
- make_until(process(cond), process(block), check_at_start)
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
- make_while(process(cond), handle_statement_list(block), true)
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
- make_while(process(cond), process(block), check_at_start)
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
- s(:for, process(coll),
35
- s(:lasgn, process(var)[1]),
36
- handle_statement_list(block))
37
- end
38
-
39
- private
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
- def make_until(cond, block, check_at_start)
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
- call[3] = process(parens) unless parens.empty?
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, s(:arglist)) }
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
- s(:call, nil, method,
21
- handle_potentially_typeless_sexp_with_fallback_type(:arglist, arglist))
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
- s(:call, process(receiver), method,
29
- handle_potentially_typeless_sexp_with_fallback_type(:arglist, arguments))
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, s(:arglist)) }
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, s(:arglist)) }
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
- s(:defs, process(receiver),
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, in_method { process(body) })
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
- _, *args = exp.shift 3
67
+ _, left, right = exp.shift 3
57
68
 
58
- args.map! do |sub_exp|
59
- make_method_name_literal sub_exp
60
- end
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
- scope = in_method { process exp }
80
- block = scope[1]
81
- if block.length == 1
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
- scope
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
- if (marker = SPECIAL_ARG_MARKER[item.sexp_type])
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
- elsif item.sexp_type == :lvar
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
- "&&".to_sym => :and,
6
- "||".to_sym => :or,
5
+ :"&&" => :and,
6
+ :"||" => :or,
7
7
  :and => :and,
8
8
  :or => :or
9
9
  }
10
10
 
11
11
  UNARY_OPERATOR_MAP = {
12
- :"!" => :not,
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
- if left.sexp_type == :regexp_literal
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, process(s(:binary, left, mapped, right)))
25
+ s(:not, make_regexp_match_operator(mapped, left, right))
34
26
  elsif (mapped = BINARY_OPERATOR_MAP[op])
35
- rebalance_binary(s(mapped, process(left), process(right)))
27
+ make_boolean_operator(mapped, left, right)
36
28
  else
37
- s(:call, process(left), op, s(:arglist, process(right)))
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
- mapped = UNARY_OPERATOR_MAP[op]
45
- if mapped
46
- s(mapped, arg)
54
+ op = UNARY_OPERATOR_MAP[op] || op
55
+ if is_literal?(arg) && op != :!
56
+ s(:lit, arg[1].send(op))
47
57
  else
48
- if is_literal? arg
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))