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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12102f722ef4074c0f6d46d207dba7dac580d0af
4
+ data.tar.gz: edf3dc287249ae2f0ccedb39e2f3cfdae622daff
5
+ SHA512:
6
+ metadata.gz: 9450f761539fbf3b3d662447497ef1fa7a220a02e9656139bb35d305863cde02a1364b9c9802dcd20883a0c6be16f7d8e80aa4529409445bf280d07e5d4a29fb
7
+ data.tar.gz: 231ced88a63860467aa18a66c37513b49e232dc9aff74c03d6ba6b7b1ac5d30bf284616ec50d05e38385b66237c3086cb78fe526aeae648b6dd1f4a8dda8a85b
@@ -1,38 +1,38 @@
1
- = RipperRubyParser
1
+ # RipperRubyParser
2
2
 
3
3
  by Matijs van Zuijlen
4
4
 
5
5
  http://www.github.com/mvz/ripper_ruby_parser
6
6
 
7
- == Description
7
+ ## Description
8
8
 
9
9
  Parse with Ripper, produce sexps that are compatible with RubyParser.
10
10
 
11
- == Features/Notes
11
+ ## Features/Notes
12
12
 
13
13
  * Drop-in replacement for RubyParser.
14
- * Should handle 1.9 syntax gracefully.
15
- * Needs MRI 1.9.3.
14
+ * Should handle 1.9 and later syntax gracefully.
15
+ * Needs MRI 1.9.3 or higher
16
16
 
17
- == Install
17
+ ## Install
18
18
 
19
19
  * gem install ripper_ruby_parser
20
20
 
21
- == Synopsis
21
+ ## Synopsis
22
22
 
23
- require 'ripper_ruby_parser'
23
+ require 'ripper_ruby_parser'
24
24
 
25
- parser = RipperRubyParser::Parser.new
26
- result = parser.parse "puts 'Hello World'"
27
- p result
28
- # => s(:call, nil, :puts, s(:arglist, s(:str, "Hello World!")))
25
+ parser = RipperRubyParser::Parser.new
26
+ result = parser.parse "puts 'Hello World'"
27
+ p result
28
+ # => s(:call, nil, :puts, s(:arglist, s(:str, "Hello World!")))
29
29
 
30
- == Requirements
30
+ ## Requirements
31
31
 
32
- * Ruby 1.9.3.
32
+ * Ruby 1.9.3 or higher
33
33
  * sexp_processor
34
34
 
35
- == Hacking and contributing
35
+ ## Hacking and contributing
36
36
 
37
37
  If you want to send pull requests or patches, please:
38
38
 
@@ -45,11 +45,11 @@ If you want to send pull requests or patches, please:
45
45
  * Try not to include changes that are irrelevant to your feature in the
46
46
  same commit.
47
47
 
48
- == License
48
+ ## License
49
49
 
50
50
  (The MIT License)
51
51
 
52
- Copyright (c) 2012 Matijs van Zuijlen
52
+ Copyright (c) 2012, 2014 Matijs van Zuijlen
53
53
 
54
54
  Permission is hereby granted, free of charge, to any person obtaining
55
55
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ require 'rake/clean'
2
+ require "bundler/gem_tasks"
1
3
  require 'rake/testtask'
2
4
 
3
5
  namespace :test do
@@ -20,7 +22,7 @@ namespace :test do
20
22
  t.warning = true
21
23
  end
22
24
 
23
- task :run => [:unit, :end_to_end]
25
+ task :run => [:unit, :end_to_end, :pt_testcase]
24
26
  end
25
27
 
26
28
  desc 'Alias to test:run'
@@ -2,7 +2,9 @@ require 'ripper'
2
2
  require 'ripper_ruby_parser/syntax_error'
3
3
 
4
4
  module RipperRubyParser
5
- class CommentingSexpBuilder < Ripper::SexpBuilderPP
5
+ # Variant of Ripper's SexpBuilderPP parser class that inserts comments as
6
+ # Sexps into the built parse tree.
7
+ class CommentingRipperParser < Ripper::SexpBuilderPP
6
8
  def initialize *args
7
9
  super
8
10
  @comment = nil
@@ -10,6 +12,13 @@ module RipperRubyParser
10
12
  @in_symbol = false
11
13
  end
12
14
 
15
+ def parse
16
+ result = suppress_warnings { super }
17
+ raise "Ripper parse failed." unless result
18
+
19
+ Sexp.from_array(result)
20
+ end
21
+
13
22
  def on_comment tok
14
23
  @comment ||= ""
15
24
  @comment += tok
@@ -92,14 +101,21 @@ module RipperRubyParser
92
101
  def commentize name, exp
93
102
  raise "Comment stack empty in #{name} event" if @comment_stack.empty?
94
103
  tok, comment = @comment_stack.pop
