ruby_parser 3.0.0 → 3.19.1
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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.autotest +36 -19
- data/History.rdoc +1297 -0
- data/Manifest.txt +35 -7
- data/{README.txt → README.rdoc} +44 -14
- data/Rakefile +308 -110
- data/bin/ruby_parse +3 -1
- data/bin/ruby_parse_extract_error +36 -16
- data/compare/normalize.rb +218 -0
- data/debugging.md +190 -0
- data/gauntlet.md +107 -0
- data/lib/.document +1 -0
- data/lib/rp_extensions.rb +53 -0
- data/lib/rp_stringscanner.rb +33 -0
- data/lib/ruby20_parser.rb +10973 -0
- data/lib/ruby20_parser.y +2683 -0
- data/lib/ruby21_parser.rb +10980 -0
- data/lib/ruby21_parser.y +2700 -0
- data/lib/ruby22_parser.rb +11123 -0
- data/lib/ruby22_parser.y +2711 -0
- data/lib/ruby23_parser.rb +11132 -0
- data/lib/ruby23_parser.y +2713 -0
- data/lib/ruby24_parser.rb +11231 -0
- data/lib/ruby24_parser.y +2721 -0
- data/lib/ruby25_parser.rb +11231 -0
- data/lib/ruby25_parser.y +2721 -0
- data/lib/ruby26_parser.rb +11253 -0
- data/lib/ruby26_parser.y +2736 -0
- data/lib/ruby27_parser.rb +12980 -0
- data/lib/ruby27_parser.y +3324 -0
- data/lib/ruby30_parser.rb +13242 -0
- data/lib/ruby30_parser.y +3447 -0
- data/lib/ruby31_parser.rb +13622 -0
- data/lib/ruby31_parser.y +3481 -0
- data/lib/ruby3_parser.yy +3536 -0
- data/lib/ruby_lexer.rb +933 -1232
- data/lib/ruby_lexer.rex +185 -0
- data/lib/ruby_lexer.rex.rb +399 -0
- data/lib/ruby_lexer_strings.rb +638 -0
- data/lib/ruby_parser.rb +97 -3
- data/lib/ruby_parser.yy +3465 -0
- data/lib/ruby_parser_extras.rb +1216 -687
- data/test/test_ruby_lexer.rb +2249 -1092
- data/test/test_ruby_parser.rb +5156 -975
- data/test/test_ruby_parser_extras.rb +47 -77
- data/tools/munge.rb +250 -0
- data/tools/ripper.rb +44 -0
- data.tar.gz.sig +1 -1
- metadata +200 -155
- metadata.gz.sig +0 -0
- data/.gemtest +0 -0
- data/History.txt +0 -482
- data/lib/gauntlet_rubyparser.rb +0 -120
- data/lib/ruby18_parser.rb +0 -5747
- data/lib/ruby18_parser.y +0 -1873
- data/lib/ruby19_parser.rb +0 -6110
- data/lib/ruby19_parser.y +0 -2078
data/Manifest.txt
CHANGED
@@ -1,18 +1,46 @@
|
|
1
1
|
.autotest
|
2
|
-
History.
|
2
|
+
History.rdoc
|
3
3
|
Manifest.txt
|
4
|
-
README.
|
4
|
+
README.rdoc
|
5
5
|
Rakefile
|
6
6
|
bin/ruby_parse
|
7
7
|
bin/ruby_parse_extract_error
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
lib
|
12
|
-
lib/
|
8
|
+
compare/normalize.rb
|
9
|
+
debugging.md
|
10
|
+
gauntlet.md
|
11
|
+
lib/.document
|
12
|
+
lib/rp_extensions.rb
|
13
|
+
lib/rp_stringscanner.rb
|
14
|
+
lib/ruby20_parser.rb
|
15
|
+
lib/ruby20_parser.y
|
16
|
+
lib/ruby21_parser.rb
|
17
|
+
lib/ruby21_parser.y
|
18
|
+
lib/ruby22_parser.rb
|
19
|
+
lib/ruby22_parser.y
|
20
|
+
lib/ruby23_parser.rb
|
21
|
+
lib/ruby23_parser.y
|
22
|
+
lib/ruby24_parser.rb
|
23
|
+
lib/ruby24_parser.y
|
24
|
+
lib/ruby25_parser.rb
|
25
|
+
lib/ruby25_parser.y
|
26
|
+
lib/ruby26_parser.rb
|
27
|
+
lib/ruby26_parser.y
|
28
|
+
lib/ruby27_parser.rb
|
29
|
+
lib/ruby27_parser.y
|
30
|
+
lib/ruby30_parser.rb
|
31
|
+
lib/ruby30_parser.y
|
32
|
+
lib/ruby31_parser.rb
|
33
|
+
lib/ruby31_parser.y
|
34
|
+
lib/ruby3_parser.yy
|
13
35
|
lib/ruby_lexer.rb
|
36
|
+
lib/ruby_lexer.rex
|
37
|
+
lib/ruby_lexer.rex.rb
|
38
|
+
lib/ruby_lexer_strings.rb
|
14
39
|
lib/ruby_parser.rb
|
40
|
+
lib/ruby_parser.yy
|
15
41
|
lib/ruby_parser_extras.rb
|
16
42
|
test/test_ruby_lexer.rb
|
17
43
|
test/test_ruby_parser.rb
|
18
44
|
test/test_ruby_parser_extras.rb
|
45
|
+
tools/munge.rb
|
46
|
+
tools/ripper.rb
|
data/{README.txt → README.rdoc}
RENAMED
@@ -7,25 +7,35 @@ rdoc :: http://docs.seattlerb.org/ruby_parser
|
|
7
7
|
== DESCRIPTION:
|
8
8
|
|
9
9
|
ruby_parser (RP) is a ruby parser written in pure ruby (utilizing
|
10
|
-
racc--which does by default use a C extension).
|
11
|
-
|
12
|
-
|
10
|
+
racc--which does by default use a C extension). It outputs
|
11
|
+
s-expressions which can be manipulated and converted back to ruby via
|
12
|
+
the ruby2ruby gem.
|
13
13
|
|
14
14
|
As an example:
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def conditional1 arg1
|
17
|
+
return 1 if arg1 == 0
|
18
|
+
return 0
|
19
|
+
end
|
20
20
|
|
21
21
|
becomes:
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
s(:defn, :conditional1, s(:args, :arg1),
|
24
|
+
s(:if,
|
25
|
+
s(:call, s(:lvar, :arg1), :==, s(:lit, 0)),
|
26
|
+
s(:return, s(:lit, 1)),
|
27
|
+
nil),
|
28
|
+
s(:return, s(:lit, 0)))
|
29
|
+
|
30
|
+
Tested against 801,039 files from the latest of all rubygems (as of 2013-05):
|
31
|
+
|
32
|
+
* 1.8 parser is at 99.9739% accuracy, 3.651 sigma
|
33
|
+
* 1.9 parser is at 99.9940% accuracy, 4.013 sigma
|
34
|
+
* 2.0 parser is at 99.9939% accuracy, 4.008 sigma
|
35
|
+
* 2.6 parser is at 99.9972% accuracy, 4.191 sigma
|
36
|
+
* 3.0 parser has a 100% parse rate.
|
37
|
+
* Tested against 2,672,412 unique ruby files across 167k gems.
|
38
|
+
* As do all the others now, basically.
|
29
39
|
|
30
40
|
== FEATURES/PROBLEMS:
|
31
41
|
|
@@ -43,9 +53,29 @@ becomes:
|
|
43
53
|
|
44
54
|
== SYNOPSIS:
|
45
55
|
|
46
|
-
|
56
|
+
RubyParser.new.parse "1+1"
|
57
|
+
# => s(:call, s(:lit, 1), :+, s(:lit, 1))
|
58
|
+
|
59
|
+
You can also use Ruby19Parser, Ruby18Parser, or RubyParser.for_current_ruby:
|
60
|
+
|
61
|
+
RubyParser.for_current_ruby.parse "1+1"
|
47
62
|
# => s(:call, s(:lit, 1), :+, s(:lit, 1))
|
48
63
|
|
64
|
+
== DEVELOPER NOTES:
|
65
|
+
|
66
|
+
To add a new version:
|
67
|
+
|
68
|
+
* New parser should be generated from lib/ruby[3]_parser.yy.
|
69
|
+
* Extend lib/ruby[3]_parser.yy with new class name.
|
70
|
+
* Add new version number to V2/V3 in Rakefile for rule creation.
|
71
|
+
* Add new (full) version to `ruby_parse` section of Rakefile for rake compare
|
72
|
+
* Require generated parser in lib/ruby_parser.rb.
|
73
|
+
* Add empty TestRubyParserShared##Plus module and TestRubyParserV## to test/test_ruby_parser.rb.
|
74
|
+
* Extend Manifest.txt with generated file names.
|
75
|
+
* Add new version number to sexp_processor's pt_testcase.rb in all_versions
|
76
|
+
|
77
|
+
Until all of these are done, you won't have a clean test run.
|
78
|
+
|
49
79
|
== REQUIREMENTS:
|
50
80
|
|
51
81
|
* ruby. woot.
|
data/Rakefile
CHANGED
@@ -1,107 +1,131 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "rubygems"
|
4
|
+
require "hoe"
|
5
5
|
|
6
6
|
Hoe.plugin :seattlerb
|
7
7
|
Hoe.plugin :racc
|
8
8
|
Hoe.plugin :isolate
|
9
|
+
Hoe.plugin :rdoc
|
9
10
|
|
11
|
+
Hoe.add_include_dirs "lib"
|
10
12
|
Hoe.add_include_dirs "../../sexp_processor/dev/lib"
|
13
|
+
Hoe.add_include_dirs "../../minitest/dev/lib"
|
14
|
+
Hoe.add_include_dirs "../../oedipus_lex/dev/lib"
|
11
15
|
|
12
|
-
|
13
|
-
|
16
|
+
V2 = %w[20 21 22 23 24 25 26 27]
|
17
|
+
V3 = %w[30 31]
|
14
18
|
|
15
|
-
|
19
|
+
VERS = V2 + V3
|
16
20
|
|
17
|
-
|
21
|
+
ENV["FAST"] = VERS.last if ENV["FAST"] && !VERS.include?(ENV["FAST"])
|
22
|
+
VERS.replace [ENV["FAST"]] if ENV["FAST"]
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
self.perforce_ignore << "lib/ruby19_parser.rb"
|
22
|
-
end
|
24
|
+
Hoe.spec "ruby_parser" do
|
25
|
+
developer "Ryan Davis", "ryand-ruby@zenspider.com"
|
23
26
|
|
24
|
-
|
25
|
-
end
|
27
|
+
license "MIT"
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
+
dependency "sexp_processor", "~> 4.16"
|
30
|
+
dependency "rake", [">= 10", "< 15"], :developer
|
31
|
+
dependency "oedipus_lex", "~> 2.6", :developer
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
Dir["coverage"] +
|
35
|
-
Dir["lib/*.output"])
|
36
|
-
end
|
33
|
+
# NOTE: Ryan!!! Stop trying to fix this dependency! Isolate just
|
34
|
+
# can't handle having a faux-gem half-installed! Stop! Just `gem
|
35
|
+
# install racc` and move on. Revisit this ONLY once racc-compiler
|
36
|
+
# gets split out.
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
dependency "racc", "~> 1.5", :developer
|
39
|
+
|
40
|
+
require_ruby_version [">= 2.1", "< 4"]
|
41
|
+
|
42
|
+
if plugin? :perforce then # generated files
|
43
|
+
VERS.each do |n|
|
44
|
+
self.perforce_ignore << "lib/ruby#{n}_parser.rb"
|
45
|
+
end
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
puts file
|
48
|
-
system "./cmp.rb -q #{file} && rm #{file}"
|
47
|
+
VERS.each do |n|
|
48
|
+
self.perforce_ignore << "lib/ruby#{n}_parser.y"
|
49
|
+
end
|
50
|
+
|
51
|
+
self.perforce_ignore << "lib/ruby_lexer.rex.rb"
|
49
52
|
end
|
50
|
-
system 'find -d unit -type d -empty -exec rmdir {} \;'
|
51
|
-
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
files.each do |file|
|
58
|
-
puts file
|
59
|
-
sh "./cmp.rb -q #{file}"
|
54
|
+
if plugin?(:racc)
|
55
|
+
self.racc_flags << " -t" if ENV["DEBUG"]
|
56
|
+
self.racc_flags << " --superclass RubyParser::Parser"
|
57
|
+
# self.racc_flags << " --runtime ruby_parser" # TODO: broken in racc
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
63
|
-
|
64
|
-
|
65
|
-
sh 'grepsort "^ +def (test|util)" test/test_ruby_lexer.rb'
|
66
|
-
end
|
61
|
+
def maybe_add_to_top path, string
|
62
|
+
file = File.read path
|
67
63
|
|
68
|
-
|
69
|
-
loc1 = `wc -l ../1.0.0/lib/ruby_lexer.rb`[/\d+/]
|
70
|
-
flog1 = `flog -s ../1.0.0/lib/ruby_lexer.rb`[/\d+\.\d+/]
|
71
|
-
loc2 = `cat lib/ruby_lexer.rb lib/ruby_parser_extras.rb | wc -l`[/\d+/]
|
72
|
-
flog2 = `flog -s lib/ruby_lexer.rb lib/ruby_parser_extras.rb`[/\d+\.\d+/]
|
64
|
+
return if file.start_with? string
|
73
65
|
|
74
|
-
|
66
|
+
warn "Altering top of #{path}"
|
67
|
+
tmp_path = "#{path}.tmp"
|
68
|
+
File.open(tmp_path, "w") do |f|
|
69
|
+
f.puts string
|
70
|
+
f.puts
|
75
71
|
|
76
|
-
|
77
|
-
|
78
|
-
|
72
|
+
f.write file
|
73
|
+
# TODO: make this deal with encoding comments properly?
|
74
|
+
end
|
75
|
+
File.rename tmp_path, path
|
79
76
|
end
|
80
77
|
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
def unifdef?
|
79
|
+
@unifdef ||= system("which unifdef") or abort <<~EOM
|
80
|
+
unifdef not found!
|
81
|
+
|
82
|
+
Please install 'unifdef' package on your system or `rake generate` on a mac.
|
83
|
+
EOM
|
84
84
|
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
86
|
+
V2.each do |n|
|
87
|
+
file "lib/ruby#{n}_parser.y" => "lib/ruby_parser.yy" do |t|
|
88
|
+
unifdef?
|
89
|
+
cmd = 'unifdef -tk -DV=%s -UDEAD %s > %s || true' % [n, t.source, t.name]
|
90
|
+
sh cmd
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
+
file "lib/ruby#{n}_parser.rb" => "lib/ruby#{n}_parser.y"
|
94
|
+
end
|
95
|
+
|
96
|
+
V3.each do |n|
|
97
|
+
file "lib/ruby#{n}_parser.y" => "lib/ruby3_parser.yy" do |t|
|
98
|
+
unifdef?
|
99
|
+
cmd = 'unifdef -tk -DV=%s -UDEAD %s > %s || true' % [n, t.source, t.name]
|
100
|
+
sh cmd
|
101
|
+
end
|
93
102
|
|
94
|
-
|
103
|
+
file "lib/ruby#{n}_parser.rb" => "lib/ruby#{n}_parser.y"
|
95
104
|
end
|
96
105
|
|
97
|
-
|
98
|
-
|
99
|
-
|
106
|
+
file "lib/ruby_lexer.rex.rb" => "lib/ruby_lexer.rex"
|
107
|
+
|
108
|
+
task :parser do |t|
|
109
|
+
t.prerequisite_tasks.grep(Rake::FileTask).select(&:already_invoked).each do |f|
|
110
|
+
maybe_add_to_top f.name, "# frozen_string_literal: true"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
task :generate => [:lexer, :parser]
|
115
|
+
|
116
|
+
task :clean do
|
117
|
+
rm_rf(Dir["**/*~"] +
|
118
|
+
Dir["diff.diff"] + # not all diffs. bit me too many times
|
119
|
+
Dir["coverage.info"] +
|
120
|
+
Dir["coverage"] +
|
121
|
+
Dir["lib/ruby2*_parser.y"] +
|
122
|
+
Dir["lib/ruby3*_parser.y"] +
|
123
|
+
Dir["lib/*.output"])
|
100
124
|
end
|
101
125
|
|
102
|
-
|
103
|
-
|
104
|
-
|
126
|
+
task :sort do
|
127
|
+
sh "grepsort '^ +def' lib/ruby_lexer.rb"
|
128
|
+
sh "grepsort '^ +def (test|util)' test/test_ruby_lexer.rb"
|
105
129
|
end
|
106
130
|
|
107
131
|
desc "what was that command again?"
|
@@ -109,80 +133,254 @@ task :huh? do
|
|
109
133
|
puts "ruby #{Hoe::RUBY_FLAGS} bin/ruby_parse -q -g ..."
|
110
134
|
end
|
111
135
|
|
112
|
-
task :irb => [:isolate] do
|
113
|
-
sh "GEM_HOME=#{Gem.path.first} irb -rubygems -Ilib -rruby_parser;"
|
114
|
-
end
|
115
|
-
|
116
136
|
def (task(:phony)).timestamp
|
117
137
|
Time.at 0
|
118
138
|
end
|
119
139
|
|
120
140
|
task :isolate => :phony
|
121
141
|
|
122
|
-
|
123
|
-
|
142
|
+
def in_compare
|
143
|
+
Dir.chdir "compare" do
|
144
|
+
yield
|
145
|
+
end
|
146
|
+
end
|
124
147
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
148
|
+
def dl v
|
149
|
+
dir = v[/^\d+\.\d+/]
|
150
|
+
url = "https://cache.ruby-lang.org/pub/ruby/#{dir}/ruby-#{v}.tar.xz"
|
151
|
+
path = File.basename url
|
152
|
+
unless File.exist? path then
|
153
|
+
system "curl -O #{url}"
|
154
|
+
end
|
131
155
|
end
|
132
156
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
157
|
+
def ruby_parse version
|
158
|
+
v = version[/^\d+\.\d+/].delete "."
|
159
|
+
rp_txt = "rp#{v}.txt"
|
160
|
+
mri_txt = "mri#{v}.txt"
|
161
|
+
parse_y = "parse#{v}.y"
|
162
|
+
tarball = "ruby-#{version}.tar.xz"
|
163
|
+
ruby_dir = "ruby-#{version}"
|
164
|
+
diff = "diff#{v}.diff"
|
165
|
+
rp_out = "lib/ruby#{v}_parser.output"
|
166
|
+
_rp_y = "lib/ruby#{v}_parser.y"
|
167
|
+
rp_y_rb = "lib/ruby#{v}_parser.rb"
|
168
|
+
|
169
|
+
c_diff = "compare/#{diff}"
|
170
|
+
c_rp_txt = "compare/#{rp_txt}"
|
171
|
+
c_mri_txt = "compare/#{mri_txt}"
|
172
|
+
c_parse_y = "compare/#{parse_y}"
|
173
|
+
c_tarball = "compare/#{tarball}"
|
174
|
+
normalize = "compare/normalize.rb"
|
175
|
+
|
176
|
+
file c_tarball do
|
177
|
+
in_compare do
|
178
|
+
dl version
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
desc "fetch all tarballs"
|
183
|
+
task :fetch => c_tarball
|
184
|
+
|
185
|
+
file c_parse_y => c_tarball do
|
186
|
+
in_compare do
|
187
|
+
extract_glob = case
|
188
|
+
when version > "2.7" then
|
189
|
+
"{id.h,parse.y,tool/{id2token.rb,lib/vpath.rb}}"
|
190
|
+
else
|
191
|
+
"{id.h,parse.y,tool/{id2token.rb,vpath.rb}}"
|
192
|
+
end
|
193
|
+
system "tar Jxf #{tarball} #{ruby_dir}/#{extract_glob}"
|
194
|
+
|
195
|
+
Dir.chdir ruby_dir do
|
196
|
+
if File.exist? "tool/id2token.rb" then
|
197
|
+
sh "ruby tool/id2token.rb --path-separator=.:./ id.h parse.y | expand > ../#{parse_y}"
|
198
|
+
else
|
199
|
+
sh "expand parse.y > ../#{parse_y}"
|
200
|
+
end
|
201
|
+
|
202
|
+
ruby "-pi", "-e", 'gsub(/^%pure-parser/, "%define api.pure")', "../#{parse_y}"
|
203
|
+
end
|
204
|
+
sh "rm -rf #{ruby_dir}"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
bison = Dir["/opt/homebrew/opt/bison/bin/bison",
|
209
|
+
"/usr/local/opt/bison/bin/bison",
|
210
|
+
`which bison`.chomp,
|
211
|
+
].first
|
212
|
+
|
213
|
+
file c_mri_txt => [c_parse_y, normalize] do
|
214
|
+
in_compare do
|
215
|
+
sh "#{bison} -r all #{parse_y}"
|
216
|
+
sh "./normalize.rb parse#{v}.output > #{mri_txt}"
|
217
|
+
rm ["parse#{v}.output", "parse#{v}.tab.c"]
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
file rp_out => rp_y_rb
|
222
|
+
|
223
|
+
file c_rp_txt => [rp_out, normalize] do
|
224
|
+
in_compare do
|
225
|
+
sh "./normalize.rb ../#{rp_out} > #{rp_txt}"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
compare = "compare#{v}"
|
230
|
+
|
231
|
+
desc "Compare all grammars to MRI"
|
232
|
+
task :compare => compare
|
233
|
+
|
234
|
+
file c_diff => [c_mri_txt, c_rp_txt] do
|
235
|
+
in_compare do
|
236
|
+
sh "diff -du #{mri_txt} #{rp_txt} > #{diff}; true"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
desc "Compare #{v} grammar to MRI #{version}"
|
241
|
+
task compare => c_diff do
|
242
|
+
in_compare do
|
243
|
+
system "wc -l #{diff}"
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
task :clean do
|
248
|
+
rm_f Dir[c_mri_txt, c_rp_txt]
|
249
|
+
end
|
250
|
+
|
251
|
+
task :realclean do
|
252
|
+
rm_f Dir[c_parse_y, tarball]
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
task :versions do
|
257
|
+
require "open-uri"
|
258
|
+
require "net/http" # avoid require issues in threads
|
259
|
+
require "net/https"
|
260
|
+
|
261
|
+
versions = VERS.map { |s| s.split(//).join "." }
|
262
|
+
|
263
|
+
base_url = "https://cache.ruby-lang.org/pub/ruby"
|
264
|
+
|
265
|
+
class Array
|
266
|
+
def human_sort
|
267
|
+
sort_by { |item| item.to_s.split(/(\d+)/).map { |e| [e.to_i, e] } }
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
versions = versions.map { |ver|
|
272
|
+
Thread.new {
|
273
|
+
URI
|
274
|
+
.parse("#{base_url}/#{ver}/")
|
275
|
+
.read
|
276
|
+
.scan(/ruby-\d+\.\d+\.\d+[-\w.]*?.tar.gz/)
|
277
|
+
.reject { |s| s =~ /-(?:rc|preview)\d/ }
|
278
|
+
.human_sort
|
279
|
+
.last
|
280
|
+
.delete_prefix("ruby-")
|
281
|
+
.delete_suffix ".tar.gz"
|
282
|
+
}
|
283
|
+
}.map(&:value).sort
|
284
|
+
|
285
|
+
puts versions.map { |v| "ruby_parse %p" % [v] }
|
139
286
|
end
|
140
287
|
|
288
|
+
ruby_parse "2.0.0-p648"
|
289
|
+
ruby_parse "2.1.10"
|
290
|
+
ruby_parse "2.2.10"
|
291
|
+
ruby_parse "2.3.8"
|
292
|
+
ruby_parse "2.4.10"
|
293
|
+
ruby_parse "2.5.9"
|
294
|
+
ruby_parse "2.6.9"
|
295
|
+
ruby_parse "2.7.5"
|
296
|
+
ruby_parse "3.0.3"
|
297
|
+
ruby_parse "3.1.1"
|
298
|
+
|
141
299
|
task :debug => :isolate do
|
142
|
-
ENV["V"] ||=
|
300
|
+
ENV["V"] ||= VERS.last
|
143
301
|
Rake.application[:parser].invoke # this way we can have DEBUG set
|
302
|
+
Rake.application[:lexer].invoke # this way we can have DEBUG set
|
303
|
+
|
304
|
+
$:.unshift "lib"
|
305
|
+
require "ruby_parser"
|
306
|
+
require "pp"
|
144
307
|
|
145
|
-
|
146
|
-
|
308
|
+
klass = Object.const_get("Ruby#{ENV["V"]}Parser") rescue nil
|
309
|
+
raise "Unsupported version #{ENV["V"]}" unless klass
|
310
|
+
parser = klass.new
|
147
311
|
|
148
|
-
|
149
|
-
Ruby18Parser.new
|
150
|
-
else
|
151
|
-
Ruby19Parser.new
|
152
|
-
end
|
312
|
+
time = (ENV["RP_TIMEOUT"] || 10).to_i
|
153
313
|
|
154
|
-
|
314
|
+
n = ENV["BUG"]
|
315
|
+
file = (n && "bug#{n}.rb") || ENV["F"] || ENV["FILE"] || "debug.rb"
|
316
|
+
ruby = ENV["R"] || ENV["RUBY"]
|
317
|
+
|
318
|
+
if ruby then
|
319
|
+
file = "env"
|
320
|
+
else
|
321
|
+
ruby = File.read file
|
322
|
+
end
|
155
323
|
|
156
|
-
ruby = if file then
|
157
|
-
File.read(file)
|
158
|
-
else
|
159
|
-
file = "env"
|
160
|
-
ENV["R"] || ENV["RUBY"]
|
161
|
-
end
|
162
324
|
|
163
325
|
begin
|
164
|
-
|
165
|
-
rescue Racc::ParseError => e
|
326
|
+
pp parser.process(ruby, file, time)
|
327
|
+
rescue ArgumentError, Racc::ParseError => e
|
166
328
|
p e
|
167
|
-
|
329
|
+
puts e.backtrace.join "\n "
|
330
|
+
ss = parser.lexer.ss
|
168
331
|
src = ss.string
|
169
332
|
lines = src[0..ss.pos].split(/\n/)
|
170
333
|
abort "on #{file}:#{lines.size}"
|
171
334
|
end
|
172
335
|
end
|
173
336
|
|
174
|
-
task :
|
175
|
-
file
|
176
|
-
|
337
|
+
task :debug3 do
|
338
|
+
file = ENV["F"] || "debug.rb"
|
339
|
+
version = ENV["V"] || ""
|
340
|
+
verbose = ENV["VERBOSE"] ? "-v" : ""
|
341
|
+
munge = "./tools/munge.rb #{verbose}"
|
342
|
+
|
343
|
+
abort "Need a file to parse, via: F=path.rb" unless file
|
344
|
+
|
345
|
+
ENV.delete "V"
|
346
|
+
|
347
|
+
ruby = "ruby#{version}"
|
348
|
+
|
349
|
+
sh "#{ruby} -v"
|
350
|
+
sh "#{ruby} -y #{file} 2>&1 | #{munge} > tmp/ruby"
|
351
|
+
sh "#{ruby} ./tools/ripper.rb -d #{file} | #{munge} > tmp/rip"
|
352
|
+
sh "rake debug F=#{file} DEBUG=1 2>&1 | #{munge} > tmp/rp"
|
353
|
+
sh "diff -U 999 -d tmp/{ruby,rp}"
|
354
|
+
end
|
355
|
+
|
356
|
+
task :cmp do
|
357
|
+
sh %(emacsclient --eval '(ediff-files "tmp/ruby" "tmp/rp")')
|
358
|
+
end
|
359
|
+
|
360
|
+
task :cmp3 do
|
361
|
+
sh %(emacsclient --eval '(ediff-files3 "tmp/ruby" "tmp/rip" "tmp/rp")')
|
177
362
|
end
|
178
363
|
|
179
364
|
task :extract => :isolate do
|
180
|
-
ENV["V"] ||=
|
365
|
+
ENV["V"] ||= VERS.last
|
181
366
|
Rake.application[:parser].invoke # this way we can have DEBUG set
|
182
367
|
|
183
|
-
file = ENV["F"] || ENV["FILE"]
|
368
|
+
file = ENV["F"] || ENV["FILE"] || abort("Need to provide F=<path>")
|
184
369
|
|
185
370
|
ruby "-Ilib", "bin/ruby_parse_extract_error", file
|
186
371
|
end
|
187
372
|
|
373
|
+
task :parse => :isolate do
|
374
|
+
ENV["V"] ||= VERS.last
|
375
|
+
Rake.application[:parser].invoke # this way we can have DEBUG set
|
376
|
+
|
377
|
+
file = ENV["F"] || ENV["FILE"] || abort("Need to provide F=<path>")
|
378
|
+
|
379
|
+
ruby "-Ilib", "bin/ruby_parse", file
|
380
|
+
end
|
381
|
+
|
382
|
+
task :bugs do
|
383
|
+
sh "for f in bug*.rb bad*.rb ; do #{Gem.ruby} -S rake debug F=$f && rm $f ; done"
|
384
|
+
end
|
385
|
+
|
188
386
|
# vim: syntax=Ruby
|
data/bin/ruby_parse
CHANGED
@@ -26,6 +26,8 @@ class File
|
|
26
26
|
end
|
27
27
|
|
28
28
|
begin
|
29
|
+
time = (ENV["RP_TIMEOUT"] || 10).to_i
|
30
|
+
|
29
31
|
ARGV.each do |file|
|
30
32
|
rp = RubyParser.new
|
31
33
|
loc = `wc -l #{file}`.strip.to_i
|
@@ -45,7 +47,7 @@ begin
|
|
45
47
|
begin
|
46
48
|
begin
|
47
49
|
rp.reset
|
48
|
-
r = rp.
|
50
|
+
r = rp.process(File.binread(file), file, time)
|
49
51
|
pp r unless $q
|
50
52
|
good += 1
|
51
53
|
rescue SyntaxError => e
|