ripper_ruby_parser 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,9 +9,10 @@ module RipperRubyParser
9
9
  @processor = processor
10
10
  end
11
11
 
12
- def parse source, filename='-', lineno=1
12
+ def parse source, filename='(string)', lineno=1
13
13
  parser = CommentingSexpBuilder.new(source, filename, lineno)
14
14
  exp = Sexp.from_array(parser.parse)
15
+ @processor.filename = filename
15
16
  @processor.process exp
16
17
  end
17
18
  end
@@ -3,7 +3,15 @@ module RipperRubyParser
3
3
  module Arrays
4
4
  def process_array exp
5
5
  _, elems = exp.shift 2
6
- s(:array, *handle_potentially_typeless_sexp(elems))
6
+ elems = handle_potentially_typeless_sexp(elems)
7
+ elems.map! do |elem|
8
+ if elem.first.is_a? Symbol
9
+ elem
10
+ else
11
+ elem.first
12
+ end
13
+ end
14
+ s(:array, *elems)
7
15
  end
8
16
 
9
17
  def process_aref exp
@@ -84,6 +84,24 @@ module RipperRubyParser
84
84
  wrap_in_block s(*map_body(block))
85
85
  end
86
86
 
87
+ def process_next exp
88
+ _, args = exp.shift 2
89
+ if args.empty?
90
+ s(:next)
91
+ else
92
+ s(:next, handle_return_argument_list(args))
93
+ end
94
+ end
95
+
96
+ def process_break exp
97
+ _, args = exp.shift 2
98
+ if args.empty?
99
+ s(:break)
100
+ else
101
+ s(:break, handle_return_argument_list(args))
102
+ end
103
+ end
104
+
87
105
  private
88
106
 
89
107
  def handle_generic_block exp
@@ -8,6 +8,22 @@ module RipperRubyParser
8
8
 
9
9
  def process_assoclist_from_args exp
10
10
  _, elems = exp.shift 2
11
+ make_hash_items elems
12
+ end
13
+
14
+ def process_assoc_new exp
15
+ _, left, right = exp.shift 3
16
+ s(process(left), process(right))
17
+ end
18
+
19
+ def process_bare_assoc_hash exp
20
+ _, elems = exp.shift 2
21
+ s(:hash, *make_hash_items(elems))
22
+ end
23
+
24
+ private
25
+
26
+ def make_hash_items elems
11
27
  result = s()
12
28
  elems.each {|sub_exp|
13
29
  process(sub_exp).each {|elm|
@@ -16,11 +32,6 @@ module RipperRubyParser
16
32
  }
17
33
  result
18
34
  end
19
-
20
- def process_assoc_new exp
21
- _, left, right = exp.shift 3
22
- s(process(left), process(right))
23
- end
24
35
  end
25
36
  end
26
37
  end
@@ -2,12 +2,24 @@ module RipperRubyParser
2
2
  module SexpHandlers
3
3
  module HelperMethods
4
4
  def handle_potentially_typeless_sexp exp
5
+ if exp.nil?
6
+ s()
7
+ elsif exp.first.is_a? Symbol
8
+ process(exp)
9
+ else
10
+ exp.map! { |sub_exp| handle_potentially_typeless_sexp(sub_exp) }
11
+ end
12
+ end
13
+
14
+ def handle_potentially_typeless_sexp_with_fallback_type type, exp
5
15
  if exp.nil?
6
16
  s()
7
17
  elsif exp.first.is_a? Symbol
8
18
  process(exp)
9
19
  else
10
20
  exp.map! { |sub_exp| process(sub_exp) }
21
+ exp.unshift type
22
+ exp
11
23
  end
12
24
  end
13
25
 
@@ -72,6 +84,22 @@ module RipperRubyParser
72
84
  s(:block, *statements)
73
85
  end
74
86
  end
87
+
88
+ def handle_return_argument_list arglist
89
+ arglist = process(arglist)
90
+ args = arglist[1..-1]
91
+
92
+ if args.length == 1
93
+ arg = args[0]
94
+ if arg.sexp_type == :splat
95
+ s(:svalue, arg)
96
+ else
97
+ arg
98
+ end
99
+ else
100
+ s(:array, *args)
101
+ end
102
+ end
75
103
  end
76
104
  end
77
105
  end
@@ -17,13 +17,17 @@ module RipperRubyParser
17
17
  def process_command exp
18
18
  _, ident, arglist = exp.shift 3
19
19
  with_position_from_node_symbol(ident) {|method|
20
- s(:call, nil, method, process(arglist)) }
20
+ s(:call, nil, method,
21
+ handle_potentially_typeless_sexp_with_fallback_type(:arglist, arglist))
22
+ }
21
23
  end