104
+ @comment = nil
95
105
  unless tok == name
96
106
  raise "Expected on_#{tok} event, got on_#{name}"
97
107
  end
98
- if comment.nil?
99
- [:comment, "", exp]
100
- else
101
- [:comment, comment, exp]
102
- end
108
+ [:comment, comment || "", exp]
109
+ end
110
+
111
+ private
112
+
113
+ def suppress_warnings
114
+ old_verbose = $VERBOSE
115
+ $VERBOSE = nil
116
+ result = yield
117
+ $VERBOSE = old_verbose
118
+ result
103
119
  end
104
120
  end
105
121
  end
@@ -1,4 +1,4 @@
1
- require 'ripper_ruby_parser/commenting_sexp_builder'
1
+ require 'ripper_ruby_parser/commenting_ripper_parser'
2
2
  require 'ripper_ruby_parser/sexp_processor'
3
3
 
4
4
  module RipperRubyParser
@@ -13,13 +13,8 @@ module RipperRubyParser
13
13
  end
14
14
 
15
15
  def parse source, filename='(string)', lineno=1
16
- # FIXME: Allow parser class to be passed to #initialize also.
17
- parser = CommentingSexpBuilder.new(source, filename, lineno)
18
-
19
- result = suppress_warnings { parser.parse }
20
- raise "Ripper parse failed." if result.nil?
21
-
22
- exp = Sexp.from_array(result)
16
+ parser = CommentingRipperParser.new(source, filename, lineno)
17
+ exp = parser.parse
23
18
 
24
19
  @processor.filename = filename
25
20
  @processor.extra_compatible = extra_compatible
@@ -31,16 +26,6 @@ module RipperRubyParser
31
26
  result
32
27
  end
33
28
  end
34
-
35
- private
36
-
37
- def suppress_warnings
38
- old_verbose = $VERBOSE
39
- $VERBOSE = nil
40
- result = yield
41
- $VERBOSE = old_verbose
42
- result
43
- end
44
29
  end
45
30
  end
46
31
 
@@ -13,7 +13,8 @@ module RipperRubyParser
13
13
  coll = nil if coll == s(:self)
14
14
 
15
15
  idx = process(idx) || s(:arglist)
16
- s(:call, coll, :[], idx)
16
+ idx.shift
17
+ s(:call, coll, :[], *idx)
17
18
  end
18
19
  end
19
20
  end
@@ -3,7 +3,6 @@ module RipperRubyParser
3
3
  module Assignment
4
4
  def process_assign exp
5
5
  _, lvalue, value = exp.shift 3
6
-
7
6
  lvalue = process(lvalue)
8
7
  value = process(value)
9
8
 
@@ -35,7 +34,7 @@ module RipperRubyParser
35
34
  case right.sexp_type
36
35
  when :fake_array
37
36
  right[0] = :array
38
- when :array, :splat
37
+ when :splat
39
38
  # Do nothing
40
39
  else
41
40
  right = s(:to_ary, right)
@@ -104,11 +103,7 @@ module RipperRubyParser
104
103
  def create_valueless_assignment_sub_type(item)
105
104
  item = with_line_number(item.line,
106
105
  create_regular_assignment_sub_type(item, nil))
107
- if item.sexp_type == :attrasgn
108
- item.last.pop
109
- else
110
- item.pop
111
- end
106
+ item.pop
112
107
  return item
113
108
  end
114
109
 
@@ -129,7 +124,7 @@ module RipperRubyParser
129
124
  if (mapped = OPERATOR_ASSIGNMENT_MAP[operator])
130
125
  s(mapped, lvalue, create_assignment_sub_type(lvalue, value))
131
126
  else
132
- operator_call = s(:call, lvalue, operator, s(:arglist, value))
127
+ operator_call = s(:call, lvalue, operator, value)
133
128
  create_assignment_sub_type lvalue, operator_call
134
129
  end
135
130
  end
@@ -140,10 +135,11 @@ module RipperRubyParser
140
135
  when :aref_field
141
136
  _, arr, arglist = lvalue
142
137
  arglist << value
143
- s(:attrasgn, arr, :[]=, arglist)
138
+ arglist.shift
139
+ s(:attrasgn, arr, :[]=, *arglist)
144
140
  when :field
145
141
  _, obj, _, (_, field) = lvalue
146
- s(:attrasgn, obj, :"#{field}=", s(:arglist, value))
142
+ s(:attrasgn, obj, :"#{field}=", value)
147
143
  else
148
144
  create_assignment_sub_type lvalue, value
149
145
  end
@@ -19,22 +19,25 @@ module RipperRubyParser
19
19
  end
20
20
 
21
21
  def process_params exp
