ripper_ruby_parser 0.0.2 → 0.0.3

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.
@@ -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