22
24
 
23
25
  def process_command_call exp
24
26
  _, receiver, _, ident, arguments = exp.shift 5
25
27
  with_position_from_node_symbol(ident) {|method|
26
- s(:call, process(receiver), method, process(arguments)) }
28
+ s(:call, process(receiver), method,
29
+ handle_potentially_typeless_sexp_with_fallback_type(:arglist, arguments))
30
+ }
27
31
  end
28
32
 
29
33
  def process_vcall exp
@@ -17,20 +17,7 @@ module RipperRubyParser
17
17
 
18
18
  def process_return exp
19
19
  _, arglist = exp.shift 2
20
-
21
- arglist = process(arglist)
22
- args = arglist[1..-1]
23
-
24
- if args.length == 1
25
- arg = args[0]
26
- if arg.sexp_type == :splat
27
- s(:return, s(:svalue, arg))
28
- else
29
- s(:return, arg)
30
- end
31
- else
32
- s(:return, s(:array, *args))
33
- end
20
+ s(:return, handle_return_argument_list(arglist))
34
21
  end
35
22
 
36
23
  def process_return0 exp
@@ -49,6 +36,36 @@ module RipperRubyParser
49
36
  s(:yield)
50
37
  end
51
38
 
39
+ def process_undef exp
40
+ _, args = exp.shift 2
41
+
42
+ args.map! do |sub_exp|
43
+ s(:undef, make_method_name_literal(sub_exp))
44
+ end
45
+
46
+ if args.size == 1
47
+ args[0]
48
+ else
49
+ s(:block, *args)
50
+ end
51
+ end
52
+
53
+ def process_alias exp
54
+ _, *args = exp.shift 3
55
+
56
+ args.map! do |sub_exp|
57
+ make_method_name_literal sub_exp
58
+ end
59
+
60
+ s(:alias, *args)
61
+ end
62
+
63
+ private
64
+
65
+ def make_method_name_literal exp
66
+ process(exp).tap {|it| it[0] = :lit}
67
+ end
68
+
52
69
  def method_body exp
53
70
  scope = process exp
54
71
  block = scope[1]
@@ -5,6 +5,8 @@ require 'ripper_ruby_parser/sexp_ext'
5
5
  module RipperRubyParser
6
6
  # Processes the sexp created by Ripper to what RubyParser would produce.
7
7
  class SexpProcessor < ::SexpProcessor
8
+ attr_accessor :filename
9
+
8
10
  def initialize
9
11
  super
10
12
 
@@ -12,6 +14,8 @@ module RipperRubyParser
12
14
 
13
15
  @processors[:@int] = :process_at_int
14
16
  @processors[:@float] = :process_at_float
17
+ @processors[:@CHAR] = :process_at_CHAR
18
+ @processors[:@label] = :process_at_label
15
19
 
16
20
  @processors[:@const] = :process_at_const
17
21
  @processors[:@ident] = :process_at_ident
@@ -19,6 +23,7 @@ module RipperRubyParser
19
23
  @processors[:@gvar] = :process_at_gvar
20
24
  @processors[:@ivar] = :process_at_ivar
21
25
  @processors[:@kw] = :process_at_kw
26
+ @processors[:@op] = :process_at_op
22
27
  @processors[:@backref] = :process_at_backref
23
28
 
24
29
  @processors[:@tstring_content] = :process_at_tstring_content
@@ -128,13 +133,20 @@ module RipperRubyParser
128
133
 
129
134
  # number literals
130
135
  def process_at_int exp
131
- _, val, pos = exp.shift 3
132
- with_position(pos, s(:lit, val.to_i))
136
+ make_literal(exp) {|val| val.to_i }
133
137
  end
134
138
 
135
139
  def process_at_float exp
136
- _, val, pos = exp.shift 3
137
- with_position(pos, s(:lit, val.to_f))
140
+ make_literal(exp) {|val| val.to_f }
141
+ end
142
+
143
+ # character literals
144
+ def process_at_CHAR exp
145
+ make_literal(exp) {|val| eval(val) }
146
+ end
147
+
148
+ def process_at_label exp
149
+ make_literal(exp) {|val| val.chop.to_sym }
138
150
  end