22
- _, normal, defaults, rest, _, block = exp.shift 6
22
+ if exp.size == 6
23
+ _, normal, defaults, splat, rest, block = exp.shift 6
24
+ else
25
+ _, normal, defaults, splat, rest, _, _, block = exp.shift 8
26
+ end
23
27
 
24
28
  args = [*normal].map do |id|
25
29
  process(id)
26
30
  end
27
31
 
28
- assigns = [*defaults].map do |pair|
32
+ [*defaults].each do |pair|
29
33
  sym = process(pair[0])
30
- args << sym
31
34
  val = process(pair[1])
32
- s(:lasgn, sym[1], val)
35
+ args << s(:lasgn, sym[1], val)
33
36
  end
34
37
 
35
- args << process(rest) unless rest.nil?
38
+ args << process(splat) unless splat.nil? || splat == 0
39
+ [*rest].each {|arg| args << process(arg)}
36
40
  args << process(block) unless block.nil?
37
- args << s(:block, *assigns) if assigns.length > 0
38
41
 
39
42
  s(:args, *args)
40
43
  end
@@ -44,20 +47,20 @@ module RipperRubyParser
44
47
 
45
48
  names = process(args)
46
49
 
47
- args_to_assignment names
50
+ convert_special_args names
48
51
  end
49
52
 
50
53
  def process_begin exp
51
54
  _, body = exp.shift 2
52
55
 
53
- block = process(body)[1]
54
-
55
- strip_wrapping_block(block.compact)
56
+ body = process(body)
57
+ strip_typeless_sexp(body)
56
58
  end
57
59
 
58
60
  def process_rescue exp
59
61
  _, eclass, evar, block, after = exp.shift 5
60
62
  rescue_block = map_body(block)
63
+ rescue_block << nil if rescue_block.empty?
61
64
 
62
65
  arr = []
63
66
  if eclass
@@ -70,13 +73,11 @@ module RipperRubyParser
70
73
  end
71
74
 
72
75
  if evar
73
- evar = process(evar)[1]
74
- easgn = s(:lasgn, evar, s(:gvar, :$!))
75
- arr << easgn
76
+ arr << create_assignment_sub_type(process(evar), s(:gvar, :$!))
76
77
  end
77
78
 
78
79
  s(
79
- s(:resbody, s(:array, *arr), wrap_in_block(rescue_block)),
80
+ s(:resbody, s(:array, *arr), *rescue_block),
80
81
  *process(after))
81
82
  end
82
83
 
@@ -85,10 +86,6 @@ module RipperRubyParser
85
86
 
86
87
  body = map_body body
87
88
 
88
- #unless rescue_block or ensure_block
89
- # return s(:scope, s(:block, *body))
90
- #end
91
-
92
89
  body = wrap_in_block(body)
93
90
 
94
91
  body = if body.nil?
@@ -110,11 +107,15 @@ module RipperRubyParser
110
107
  body = s(s(:ensure, *body))
111
108
  end
112
109
 
113
- if body.length == 1 and body.first.sexp_type == :block
114
- s(:scope, *body)
115
- else
116
- s(:scope, s(:block, *body))
117
- end
110
+ body = wrap_in_block(body)
111
+
112
+ body = if body.nil?
113
+ s()
114
+ else
115
+ s(body)
116
+ end
117
+
118
+ body
118
119
  end
119
120
 
120
121
  def process_rescue_mod exp
@@ -124,7 +125,7 @@ module RipperRubyParser
124
125
 
125
126
  def process_ensure exp
126
127
  _, block = exp.shift 2
127
- wrap_in_block s(*map_body(block))
128
+ strip_typeless_sexp safe_wrap_in_block s(*map_body(block))
128
129
  end
129
130
 
130
131
  def process_next exp
@@ -147,8 +148,10 @@ module RipperRubyParser
147
148
 
148
149
  def process_lambda exp
149
150
  _, args, statements = exp.shift 3
