ruby_parser 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
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),
|