139
151
 
140
152
  # symbol-like sexps
@@ -158,10 +170,17 @@ module RipperRubyParser
158
170
  make_identifier(:lvar, exp)
159
171
  end
160
172
 
173
+ def process_at_op exp
174
+ make_identifier(:op, exp)
175
+ end
176
+
161
177
  def process_at_kw exp
162
178
  sym, pos = extract_node_symbol_with_position(exp)
163
- result = if sym == :__FILE__
164
- s(:str, "(string)")
179
+ result = case sym
180
+ when :__FILE__
181
+ s(:str, @filename)
182
+ when :__LINE__
183
+ s(:lit, pos[0])
165
184
  else
166
185
  s(sym)
167
186
  end
@@ -200,6 +219,11 @@ module RipperRubyParser
200
219
  s(type, ident) }
201
220
  end
202
221
 
222
+ def make_literal exp
223
+ _, val, pos = exp.shift 3
224
+ with_position(pos, s(:lit, yield(val)))
225
+ end
226
+
203
227
  def trickle_up_line_numbers exp
204
228
  exp.each do |sub_exp|
205
229
  if sub_exp.is_a? Sexp
@@ -1,3 +1,3 @@
1
1
  module RipperRubyParser
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
@@ -11,6 +11,7 @@ describe RipperRubyParser::Parser do
11
11
  it "post-processes its result with the passed sexp processor" do
12
12
  sexp_p = MiniTest::Mock.new
13
13
  sexp_p.expect :process, s(:result), [Sexp]
14
+ sexp_p.expect :filename=, nil, ['(string)']
14
15
 
15
16
  parser = RipperRubyParser::Parser.new sexp_p
16
17
  result = parser.parse "any code"
@@ -375,6 +376,52 @@ describe RipperRubyParser::Parser do
375
376
  end
376
377
  end
377
378
 
379
+ describe "for the undef statement" do
380
+ it "works with a single bareword identifier" do
381
+ result = parser.parse "undef foo"
382
+ result.must_equal s(:undef, s(:lit, :foo))
383
+ end
384
+
385
+ it "works with a single symbol" do
386
+ result = parser.parse "undef :foo"
387
+ result.must_equal s(:undef, s(:lit, :foo))
388
+ end
389
+
390
+ it "works with multiple bareword identifiers" do
391
+ result = parser.parse "undef foo, bar"
392
+ result.must_equal s(:block,
393
+ s(:undef, s(:lit, :foo)),
394
+ s(:undef, s(:lit, :bar)))
395
+ end
396
+
397
+ it "works with multiple bareword symbols" do
398
+ result = parser.parse "undef :foo, :bar"
399
+ result.must_equal s(:block,
400
+ s(:undef, s(:lit, :foo)),
401
+ s(:undef, s(:lit, :bar)))
402
+ end
403
+ end
404
+
405
+ describe "for the alias statement" do
406
+ it "works with regular barewords" do
407
+ result = parser.parse "alias foo bar"
408
+ result.must_equal s(:alias,
409
+ s(:lit, :foo), s(:lit, :bar))
410
+ end
411
+
412
+ it "works with symbols" do
413
+ result = parser.parse "alias :foo :bar"
414
+ result.must_equal s(:alias,
415
+ s(:lit, :foo), s(:lit, :bar))
416
+ end
417
+
418
+ it "works with operator barewords" do
419
+ result = parser.parse "alias + -"
420
+ result.must_equal s(:alias,
421
+ s(:lit, :+), s(:lit, :-))
422
+ end
423
+ end
424
+
378
425
  describe "for arguments" do
379
426
  it "works for a simple case with splat" do
380
427
  result = parser.parse "foo *bar"
@@ -402,6 +449,15 @@ describe RipperRubyParser::Parser do
402
449
  s(:block_pass,
403
450
  s(:call, nil, :bar, s(:arglist)))))
404
451
  end
452
+
453
+ it "works for a bare hash" do
454
+ result = parser.parse "foo bar => baz"
455
+ result.must_equal s(:call, nil, :foo,
456
+ s(:arglist,
457
+ s(:hash,
458
+ s(:call, nil, :bar, s(:arglist)),
459
+ s(:call, nil, :baz, s(:arglist)))))
460
+ end
405
461
  end