150
- make_iter(s(:call, nil, :lambda, s(:arglist)),
151
- args_to_assignment(process(args)),
151
+ args = convert_special_args(process(args))
152
+ args = 0 if args == s(:args)
153
+ make_iter(s(:call, nil, :lambda),
154
+ args,
152
155
  *handle_potentially_typeless_sexp(statements))
153
156
  end
154
157
 
@@ -156,57 +159,31 @@ module RipperRubyParser
156
159
 
157
160
  def handle_generic_block exp
158
161
  _, args, stmts = exp.shift 3
162
+ args = process(args)
163
+ args = 0 if args == s(:args)
159
164
  # FIXME: Symbol :block is irrelevant.
160
- s(:block, process(args), s(handle_statement_list(stmts)))
165
+ s(:block, args, s(wrap_in_block(map_body(stmts))))
161
166
  end
162
167
 
163
- def strip_wrapping_block(block)
164
- return block unless block.sexp_type == :block
168
+ def strip_typeless_sexp(block)
165
169
  case block.length
166
- when 1
170
+ when 0
167
171
  s(:nil)
168
- when 2
169
- block[1]
172
+ when 1
173
+ block[0]
170
174
  else
171
175
  block
172
176
  end
173
177
  end
174
178
 
175
- def arg_name_to_lasgn(name)
176
- case name.sexp_type
177
- when :lvar
178
- s(:lasgn, name[1])
179
- when :blockarg
180
- s(:lasgn, :"&#{name[1][1]}")
181
- when :splat
182
- if name[1].nil?
183
- s(:splat)
184
- else
185
- s(:splat, s(:lasgn, name[1][1]))
186
- end
187
- else
188
- name
189
- end
190
- end
191
-
192
179
  def make_iter call, args, stmt
180
+ args = s(:args) unless args
193
181
  if stmt.nil?
194
182
  s(:iter, call, args)
195
183
  else
196
184
  s(:iter, call, args, stmt)
197
185
  end
198
186
  end
199
-
200
- def args_to_assignment names
201
- names.shift
202
- if names.length == 1 and names.first.sexp_type == :lvar
203
- s(:lasgn, names.first[1])
204
- elsif names.length == 1 and names.first.sexp_type == :masgn
205
- names.first
206
- else
207
- s(:masgn, s(:array, *names.map { |name| arg_name_to_lasgn(name) }))
208
- end
209
- end
210
187
  end
211
188
  end
212
189
  end
@@ -4,42 +4,35 @@ module RipperRubyParser
4
4
  def process_if exp
5
5
  _, cond, truepart, falsepart = exp.shift 4
6
6
 
7
- cond = process(cond)
8
- truepart = handle_statement_list(truepart)
9
- falsepart = process(falsepart)
10
-
11
- if cond.sexp_type == :not
12
- cond = cond[1]
13
- truepart, falsepart = falsepart, truepart
14
- end
15
-
16
- s(:if, cond, truepart, falsepart)
7
+ s(:if, handle_condition(cond),
8
+ wrap_in_block(map_body(truepart)),
9
+ process(falsepart))
17
10
  end
18
11
 
19
12
  def process_elsif exp
20
13
  _, cond, truepart, falsepart = exp.shift 4
21
14
 
22
15
  s(:if, process(cond),
23
- handle_statement_list(truepart),
16
+ wrap_in_block(map_body(truepart)),
24
17
  process(falsepart))
25
18
  end
26
19
 
27
20
  def process_if_mod exp
28
21
  _, cond, truepart = exp.shift 3
29
- process_if s(:if, cond, s(truepart), nil)
22
+ s(:if, handle_condition(cond), process(truepart), nil)
30
23
  end
31
24
 
32
25
  def process_unless_mod exp
33
26
  _, cond, truepart = exp.shift 3
34
- s(:if, process(cond), nil, process(truepart))
27
+ s(:if, handle_condition(cond), nil, process(truepart))
35
28
  end
36
29
 
37
30
  def process_unless exp
38
31
  _, cond, truepart, falsepart = exp.shift 4
39
32
  s(:if,
40
- process(cond),
33
+ handle_condition(cond),
41
34
  process(falsepart),
42
- handle_statement_list(truepart))
35
+ wrap_in_block(map_body(truepart)))
43
36
  end
44
37
 
45
38
  def process_case exp
@@ -58,25 +51,38 @@ module RipperRubyParser
58
51
  falsepart = s(falsepart)
59
52
  end
60
53
  end
54
+ falsepart = [nil] if falsepart.empty?
61
55
 
62
56
  values = handle_array_elements values
63
- values = values.map do |val|
64
- if val.sexp_type == :splat
65
- s(:when, val[1], nil)
66
- else
67
- val
68
- end
69
- end
70
57
 
71
- s(s(:when, s(:array, *values),
72
- handle_statement_list(truepart)),
58
+ truepart = map_body(truepart)
59
+ truepart = [nil] if truepart.empty?
60
+
61
+ s(s(:when,
62
+ s(:array, *values),
63
+ *truepart),
73
64
  *falsepart)
74
65
  end
75
66
 
76
67
  def process_else exp
77
68
  _, body = exp.shift 2
78
- handle_statement_list body
69
+ safe_wrap_in_block(map_body(body))
79
70
  end
71
+
72
+ private
73
+
74
+ def handle_condition(cond)
75
+ cond = process(cond)
76
+ if (cond.sexp_type == :lit) && cond[1].is_a?(Regexp)
77
+ cond = s(:match, cond)
78
+ elsif cond.sexp_type == :dot2
79
+ cond = s(:flip2, *cond[1..-1])
80
+ elsif cond.sexp_type == :dot3
81
+ cond = s(:flip3, *cond[1..-1])
82
+ end
83
+ return cond
84
+ end
85
+
80
86
  end
81
87
  end
82
88
  end