ruby_parser 2.1.0 → 2.2.0
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.
Potentially problematic release.
This version of ruby_parser might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/History.txt +13 -0
- data/lib/ruby_lexer.rb +3 -4
- data/lib/ruby_parser.rb +2502 -2511
- data/lib/ruby_parser.y +7 -4
- data/lib/ruby_parser_extras.rb +155 -155
- data/test/test_ruby_parser.rb +65 -0
- data/test/test_ruby_parser_extras.rb +7 -6
- metadata +11 -11
- metadata.gz.sig +0 -0
data/lib/ruby_parser.y
CHANGED
@@ -461,9 +461,10 @@ rule
|
|
461
461
|
result = val[0]
|
462
462
|
}
|
463
463
|
|
464
|
-
|
465
|
-
|
466
|
-
|
464
|
+
fsym: fname | symbol
|
465
|
+
|
466
|
+
fitem: fsym { result = s(:lit, val[0].to_sym) }
|
467
|
+
| dsym
|
467
468
|
|
468
469
|
undef_list: fitem
|
469
470
|
{
|
@@ -986,7 +987,7 @@ rule
|
|
986
987
|
call = new_call(nil, oper.to_sym)
|
987
988
|
iter.insert 1, call
|
988
989
|
result = iter
|
989
|
-
call.line
|
990
|
+
call.line = iter.line
|
990
991
|
}
|
991
992
|
| method_call
|
992
993
|
| method_call brace_block
|
@@ -1202,6 +1203,7 @@ rule
|
|
1202
1203
|
do_block: kDO_BLOCK
|
1203
1204
|
{
|
1204
1205
|
self.env.extend :dynamic
|
1206
|
+
result = self.lexer.lineno
|
1205
1207
|
}
|
1206
1208
|
opt_block_var
|
1207
1209
|
{
|
@@ -1212,6 +1214,7 @@ rule
|
|
1212
1214
|
vars = val[2]
|
1213
1215
|
body = val[4]
|
1214
1216
|
result = new_iter nil, vars, body
|
1217
|
+
result.line = val[1]
|
1215
1218
|
|
1216
1219
|
self.env.unextend
|
1217
1220
|
}
|
data/lib/ruby_parser_extras.rb
CHANGED
@@ -123,7 +123,7 @@ class RPStringScanner < StringScanner
|
|
123
123
|
end
|
124
124
|
|
125
125
|
class RubyParser < Racc::Parser
|
126
|
-
VERSION = '2.
|
126
|
+
VERSION = '2.2.0' unless constants.include? "VERSION" # SIGH
|
127
127
|
|
128
128
|
attr_accessor :lexer, :in_def, :in_single, :file
|
129
129
|
attr_reader :env, :comments
|
@@ -824,187 +824,187 @@ class RubyParser < Racc::Parser
|
|
824
824
|
# for now do nothing with the msg
|
825
825
|
old_yyerror
|
826
826
|
end
|
827
|
-
end
|
828
827
|
|
829
|
-
class Keyword
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
828
|
+
class Keyword
|
829
|
+
class KWtable
|
830
|
+
attr_accessor :name, :state, :id0, :id1
|
831
|
+
def initialize(name, id=[], state=nil)
|
832
|
+
@name = name
|
833
|
+
@id0, @id1 = id
|
834
|
+
@state = state
|
835
|
+
end
|
836
836
|
end
|
837
|
-
end
|
838
837
|
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
838
|
+
##
|
839
|
+
# :stopdoc:
|
840
|
+
#
|
841
|
+
# :expr_beg = ignore newline, +/- is a sign.
|
842
|
+
# :expr_end = newline significant, +/- is a operator.
|
843
|
+
# :expr_arg = newline significant, +/- is a operator.
|
844
|
+
# :expr_cmdarg = newline significant, +/- is a operator.
|
845
|
+
# :expr_endarg = newline significant, +/- is a operator.
|
846
|
+
# :expr_mid = newline significant, +/- is a operator.
|
847
|
+
# :expr_fname = ignore newline, no reserved words.
|
848
|
+
# :expr_dot = right after . or ::, no reserved words.
|
849
|
+
# :expr_class = immediate after class, no here document.
|
850
|
+
|
851
|
+
wordlist = [
|
852
|
+
["end", [:kEND, :kEND ], :expr_end ],
|
853
|
+
["else", [:kELSE, :kELSE ], :expr_beg ],
|
854
|
+
["case", [:kCASE, :kCASE ], :expr_beg ],
|
855
|
+
["ensure", [:kENSURE, :kENSURE ], :expr_beg ],
|
856
|
+
["module", [:kMODULE, :kMODULE ], :expr_beg ],
|
857
|
+
["elsif", [:kELSIF, :kELSIF ], :expr_beg ],
|
858
|
+
["def", [:kDEF, :kDEF ], :expr_fname ],
|
859
|
+
["rescue", [:kRESCUE, :kRESCUE_MOD ], :expr_mid ],
|
860
|
+
["not", [:kNOT, :kNOT ], :expr_beg ],
|
861
|
+
["then", [:kTHEN, :kTHEN ], :expr_beg ],
|
862
|
+
["yield", [:kYIELD, :kYIELD ], :expr_arg ],
|
863
|
+
["for", [:kFOR, :kFOR ], :expr_beg ],
|
864
|
+
["self", [:kSELF, :kSELF ], :expr_end ],
|
865
|
+
["false", [:kFALSE, :kFALSE ], :expr_end ],
|
866
|
+
["retry", [:kRETRY, :kRETRY ], :expr_end ],
|
867
|
+
["return", [:kRETURN, :kRETURN ], :expr_mid ],
|
868
|
+
["true", [:kTRUE, :kTRUE ], :expr_end ],
|
869
|
+
["if", [:kIF, :kIF_MOD ], :expr_beg ],
|
870
|
+
["defined?", [:kDEFINED, :kDEFINED ], :expr_arg ],
|
871
|
+
["super", [:kSUPER, :kSUPER ], :expr_arg ],
|
872
|
+
["undef", [:kUNDEF, :kUNDEF ], :expr_fname ],
|
873
|
+
["break", [:kBREAK, :kBREAK ], :expr_mid ],
|
874
|
+
["in", [:kIN, :kIN ], :expr_beg ],
|
875
|
+
["do", [:kDO, :kDO ], :expr_beg ],
|
876
|
+
["nil", [:kNIL, :kNIL ], :expr_end ],
|
877
|
+
["until", [:kUNTIL, :kUNTIL_MOD ], :expr_beg ],
|
878
|
+
["unless", [:kUNLESS, :kUNLESS_MOD ], :expr_beg ],
|
879
|
+
["or", [:kOR, :kOR ], :expr_beg ],
|
880
|
+
["next", [:kNEXT, :kNEXT ], :expr_mid ],
|
881
|
+
["when", [:kWHEN, :kWHEN ], :expr_beg ],
|
882
|
+
["redo", [:kREDO, :kREDO ], :expr_end ],
|
883
|
+
["and", [:kAND, :kAND ], :expr_beg ],
|
884
|
+
["begin", [:kBEGIN, :kBEGIN ], :expr_beg ],
|
885
|
+
["__LINE__", [:k__LINE__, :k__LINE__ ], :expr_end ],
|
886
|
+
["class", [:kCLASS, :kCLASS ], :expr_class ],
|
887
|
+
["__FILE__", [:k__FILE__, :k__FILE__ ], :expr_end ],
|
888
|
+
["END", [:klEND, :klEND ], :expr_end ],
|
889
|
+
["BEGIN", [:klBEGIN, :klBEGIN ], :expr_end ],
|
890
|
+
["while", [:kWHILE, :kWHILE_MOD ], :expr_beg ],
|
891
|
+
["alias", [:kALIAS, :kALIAS ], :expr_fname ],
|
892
|
+
].map { |args| KWtable.new(*args) }
|
893
|
+
|
894
|
+
# :startdoc:
|
895
|
+
|
896
|
+
WORDLIST = Hash[*wordlist.map { |o| [o.name, o] }.flatten] unless
|
897
|
+
defined? WORDLIST
|
898
|
+
|
899
|
+
def self.keyword str
|
900
|
+
WORDLIST[str]
|
901
|
+
end
|
902
902
|
end
|
903
|
-
end
|
904
903
|
|
905
|
-
class Environment
|
906
|
-
|
904
|
+
class Environment
|
905
|
+
attr_reader :env, :dyn
|
907
906
|
|
908
|
-
|
909
|
-
|
910
|
-
|
907
|
+
def [] k
|
908
|
+
self.all[k]
|
909
|
+
end
|
911
910
|
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
911
|
+
def []= k, v
|
912
|
+
raise "no" if v == true
|
913
|
+
self.current[k] = v
|
914
|
+
end
|
916
915
|
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
916
|
+
def all
|
917
|
+
idx = @dyn.index(false) || 0
|
918
|
+
@env[0..idx].reverse.inject { |env, scope| env.merge scope }
|
919
|
+
end
|
921
920
|
|
922
|
-
|
923
|
-
|
924
|
-
|
921
|
+
def current
|
922
|
+
@env.first
|
923
|
+
end
|
925
924
|
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
925
|
+
def dynamic
|
926
|
+
idx = @dyn.index false
|
927
|
+
@env[0...idx].reverse.inject { |env, scope| env.merge scope } || {}
|
928
|
+
end
|
930
929
|
|
931
|
-
|
932
|
-
|
933
|
-
|
930
|
+
def dynamic?
|
931
|
+
@dyn[0] != false
|
932
|
+
end
|
934
933
|
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
934
|
+
def extend dyn = false
|
935
|
+
@dyn.unshift dyn
|
936
|
+
@env.unshift({})
|
937
|
+
@use.unshift({})
|
938
|
+
end
|
940
939
|
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
940
|
+
def initialize dyn = false
|
941
|
+
@dyn = []
|
942
|
+
@env = []
|
943
|
+
@use = []
|
944
|
+
self.reset
|
945
|
+
end
|
947
946
|
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
947
|
+
def reset
|
948
|
+
@dyn.clear
|
949
|
+
@env.clear
|
950
|
+
@use.clear
|
951
|
+
self.extend
|
952
|
+
end
|
954
953
|
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
954
|
+
def unextend
|
955
|
+
@dyn.shift
|
956
|
+
@env.shift
|
957
|
+
@use.shift
|
958
|
+
raise "You went too far unextending env" if @env.empty?
|
959
|
+
end
|
961
960
|
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
961
|
+
def use id
|
962
|
+
@env.each_with_index do |env, i|
|
963
|
+
if env[id] then
|
964
|
+
@use[i][id] = true
|
965
|
+
end
|
966
966
|
end
|
967
967
|
end
|
968
|
-
end
|
969
968
|
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
969
|
+
def used? id
|
970
|
+
idx = @dyn.index false # REFACTOR
|
971
|
+
u = @use[0...idx].reverse.inject { |env, scope| env.merge scope } || {}
|
972
|
+
u[id]
|
973
|
+
end
|
974
974
|
end
|
975
|
-
end
|
976
975
|
|
977
|
-
class StackState
|
978
|
-
|
976
|
+
class StackState
|
977
|
+
attr_reader :stack
|
979
978
|
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
979
|
+
def initialize(name)
|
980
|
+
@name = name
|
981
|
+
@stack = [false]
|
982
|
+
end
|
984
983
|
|
985
|
-
|
986
|
-
|
987
|
-
|
984
|
+
def inspect
|
985
|
+
"StackState(#{@name}, #{@stack.inspect})"
|
986
|
+
end
|
988
987
|
|
989
|
-
|
990
|
-
|
991
|
-
|
988
|
+
def is_in_state
|
989
|
+
@stack.last
|
990
|
+
end
|
992
991
|
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
992
|
+
def lexpop
|
993
|
+
raise if @stack.size == 0
|
994
|
+
a = @stack.pop
|
995
|
+
b = @stack.pop
|
996
|
+
@stack.push(a || b)
|
997
|
+
end
|
999
998
|
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
999
|
+
def pop
|
1000
|
+
r = @stack.pop
|
1001
|
+
@stack.push false if @stack.size == 0
|
1002
|
+
r
|
1003
|
+
end
|
1005
1004
|
|
1006
|
-
|
1007
|
-
|
1005
|
+
def push val
|
1006
|
+
@stack.push val
|
1007
|
+
end
|
1008
1008
|
end
|
1009
1009
|
end
|
1010
1010
|
|
data/test/test_ruby_parser.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
#!/usr/local/bin/ruby
|
2
2
|
|
3
|
+
ENV['VERBOSE'] = "1"
|
4
|
+
|
3
5
|
require 'rubygems'
|
4
6
|
require 'minitest/autorun'
|
5
7
|
require 'ruby_parser'
|
@@ -372,6 +374,14 @@ class TestRubyParser < RubyParserTestCase
|
|
372
374
|
assert_equal pt, @processor.parse(rb)
|
373
375
|
end
|
374
376
|
|
377
|
+
def test_dsym_to_sym
|
378
|
+
assert_equal(s(:alias, s(:lit, :<<), s(:lit, :>>)),
|
379
|
+
@processor.parse('alias :<< :>>'))
|
380
|
+
|
381
|
+
assert_equal(s(:alias, s(:lit, :<<), s(:lit, :>>)),
|
382
|
+
@processor.parse('alias :"<<" :">>"'))
|
383
|
+
end
|
384
|
+
|
375
385
|
def test_regexp
|
376
386
|
regexps = {
|
377
387
|
"/wtf/" => /wtf/,
|
@@ -463,6 +473,61 @@ class TestRubyParser < RubyParserTestCase
|
|
463
473
|
assert_same result.file, result.call.file
|
464
474
|
end
|
465
475
|
|
476
|
+
def test_position_info_call_no_args
|
477
|
+
rb = "f do |x, y|\n x + y\nend"
|
478
|
+
|
479
|
+
pt = s(:iter,
|
480
|
+
s(:call, nil, :f, s(:arglist)),
|
481
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
482
|
+
s(:call, s(:lvar, :x), :+, s(:arglist, s(:lvar, :y))))
|
483
|
+
|
484
|
+
result = @processor.parse(rb)
|
485
|
+
|
486
|
+
assert_equal pt, result
|
487
|
+
|
488
|
+
assert_equal 1, result[1].line, "call should have line number"
|
489
|
+
assert_equal 1, result.line, "iter should have line number"
|
490
|
+
assert_equal 1, result[2].line, "masgn should have line number"
|
491
|
+
assert_equal 2, result[3].line, "call should have line number"
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_position_info_call_parens
|
495
|
+
rb = "f(a) do |x, y|\n x + y\nend"
|
496
|
+
|
497
|
+
pt = s(:iter,
|
498
|
+
s(:call, nil, :f, s(:arglist, s(:call, nil, :a, s(:arglist)))),
|
499
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
500
|
+
s(:call, s(:lvar, :x), :+, s(:arglist, s(:lvar, :y))))
|
501
|
+
|
502
|
+
result = @processor.parse(rb)
|
503
|
+
|
504
|
+
assert_equal pt, result
|
505
|
+
|
506
|
+
assert_equal 1, result[1].line, "call should have line number"
|
507
|
+
assert_equal 1, result.line, "iter should have line number"
|
508
|
+
assert_equal 1, result[2].line, "masgn should have line number"
|
509
|
+
assert_equal 2, result[3].line, "call should have line number"
|
510
|
+
# flunk "not yet"
|
511
|
+
end
|
512
|
+
|
513
|
+
def test_position_info_call_no_parens
|
514
|
+
rb = "f a do |x, y|\n x + y\nend"
|
515
|
+
|
516
|
+
pt = s(:iter,
|
517
|
+
s(:call, nil, :f, s(:arglist, s(:call, nil, :a, s(:arglist)))),
|
518
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
519
|
+
s(:call, s(:lvar, :x), :+, s(:arglist, s(:lvar, :y))))
|
520
|
+
|
521
|
+
result = @processor.parse(rb)
|
522
|
+
|
523
|
+
assert_equal pt, result
|
524
|
+
|
525
|
+
assert_equal 1, result.line, "iter should have line number"
|
526
|
+
assert_equal 1, result[1].line, "call should have line number"
|
527
|
+
assert_equal 1, result[2].line, "masgn should have line number"
|
528
|
+
assert_equal 2, result[3].line, "call should have line number"
|
529
|
+
end
|
530
|
+
|
466
531
|
def test_position_info_defn
|
467
532
|
rb = "def x(y)\n p(y)\n y *= 2\n return y;\nend" # TODO: remove () & ;
|
468
533
|
pt = s(:defn, :x, s(:args, :y),
|