406
462
 
407
463
  describe "for array literals" do
@@ -422,6 +478,11 @@ describe RipperRubyParser::Parser do
422
478
  s(:call, nil, :foo, s(:arglist)),
423
479
  s(:splat, s(:call, nil, :bar, s(:arglist))))
424
480
  end
481
+
482
+ it "works for an array created with %W" do
483
+ result = parser.parse "%W(foo bar)"
484
+ result.must_equal s(:array, s(:str, "foo"), s(:str, "bar"))
485
+ end
425
486
  end
426
487
 
427
488
  describe "for hash literals" do
@@ -445,6 +506,15 @@ describe RipperRubyParser::Parser do
445
506
  s(:call, nil, :baz, s(:arglist)),
446
507
  s(:call, nil, :qux, s(:arglist)))
447
508
  end
509
+
510
+ it "works for a hash with label keys (Ruby 1.9 only)" do
511
+ result = parser.parse "{foo: bar, baz: qux}"
512
+ result.must_equal s(:hash,
513
+ s(:lit, :foo),
514
+ s(:call, nil, :bar, s(:arglist)),
515
+ s(:lit, :baz),
516
+ s(:call, nil, :qux, s(:arglist)))
517
+ end
448
518
  end
449
519
 
450
520
  describe "for number literals" do
@@ -606,6 +676,15 @@ describe RipperRubyParser::Parser do
606
676
  result = parser.parse "foo?"
607
677
  result.must_equal s(:call, nil, :foo?, s(:arglist))
608
678
  end
679
+
680
+ it "works with nested calls without brackets" do
681
+ result = parser.parse "foo bar baz"
682
+ result.must_equal s(:call, nil, :foo,
683
+ s(:arglist,
684
+ s(:call, nil, :bar,
685
+ s(:arglist,
686
+ s(:call, nil, :baz, s(:arglist))))))
687
+ end
609
688
  end
610
689
 
611
690
  describe "with a reciever" do
@@ -635,6 +714,17 @@ describe RipperRubyParser::Parser do
635
714
  s(:arglist,
636
715
  s(:call, nil, :qux, s(:arglist))))))
637
716
  end
717
+
718
+ it "works with nested calls without brackets" do
719
+ result = parser.parse "foo.bar baz qux"
720
+ result.must_equal s(:call,
721
+ s(:call, nil, :foo, s(:arglist)),
722
+ :bar,
723
+ s(:arglist,
724
+ s(:call, nil, :baz,
725
+ s(:arglist,
726
+ s(:call, nil, :qux, s(:arglist))))))
727
+ end
638
728
  end
639
729
 
640
730
  describe "with blocks" do
@@ -664,6 +754,70 @@ describe RipperRubyParser::Parser do
664
754
  end
665
755
  end
666
756
 
757
+ describe "for blocks" do
758
+ it "works with next with no arguments" do
759
+ result = parser.parse "foo do; next; end"
760
+ result.must_equal s(:iter,
761
+ s(:call, nil, :foo, s(:arglist)),
762
+ nil,
763
+ s(:next))
764
+ end
765
+
766
+ it "works with next with one argument" do
767
+ result = parser.parse "foo do; next bar; end"
768
+ result.must_equal s(:iter,
769
+ s(:call, nil, :foo, s(:arglist)),
770
+ nil,
771
+ s(:next, s(:call, nil, :bar, s(:arglist))))
772
+ end
773
+
774
+ it "works with next with several arguments" do
775
+ result = parser.parse "foo do; next bar, baz; end"
776
+ result.must_equal s(:iter,
777
+ s(:call, nil, :foo, s(:arglist)),
778
+ nil,
779
+ s(:next,
780
+ s(:array,
781
+ s(:call, nil, :bar, s(:arglist)),
782
+ s(:call, nil, :baz, s(:arglist)))))
783
+ end
784
+
785
+ it "works with break with no arguments" do
786
+ result = parser.parse "foo do; break; end"
787
+ result.must_equal s(:iter,
788
+ s(:call, nil, :foo, s(:arglist)),
789
+ nil,
790
+ s(:break))
791
+ end
792
+
793
+ it "works with break with one argument" do
794
+ result = parser.parse "foo do; break bar; end"
795
+ result.must_equal s(:iter,
796
+ s(:call, nil, :foo, s(:arglist)),
797
+ nil,
798
+ s(:break, s(:call, nil, :bar, s(:arglist))))
799
+ end
800
+
801
+ it "works with break with several arguments" do
802
+ result = parser.parse "foo do; break bar, baz; end"
803
+ result.must_equal s(:iter,
804
+ s(:call, nil, :foo, s(:arglist)),
805
+ nil,
806
+ s(:break,
807
+ s(:array,
808
+ s(:call, nil, :bar, s(:arglist)),
809
+ s(:call, nil, :baz, s(:arglist)))))
810
+ end
811
+
812
+ it "works with redo" do
813
+ result = parser.parse "foo do; redo; end"
814
+ result.must_equal s(:iter,
815
+ s(:call, nil, :foo, s(:arglist)),
816
+ nil,
817
+ s(:redo))
818
+ end
819
+ end
820
+
667
821
  describe "for yield" do
