redparse 0.8.3 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +63 -4
- data/Makefile +43 -0
- data/README.txt +101 -166
- data/Rakefile +1 -1
- data/bin/redparse +49 -21
- data/lib/redparse.rb +88 -1654
- data/lib/redparse/cache.rb +172 -0
- data/lib/redparse/compile.rb +1648 -0
- data/lib/redparse/float_accurate_to_s.rb +162 -0
- data/lib/redparse/generate.rb +6 -2
- data/lib/redparse/node.rb +677 -397
- data/lib/redparse/parse_tree_server.rb +129 -0
- data/lib/redparse/pthelper.rb +43 -0
- data/lib/redparse/reg_more_sugar.rb +5 -5
- data/lib/redparse/version.rb +1 -1
- data/redparse.gemspec +43 -0
- data/test/data/skkdictools.rb +3 -0
- data/test/generate_parse_tree_server_rc.rb +43 -0
- data/test/rp-locatetest.rb +41 -1
- data/test/test_1.9.rb +114 -0
- data/test/test_all.rb +3 -0
- data/test/test_redparse.rb +283 -124
- data/test/test_xform_tree.rb +66 -0
- metadata +57 -56
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
#require 'yaml'
|
3
|
+
#require 'marshal'
|
4
|
+
|
5
|
+
module ParseTreeComm
|
6
|
+
SERIALIZE=Marshal
|
7
|
+
def put o
|
8
|
+
o=SERIALIZE.dump o
|
9
|
+
msg= o.size.to_s+"\n"+o+"\n"
|
10
|
+
begin
|
11
|
+
@out.write msg
|
12
|
+
@out.flush
|
13
|
+
rescue Exception
|
14
|
+
@out=@in=nil
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def get
|
19
|
+
begin
|
20
|
+
len=@in.gets.to_i
|
21
|
+
msg=@in.read(len)
|
22
|
+
@in.getc #read trailing \n
|
23
|
+
rescue Exception
|
24
|
+
@in=@out=nil
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
result=SERIALIZE.load msg
|
28
|
+
return result
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class ParseTreeServer
|
33
|
+
include ParseTreeComm
|
34
|
+
|
35
|
+
def self.path_to_server_command
|
36
|
+
File.expand_path __FILE__
|
37
|
+
end
|
38
|
+
|
39
|
+
def ensure_parse_tree_and_1_8
|
40
|
+
if ::RUBY_VERSION[/^\d+\.\d+/].to_f>1.8
|
41
|
+
ruby18=ENV['RUBY1_8']||fail("you must use ruby <= 1.8 (with parse_tree) or set RUBY1_8 env to a 1.8 interpreter")
|
42
|
+
exec ruby18, $0
|
43
|
+
else
|
44
|
+
begin require 'rubygems'; rescue LoadError; end
|
45
|
+
|
46
|
+
if File.exist? find_home+"/.redparse/parse_tree_server.rc"
|
47
|
+
$:.concat File.readlines(find_home+"/.redparse/parse_tree_server.rc").map{|l| l.chop }
|
48
|
+
end
|
49
|
+
|
50
|
+
require 'parse_tree'
|
51
|
+
end
|
52
|
+
rescue Exception=>e
|
53
|
+
put e
|
54
|
+
put nil
|
55
|
+
put nil
|
56
|
+
raise
|
57
|
+
end
|
58
|
+
|
59
|
+
def main
|
60
|
+
si=STDIN
|
61
|
+
so=STDOUT
|
62
|
+
@out=so; @in=si
|
63
|
+
ensure_parse_tree_and_1_8
|
64
|
+
begin
|
65
|
+
warnstash=Tempfile.new "warnstash"
|
66
|
+
STDERR.reopen warnstash
|
67
|
+
instance=ParseTree.new
|
68
|
+
while true
|
69
|
+
str=get
|
70
|
+
exit! if str==:exit!
|
71
|
+
if str==:version
|
72
|
+
put ::RUBY_VERSION
|
73
|
+
next
|
74
|
+
end
|
75
|
+
|
76
|
+
pos=STDERR.pos
|
77
|
+
|
78
|
+
tree=
|
79
|
+
begin
|
80
|
+
instance.parse_tree_for_string(str) #tree
|
81
|
+
rescue Exception=>e;
|
82
|
+
tree=e
|
83
|
+
end
|
84
|
+
put tree
|
85
|
+
|
86
|
+
open(STDERR.path){|f|
|
87
|
+
f.pos=pos
|
88
|
+
put warnings=f.read.split #warnings
|
89
|
+
}
|
90
|
+
end
|
91
|
+
rescue Exception=>e; put e; raise
|
92
|
+
ensure exit!
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Finds the user's home directory.
|
98
|
+
#--
|
99
|
+
# Some comments from the ruby-talk list regarding finding the home
|
100
|
+
# directory:
|
101
|
+
#
|
102
|
+
# I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
|
103
|
+
# to be depending on HOME in those code samples. I propose that
|
104
|
+
# it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
|
105
|
+
# least on Win32).
|
106
|
+
#(originally stolen from rubygems)
|
107
|
+
def find_home
|
108
|
+
['HOME', 'USERPROFILE'].each do |homekey|
|
109
|
+
return ENV[homekey] if ENV[homekey]
|
110
|
+
end
|
111
|
+
|
112
|
+
if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
|
113
|
+
return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
|
114
|
+
end
|
115
|
+
|
116
|
+
begin
|
117
|
+
File.expand_path("~")
|
118
|
+
rescue
|
119
|
+
if File::ALT_SEPARATOR then
|
120
|
+
"C:/"
|
121
|
+
else
|
122
|
+
"/"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
ParseTreeServer.new.main if $0==__FILE__
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class RedParse
|
2
|
+
def self.remove_silly_begins(pt)
|
3
|
+
pt.each_with_index{|x,i|
|
4
|
+
if Array===x
|
5
|
+
remove_silly_begins(x)
|
6
|
+
if x.size==2 and x.first==:begin
|
7
|
+
pt[i]=x=x.last
|
8
|
+
end
|
9
|
+
end
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
__END__
|
15
|
+
begin require 'rubygems'
|
16
|
+
rescue LoadError; #do nothing
|
17
|
+
end
|
18
|
+
|
19
|
+
have_graphwalk=true
|
20
|
+
begin require 'ron/graphedge'
|
21
|
+
rescue LoadError;
|
22
|
+
warn 'Ron::GraphWalk not found; some tests will be too strict'
|
23
|
+
have_graphwalk=false
|
24
|
+
end
|
25
|
+
|
26
|
+
unless have_graphwalk
|
27
|
+
class RedParse
|
28
|
+
def self.remove_silly_begins(pt) pt end
|
29
|
+
end
|
30
|
+
else
|
31
|
+
class RedParse
|
32
|
+
def self.remove_silly_begins(pt)
|
33
|
+
munger=proc{|cntr,o,i,ty,useit|
|
34
|
+
if Array===o and o.size==2 and o.first==:begin
|
35
|
+
useit[0]=true
|
36
|
+
Ron::GraphWalk.graphcopy(o.last,&munger)
|
37
|
+
end
|
38
|
+
}
|
39
|
+
Ron::GraphWalk.graphcopy(pt,&munger)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -20,7 +20,7 @@
|
|
20
20
|
unless Array===(Class*5).subregs
|
21
21
|
module ::Reg
|
22
22
|
class Repeat
|
23
|
-
undef subregs if
|
23
|
+
undef subregs if allocate.respond_to? :subregs
|
24
24
|
def subregs
|
25
25
|
[@reg]
|
26
26
|
end
|
@@ -29,7 +29,7 @@
|
|
29
29
|
end
|
30
30
|
|
31
31
|
|
32
|
-
unless defined? ::Reg::Transform and ::Reg::Transform.ancestors.include? ::Reg::
|
32
|
+
unless defined? ::Reg::Transform #and ::Reg::Transform.ancestors.include? ::Reg::HasBmatch
|
33
33
|
#hack, until support for this syntax makes it into the release of reg
|
34
34
|
module ::Reg
|
35
35
|
class Transform;
|
@@ -46,7 +46,7 @@
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
unless ::Reg::Reg.
|
49
|
+
unless Object.allocate.extend(::Reg::Reg).respond_to? :lb
|
50
50
|
module ::Reg
|
51
51
|
module Reg
|
52
52
|
def lb
|
@@ -73,7 +73,7 @@
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
-
unless ::Reg::Reg.
|
76
|
+
unless Object.allocate.extend(::Reg::Reg).respond_to? :la
|
77
77
|
module ::Reg
|
78
78
|
module Reg
|
79
79
|
def la
|
@@ -100,7 +100,7 @@
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
-
unless ::Reg::Reg.
|
103
|
+
unless Object.allocate.extend(::Reg::Reg).respond_to? :watch
|
104
104
|
module ::Reg
|
105
105
|
module Reg
|
106
106
|
def watch
|
data/lib/redparse/version.rb
CHANGED
data/redparse.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require "#{File.dirname(__FILE__)}/lib/redparse/version"
|
4
|
+
RedParse::Description=open("README.txt"){|f| f.read[/^==+ ?description[^\n]*?\n *\n?(.*?\n *\n.*?)\n *\n/im,1] }
|
5
|
+
RedParse::Latest_changes="###"+open("History.txt"){|f| f.read[/\A===(.*?)(?====)/m,1] }
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "redparse"
|
9
|
+
s.version = RedParse::VERSION
|
10
|
+
s.date = Time.now.strftime("%Y-%m-%d")
|
11
|
+
s.authors = ["Caleb Clausen"]
|
12
|
+
s.email = %q{caleb (at) inforadical (dot) net}
|
13
|
+
s.summary = "RedParse is a ruby parser written in pure ruby."
|
14
|
+
s.description = RedParse::Description
|
15
|
+
s.homepage = %{http://github.com/coatl/redparse}
|
16
|
+
s.rubyforge_project = %q{redparse}
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split
|
19
|
+
s.test_files = %w[test/test_all.rb]
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
s.extra_rdoc_files = ["README.txt", "COPYING.LGPL"]
|
22
|
+
s.has_rdoc = true
|
23
|
+
s.rdoc_options = %w[--main README.txt]
|
24
|
+
|
25
|
+
s.rubygems_version = %q{1.3.0}
|
26
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
27
|
+
|
28
|
+
if s.respond_to? :specification_version then
|
29
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
30
|
+
s.specification_version = 2
|
31
|
+
|
32
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
33
|
+
s.add_runtime_dependency("rubylexer", '0.7.7')
|
34
|
+
s.add_runtime_dependency("reg", ['>= 0.4.8'])
|
35
|
+
else
|
36
|
+
s.add_dependency("rubylexer", '0.7.7')
|
37
|
+
s.add_dependency("reg", ['>= 0.4.8'])
|
38
|
+
end
|
39
|
+
else
|
40
|
+
s.add_dependency("rubylexer", '0.7.7')
|
41
|
+
s.add_dependency("reg", ['>= 0.4.8'])
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'parse_tree'
|
4
|
+
|
5
|
+
##
|
6
|
+
# Finds the user's home directory.
|
7
|
+
#--
|
8
|
+
# Some comments from the ruby-talk list regarding finding the home
|
9
|
+
# directory:
|
10
|
+
#
|
11
|
+
# I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
|
12
|
+
# to be depending on HOME in those code samples. I propose that
|
13
|
+
# it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
|
14
|
+
# least on Win32).
|
15
|
+
#(originally stolen from rubygems)
|
16
|
+
def find_home
|
17
|
+
['HOME', 'USERPROFILE'].each do |homekey|
|
18
|
+
return ENV[homekey] if ENV[homekey]
|
19
|
+
end
|
20
|
+
|
21
|
+
if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
|
22
|
+
return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
File.expand_path("~")
|
27
|
+
rescue
|
28
|
+
if File::ALT_SEPARATOR then
|
29
|
+
"C:/"
|
30
|
+
else
|
31
|
+
"/"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
PARSETREE_AND_DEPENDANCIES=
|
37
|
+
%r{/(?:ZenTest|RubyInline|sexp_processor|ParseTree)-}
|
38
|
+
|
39
|
+
pt_needs_dirs=$:.grep PARSETREE_AND_DEPENDANCIES
|
40
|
+
|
41
|
+
open find_home+"/.redparse/parse_tree_server.rc","w" do |rcfile|
|
42
|
+
rcfile.write pt_needs_dirs.join("\n")+"\n"
|
43
|
+
end
|
data/test/rp-locatetest.rb
CHANGED
@@ -17,6 +17,43 @@
|
|
17
17
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18
18
|
=end
|
19
19
|
|
20
|
+
|
21
|
+
=begin
|
22
|
+
rp-locatetest passes all the ruby files it can find on the system (using
|
23
|
+
the unix command locate) to bin/redparse --vsparsetree. In other words,
|
24
|
+
it's comparing the output of RedParse (when cvt'd to a ParseTree-style
|
25
|
+
tree) to the actual output of ParseTree.
|
26
|
+
|
27
|
+
I usually run it like this:
|
28
|
+
|
29
|
+
nice ruby test/rp-locatetest.rb >test.log 2>&1 &
|
30
|
+
|
31
|
+
That runs rp-locatetest at low priority, in the background, saving
|
32
|
+
stdout and stderr to test.log.
|
33
|
+
|
34
|
+
You can then trawl through test.log, looking for lines that don't start
|
35
|
+
with 'no differences in '. (Other than the page of warnings in the
|
36
|
+
beginning, which is repeated every so often.) Or, you can look for
|
37
|
+
non-commented lines in the file 'problemfiles'. (Which is just a list of
|
38
|
+
files that caused failures in rp-locatetest.)
|
39
|
+
|
40
|
+
Ok, this is more complicated than it ought to be. Sorry.
|
41
|
+
|
42
|
+
rp-locatetest takes a LONG time to run, and hogs the cpu at 100%. That's
|
43
|
+
why I was using nice. So, make sure it's ok to do that on whatever
|
44
|
+
server you run it on. I always get impatient and kill it after some
|
45
|
+
hours or days. On a subsequent run it'll pick up again where it left
|
46
|
+
off.
|
47
|
+
|
48
|
+
Right now, about 0.5% of my ruby files cause problems for rp-locatetest.
|
49
|
+
Most of those failures correspond to known problems (the file is listed
|
50
|
+
at the end of the README and/or there's a case in test_redparse.rb for
|
51
|
+
that failure).
|
52
|
+
=end
|
53
|
+
|
54
|
+
$VERBOSE=1
|
55
|
+
$Debug=1
|
56
|
+
|
20
57
|
#require 'test/code/rubylexervsruby'
|
21
58
|
#require 'test/code/strgen'
|
22
59
|
require "redparse/problemfiles"
|
@@ -152,7 +189,8 @@ until testdata.empty?
|
|
152
189
|
|
153
190
|
# puts "testing: "+chunk.join(" ")
|
154
191
|
chunk.empty? and next
|
155
|
-
system $RUBY, "-Ilib", "bin/redparse", "--update-problemfiles", "-
|
192
|
+
system $RUBY, "-Ilib", "bin/redparse", "--update-problemfiles", "--ignore-silly-begins", "--unparse",
|
193
|
+
"-q", "--vsparsetree", *chunk
|
156
194
|
exit 2 if $?>>8 == 2 #exit if child got ^c
|
157
195
|
end
|
158
196
|
end
|
@@ -343,3 +381,5 @@ __END__
|
|
343
381
|
/usr/lib/ruby/1.8/hpricot/traverse.rb
|
344
382
|
/home/caleb/sandbox/rubylexer/jewels/net-netrc-0.2.1/lib/net/netrc.rb
|
345
383
|
/home/caleb/sandbox/rubylexer/jewels/etc-0.2.0/lib/etc.rb
|
384
|
+
|
385
|
+
|
data/test/test_1.9.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubylexer/test/oneliners_1.9'
|
3
|
+
require "redparse"
|
4
|
+
|
5
|
+
class TestsFor1_9 < Test::Unit::TestCase
|
6
|
+
RUBY_1_9_TO_1_8_EQUIVALENCES=[
|
7
|
+
'{a: b}'...'{:a=>b}',
|
8
|
+
'{a: b, c: d}'...'{:a=>b, :c=>d}',
|
9
|
+
"a ? b\n : c"..."a ? b : \n c",
|
10
|
+
|
11
|
+
'not(true)'...'not true',
|
12
|
+
'not(+1)'...'not +1',
|
13
|
+
'not (true).to_s'...'not (true).to_s', #equivalent, but parser gets there different ways
|
14
|
+
]
|
15
|
+
|
16
|
+
RUBY_1_9_TO_1_8_EQUIVALENCES_BUT_FOR_STRESC=[
|
17
|
+
'"foo"'...'"foo"',
|
18
|
+
'"foo#{bar}"'...'"foo#{bar}"',
|
19
|
+
|
20
|
+
'%W[foo]'...'%W[foo]',
|
21
|
+
'%W[foo#{bar}]'...'%W[foo#{bar}]',
|
22
|
+
|
23
|
+
'`foo`'...'`foo`',
|
24
|
+
'`foo#{bar}`'...'`foo#{bar}`',
|
25
|
+
|
26
|
+
'//'...'//',
|
27
|
+
'/aa/i'...'/aa/i',
|
28
|
+
'/a#{a}/u'...'/a#{a}/u',
|
29
|
+
'/a#{"a"}/e'...'/a#{"a"}/e',
|
30
|
+
'/b#{__FILE__}/s'...'/b#{__FILE__}/s',
|
31
|
+
'/bb/m'...'/bb/m',
|
32
|
+
'/b b/x'...'/b b/x',
|
33
|
+
'/b#{b}/o'...'/b#{b}/o',
|
34
|
+
]
|
35
|
+
|
36
|
+
|
37
|
+
RUBY_1_9_VALID=[
|
38
|
+
'not (true).to_s',
|
39
|
+
]
|
40
|
+
|
41
|
+
include RedParse::Nodes
|
42
|
+
RUBY_1_9_PATTERNS={
|
43
|
+
'not(true).to_s'=>+CallNode[+UnOpNode["not", +VarLikeNode["true"]], "to_s"],
|
44
|
+
}
|
45
|
+
|
46
|
+
def test_ruby19_equivs
|
47
|
+
RUBY_1_9_TO_1_8_EQUIVALENCES.each{|pair|
|
48
|
+
new,old=pair.first,pair.last
|
49
|
+
pt19=RedParse.new(new,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
|
50
|
+
pt18=RedParse.new(old,'(eval)',1,[],:cache_mode=>:none).parse
|
51
|
+
assert_equal pt18,pt19
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_ruby19_equivs_but_for_stresc
|
56
|
+
RUBY_1_9_TO_1_8_EQUIVALENCES_BUT_FOR_STRESC.each{|pair|
|
57
|
+
new,old=pair.first,pair.last
|
58
|
+
pt19=RedParse.new(new,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
|
59
|
+
pt18=RedParse.new(old,'(eval)',1,[],:cache_mode=>:none).parse
|
60
|
+
if pt18.instance_variable_get(:@bs_handler)==:dquote_esc_seq
|
61
|
+
pt18.instance_variable_set :@bs_handler,:dquote19_esc_seq
|
62
|
+
else
|
63
|
+
pt18.instance_variable_set :@bs_handler,:Wquote19_esc_seq
|
64
|
+
pt18.instance_variable_get(:@parses_like).each{|x|
|
65
|
+
x.instance_variable_set :@bs_handler,:Wquote19_esc_seq if x.instance_variable_get :@bs_handler
|
66
|
+
}
|
67
|
+
end
|
68
|
+
assert_equal pt18,pt19
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_ruby19_valid
|
73
|
+
RUBY_1_9_VALID.each{|xmpl|
|
74
|
+
pt19=RedParse.new(xmpl,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
|
75
|
+
assert_nil pt19.errors
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_ruby19_patterns
|
80
|
+
RUBY_1_9_PATTERNS.each_pair{|code,pattern|
|
81
|
+
pt=RedParse.new(code,'(eval)',1,[],:rubyversion=>1.9,:cache_mode=>:none).parse
|
82
|
+
assert_match pattern, pt
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
include Ruby1_9OneLiners
|
90
|
+
|
91
|
+
def count_methods(tree)
|
92
|
+
count=0
|
93
|
+
tree.walk{|node|
|
94
|
+
case node
|
95
|
+
when CallSiteNode, MethodNode; count+=1
|
96
|
+
end
|
97
|
+
}
|
98
|
+
return count
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_1_9
|
102
|
+
EXPECT_NO_METHODS.each{|snippet|
|
103
|
+
tree=RedParse.new(snippet,"-e").parse
|
104
|
+
count=count_methods(tree)
|
105
|
+
assert_equal count,0
|
106
|
+
}
|
107
|
+
|
108
|
+
EXPECT_1_METHOD.each{|snippet|
|
109
|
+
tree=RedParse.new(snippet,"-e").parse
|
110
|
+
count=count_methods(tree)
|
111
|
+
assert_equal count,1
|
112
|
+
}
|
113
|
+
end
|
114
|
+
end
|