668
822
  it "works with no arguments and no brackets" do
669
823
  result = parser.parse "yield"
@@ -807,12 +961,35 @@ describe RipperRubyParser::Parser do
807
961
  "foo",
808
962
  s(:evstr, s(:call, nil, :bar, s(:arglist))))
809
963
  end
964
+
965
+ it "works for character literals (which are string literals in Ruby 1.9.3)" do
966
+ result = parser.parse "?a"
967
+ result.must_equal s(:lit, "a")
968
+ end
810
969
  end
811
970
 
812
971
  describe "for the __FILE__ keyword" do
813
- it "creates a string sexp with value '(string)'" do
814
- result = parser.parse "__FILE__"
815
- result.must_equal s(:str, "(string)")
972
+ describe "when not passing a file name" do
973
+ it "creates a string sexp with value '(string)'" do
974
+ result = parser.parse "__FILE__"
975
+ result.must_equal s(:str, "(string)")
976
+ end
977
+ end
978
+
979
+ describe "when passing a file name" do
980
+ it "creates a string sexp with the file name" do
981
+ result = parser.parse "__FILE__", "foo"
982
+ result.must_equal s(:str, "foo")
983
+ end
984
+ end
985
+ end
986
+
987
+ describe "for the __LINE__ keyword" do
988
+ it "creates a literal sexp with value of the line number" do
989
+ result = parser.parse "__LINE__"
990
+ result.must_equal s(:lit, 1)
991
+ result = parser.parse "\n__LINE__"
992
+ result.must_equal s(:lit, 2)
816
993
  end
817
994
  end
818
995
 
@@ -1413,6 +1590,18 @@ describe RipperRubyParser::Parser do
1413
1590
  nums = [ arglist.line, block.line ]
1414
1591
  nums.must_equal [1, 1]
1415
1592
  end
1593
+
1594
+ describe "when a line number is passed" do
1595
+ it "shifts all line numbers as appropriate" do
1596
+ result = parser.parse "foo\nbar\n", '(string)', 3
1597
+ result.must_equal s(:block,
1598
+ s(:call, nil, :foo, s(:arglist)),
1599
+ s(:call, nil, :bar, s(:arglist)))
1600
+ result.line.must_equal 3
1601
+ result[1].line.must_equal 3
1602
+ result[2].line.must_equal 4
1603
+ end
1604
+ end
1416
1605
  end
1417
1606
  end
1418
1607
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ripper_ruby_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-19 00:00:00.000000000 Z
12
+ date: 2012-03-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sexp_processor
16
- requirement: &13025240 !ruby/object:Gem::Requirement
16
+ requirement: &16124900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 3.0.10
21
+ version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *13025240
24
+ version_requirements: *16124900
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: minitest
27
- requirement: &13024720 !ruby/object:Gem::Requirement
27
+ requirement: &16124380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.11.2
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *13024720
35
+ version_requirements: *16124380
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &13024240 !ruby/object:Gem::Requirement
38
+ requirement: &16123900 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.2
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *13024240
46
+ version_requirements: *16123900
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: ruby_parser
49
- requirement: &13023760 !ruby/object:Gem::Requirement
49
+ requirement: &16123420 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 2.3.1
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *13023760
57
+ version_requirements: *16123420
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: simplecov
60
- requirement: &13023380 !ruby/object:Gem::Requirement
60
+ requirement: &16123040 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *13023380
68
+ version_requirements: *16123040
69
69
  description:
70
70
  email:
71
71
  - matijs@matijs.net