ruby_parser 3.12.0 → 3.18.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.autotest +18 -29
- data/History.rdoc +283 -0
- data/Manifest.txt +12 -4
- data/README.rdoc +4 -3
- data/Rakefile +189 -51
- data/bin/ruby_parse +3 -1
- data/bin/ruby_parse_extract_error +19 -36
- data/compare/normalize.rb +76 -4
- data/debugging.md +190 -0
- data/gauntlet.md +106 -0
- data/lib/rp_extensions.rb +14 -42
- data/lib/rp_stringscanner.rb +20 -51
- data/lib/ruby20_parser.rb +4659 -4218
- data/lib/ruby20_parser.y +953 -602
- data/lib/ruby21_parser.rb +4723 -4308
- data/lib/ruby21_parser.y +956 -605
- data/lib/ruby22_parser.rb +4762 -4337
- data/lib/ruby22_parser.y +960 -612
- data/lib/ruby23_parser.rb +4761 -4342
- data/lib/ruby23_parser.y +961 -613
- data/lib/ruby24_parser.rb +4791 -4341
- data/lib/ruby24_parser.y +968 -612
- data/lib/ruby25_parser.rb +4791 -4341
- data/lib/ruby25_parser.y +968 -612
- data/lib/ruby26_parser.rb +7287 -0
- data/lib/ruby26_parser.y +2749 -0
- data/lib/ruby27_parser.rb +8517 -0
- data/lib/ruby27_parser.y +3346 -0
- data/lib/ruby30_parser.rb +8751 -0
- data/lib/ruby30_parser.y +3472 -0
- data/lib/ruby3_parser.yy +3476 -0
- data/lib/ruby_lexer.rb +611 -826
- data/lib/ruby_lexer.rex +48 -40
- data/lib/ruby_lexer.rex.rb +122 -46
- data/lib/ruby_lexer_strings.rb +638 -0
- data/lib/ruby_parser.rb +38 -34
- data/lib/ruby_parser.yy +1710 -704
- data/lib/ruby_parser_extras.rb +987 -553
- data/test/test_ruby_lexer.rb +1718 -1539
- data/test/test_ruby_parser.rb +3957 -2164
- data/test/test_ruby_parser_extras.rb +39 -4
- data/tools/munge.rb +250 -0
- data/tools/ripper.rb +44 -0
- data.tar.gz.sig +0 -0
- metadata +68 -47
- metadata.gz.sig +0 -0
- data/lib/ruby18_parser.rb +0 -5793
- data/lib/ruby18_parser.y +0 -1908
- data/lib/ruby19_parser.rb +0 -6185
- data/lib/ruby19_parser.y +0 -2116
data/Rakefile
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# -*- ruby -*-
|
2
2
|
|
3
|
-
$:.unshift "../../hoe/dev/lib"
|
4
|
-
|
5
3
|
require "rubygems"
|
6
4
|
require "hoe"
|
7
5
|
|
@@ -10,29 +8,43 @@ Hoe.plugin :racc
|
|
10
8
|
Hoe.plugin :isolate
|
11
9
|
Hoe.plugin :rdoc
|
12
10
|
|
11
|
+
Hoe.add_include_dirs "lib"
|
13
12
|
Hoe.add_include_dirs "../../sexp_processor/dev/lib"
|
14
13
|
Hoe.add_include_dirs "../../minitest/dev/lib"
|
15
14
|
Hoe.add_include_dirs "../../oedipus_lex/dev/lib"
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
V2 = %w[20 21 22 23 24 25 26 27]
|
17
|
+
V3 = %w[30]
|
18
|
+
|
19
|
+
VERS = V2 + V3
|
20
|
+
|
21
|
+
ENV["FAST"] = VERS.last if ENV["FAST"] && !VERS.include?(ENV["FAST"])
|
22
|
+
VERS.replace [ENV["FAST"]] if ENV["FAST"]
|
20
23
|
|
21
24
|
Hoe.spec "ruby_parser" do
|
22
25
|
developer "Ryan Davis", "ryand-ruby@zenspider.com"
|
23
26
|
|
24
27
|
license "MIT"
|
25
28
|
|
26
|
-
dependency "sexp_processor", "~> 4.
|
27
|
-
dependency "rake", "<
|
28
|
-
dependency "oedipus_lex", "~> 2.
|
29
|
+
dependency "sexp_processor", "~> 4.16"
|
30
|
+
dependency "rake", [">= 10", "< 15"], :developer
|
31
|
+
dependency "oedipus_lex", "~> 2.6", :developer
|
32
|
+
|
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
|
+
|
38
|
+
dependency "racc", "~> 1.5", :developer
|
39
|
+
|
40
|
+
require_ruby_version [">= 2.1", "< 4"]
|
29
41
|
|
30
42
|
if plugin? :perforce then # generated files
|
31
|
-
|
43
|
+
VERS.each do |n|
|
32
44
|
self.perforce_ignore << "lib/ruby#{n}_parser.rb"
|
33
45
|
end
|
34
46
|
|
35
|
-
|
47
|
+
VERS.each do |n|
|
36
48
|
self.perforce_ignore << "lib/ruby#{n}_parser.y"
|
37
49
|
end
|
38
50
|
|
@@ -46,25 +58,68 @@ Hoe.spec "ruby_parser" do
|
|
46
58
|
end
|
47
59
|
end
|
48
60
|
|
61
|
+
def maybe_add_to_top path, string
|
62
|
+
file = File.read path
|
63
|
+
|
64
|
+
return if file.start_with? string
|
65
|
+
|
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
|
71
|
+
|
72
|
+
f.write file
|
73
|
+
# TODO: make this deal with encoding comments properly?
|
74
|
+
end
|
75
|
+
File.rename tmp_path, path
|
76
|
+
end
|
77
|
+
|
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
|
+
end
|
85
|
+
|
49
86
|
V2.each do |n|
|
50
87
|
file "lib/ruby#{n}_parser.y" => "lib/ruby_parser.yy" do |t|
|
88
|
+
unifdef?
|
51
89
|
cmd = 'unifdef -tk -DV=%s -UDEAD %s > %s || true' % [n, t.source, t.name]
|
52
90
|
sh cmd
|
53
91
|
end
|
92
|
+
|
93
|
+
file "lib/ruby#{n}_parser.rb" => "lib/ruby#{n}_parser.y"
|
54
94
|
end
|
55
95
|
|
56
|
-
|
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
|
102
|
+
|
57
103
|
file "lib/ruby#{n}_parser.rb" => "lib/ruby#{n}_parser.y"
|
58
104
|
end
|
59
105
|
|
60
106
|
file "lib/ruby_lexer.rex.rb" => "lib/ruby_lexer.rex"
|
61
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
|
+
|
62
116
|
task :clean do
|
63
117
|
rm_rf(Dir["**/*~"] +
|
64
118
|
Dir["diff.diff"] + # not all diffs. bit me too many times
|
65
119
|
Dir["coverage.info"] +
|
66
120
|
Dir["coverage"] +
|
67
121
|
Dir["lib/ruby2*_parser.y"] +
|
122
|
+
Dir["lib/ruby3*_parser.y"] +
|
68
123
|
Dir["lib/*.output"])
|
69
124
|
end
|
70
125
|
|
@@ -78,10 +133,6 @@ task :huh? do
|
|
78
133
|
puts "ruby #{Hoe::RUBY_FLAGS} bin/ruby_parse -q -g ..."
|
79
134
|
end
|
80
135
|
|
81
|
-
task :irb => [:isolate] do
|
82
|
-
sh "GEM_HOME=#{Gem.path.first} irb -rubygems -Ilib -rruby_parser;"
|
83
|
-
end
|
84
|
-
|
85
136
|
def (task(:phony)).timestamp
|
86
137
|
Time.at 0
|
87
138
|
end
|
@@ -96,7 +147,7 @@ end
|
|
96
147
|
|
97
148
|
def dl v
|
98
149
|
dir = v[/^\d+\.\d+/]
|
99
|
-
url = "https://cache.ruby-lang.org/pub/ruby/#{dir}/ruby-#{v}.tar.
|
150
|
+
url = "https://cache.ruby-lang.org/pub/ruby/#{dir}/ruby-#{v}.tar.xz"
|
100
151
|
path = File.basename url
|
101
152
|
unless File.exist? path then
|
102
153
|
system "curl -O #{url}"
|
@@ -108,48 +159,68 @@ def ruby_parse version
|
|
108
159
|
rp_txt = "rp#{v}.txt"
|
109
160
|
mri_txt = "mri#{v}.txt"
|
110
161
|
parse_y = "parse#{v}.y"
|
111
|
-
tarball = "ruby-#{version}.tar.
|
162
|
+
tarball = "ruby-#{version}.tar.xz"
|
112
163
|
ruby_dir = "ruby-#{version}"
|
113
164
|
diff = "diff#{v}.diff"
|
114
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"
|
115
168
|
|
116
169
|
c_diff = "compare/#{diff}"
|
117
170
|
c_rp_txt = "compare/#{rp_txt}"
|
118
171
|
c_mri_txt = "compare/#{mri_txt}"
|
119
172
|
c_parse_y = "compare/#{parse_y}"
|
120
173
|
c_tarball = "compare/#{tarball}"
|
174
|
+
normalize = "compare/normalize.rb"
|
121
175
|
|
122
|
-
file
|
176
|
+
file c_tarball do
|
123
177
|
in_compare do
|
124
178
|
dl version
|
125
179
|
end
|
126
180
|
end
|
127
181
|
|
182
|
+
desc "fetch all tarballs"
|
183
|
+
task :fetch => c_tarball
|
184
|
+
|
128
185
|
file c_parse_y => c_tarball do
|
129
186
|
in_compare do
|
130
|
-
|
187
|
+
extract_glob = case version
|
188
|
+
when /2\.7|3\.0/
|
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
|
+
|
131
195
|
Dir.chdir ruby_dir do
|
132
196
|
if File.exist? "tool/id2token.rb" then
|
133
|
-
sh "ruby tool/id2token.rb --path-separator=.:./ id.h parse.y > ../#{parse_y}"
|
197
|
+
sh "ruby tool/id2token.rb --path-separator=.:./ id.h parse.y | expand > ../#{parse_y}"
|
134
198
|
else
|
135
|
-
|
199
|
+
sh "expand parse.y > ../#{parse_y}"
|
136
200
|
end
|
201
|
+
|
202
|
+
ruby "-pi", "-e", 'gsub(/^%pure-parser/, "%define api.pure")', "../#{parse_y}"
|
137
203
|
end
|
138
204
|
sh "rm -rf #{ruby_dir}"
|
139
205
|
end
|
140
206
|
end
|
141
207
|
|
142
|
-
|
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
|
143
214
|
in_compare do
|
144
|
-
sh "bison -r all #{parse_y}"
|
215
|
+
sh "#{bison} -r all #{parse_y}"
|
145
216
|
sh "./normalize.rb parse#{v}.output > #{mri_txt}"
|
146
217
|
rm ["parse#{v}.output", "parse#{v}.tab.c"]
|
147
218
|
end
|
148
219
|
end
|
149
220
|
|
150
|
-
file rp_out =>
|
221
|
+
file rp_out => rp_y_rb
|
151
222
|
|
152
|
-
file c_rp_txt => rp_out do
|
223
|
+
file c_rp_txt => [rp_out, normalize] do
|
153
224
|
in_compare do
|
154
225
|
sh "./normalize.rb ../#{rp_out} > #{rp_txt}"
|
155
226
|
end
|
@@ -160,9 +231,9 @@ def ruby_parse version
|
|
160
231
|
desc "Compare all grammars to MRI"
|
161
232
|
task :compare => compare
|
162
233
|
|
163
|
-
|
234
|
+
file c_diff => [c_mri_txt, c_rp_txt] do
|
164
235
|
in_compare do
|
165
|
-
|
236
|
+
sh "diff -du #{mri_txt} #{rp_txt} > #{diff}; true"
|
166
237
|
end
|
167
238
|
end
|
168
239
|
|
@@ -174,28 +245,62 @@ def ruby_parse version
|
|
174
245
|
end
|
175
246
|
|
176
247
|
task :clean do
|
177
|
-
rm_f Dir[
|
248
|
+
rm_f Dir[c_mri_txt, c_rp_txt]
|
178
249
|
end
|
179
250
|
|
180
251
|
task :realclean do
|
181
|
-
rm_f Dir[tarball]
|
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 = %w[ 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 3.0 ]
|
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
|
182
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] }
|
183
286
|
end
|
184
287
|
|
185
|
-
ruby_parse "1.8.7-p374"
|
186
|
-
ruby_parse "1.9.3-p551"
|
187
288
|
ruby_parse "2.0.0-p648"
|
188
|
-
ruby_parse "2.1.
|
189
|
-
ruby_parse "2.2.
|
190
|
-
ruby_parse "2.3.
|
191
|
-
|
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.8"
|
295
|
+
ruby_parse "2.7.4"
|
296
|
+
ruby_parse "3.0.2"
|
192
297
|
|
193
298
|
task :debug => :isolate do
|
194
|
-
ENV["V"] ||=
|
299
|
+
ENV["V"] ||= VERS.last
|
195
300
|
Rake.application[:parser].invoke # this way we can have DEBUG set
|
196
301
|
Rake.application[:lexer].invoke # this way we can have DEBUG set
|
197
302
|
|
198
|
-
|
303
|
+
$:.unshift "lib"
|
199
304
|
require "ruby_parser"
|
200
305
|
require "pp"
|
201
306
|
|
@@ -206,19 +311,21 @@ task :debug => :isolate do
|
|
206
311
|
time = (ENV["RP_TIMEOUT"] || 10).to_i
|
207
312
|
|
208
313
|
n = ENV["BUG"]
|
209
|
-
file = (n && "bug#{n}.rb") || ENV["F"] || ENV["FILE"]
|
314
|
+
file = (n && "bug#{n}.rb") || ENV["F"] || ENV["FILE"] || "debug.rb"
|
315
|
+
ruby = ENV["R"] || ENV["RUBY"]
|
316
|
+
|
317
|
+
if ruby then
|
318
|
+
file = "env"
|
319
|
+
else
|
320
|
+
ruby = File.read file
|
321
|
+
end
|
210
322
|
|
211
|
-
ruby = if file then
|
212
|
-
File.read(file)
|
213
|
-
else
|
214
|
-
file = "env"
|
215
|
-
ENV["R"] || ENV["RUBY"]
|
216
|
-
end
|
217
323
|
|
218
324
|
begin
|
219
325
|
pp parser.process(ruby, file, time)
|
220
|
-
rescue Racc::ParseError => e
|
326
|
+
rescue ArgumentError, Racc::ParseError => e
|
221
327
|
p e
|
328
|
+
puts e.backtrace.join "\n "
|
222
329
|
ss = parser.lexer.ss
|
223
330
|
src = ss.string
|
224
331
|
lines = src[0..ss.pos].split(/\n/)
|
@@ -226,22 +333,53 @@ task :debug => :isolate do
|
|
226
333
|
end
|
227
334
|
end
|
228
335
|
|
229
|
-
task :
|
230
|
-
file
|
231
|
-
|
336
|
+
task :debug3 do
|
337
|
+
file = ENV["F"] || "debug.rb"
|
338
|
+
version = ENV["V"] || ""
|
339
|
+
verbose = ENV["VERBOSE"] ? "-v" : ""
|
340
|
+
munge = "./tools/munge.rb #{verbose}"
|
341
|
+
|
342
|
+
abort "Need a file to parse, via: F=path.rb" unless file
|
343
|
+
|
344
|
+
ENV.delete "V"
|
345
|
+
|
346
|
+
ruby = "ruby#{version}"
|
347
|
+
|
348
|
+
sh "#{ruby} -v"
|
349
|
+
sh "#{ruby} -y #{file} 2>&1 | #{munge} > tmp/ruby"
|
350
|
+
sh "#{ruby} ./tools/ripper.rb -d #{file} | #{munge} > tmp/rip"
|
351
|
+
sh "rake debug F=#{file} DEBUG=1 2>&1 | #{munge} > tmp/rp"
|
352
|
+
sh "diff -U 999 -d tmp/{ruby,rp}"
|
353
|
+
end
|
354
|
+
|
355
|
+
task :cmp do
|
356
|
+
sh %(emacsclient --eval '(ediff-files "tmp/ruby" "tmp/rp")')
|
357
|
+
end
|
358
|
+
|
359
|
+
task :cmp3 do
|
360
|
+
sh %(emacsclient --eval '(ediff-files3 "tmp/ruby" "tmp/rip" "tmp/rp")')
|
232
361
|
end
|
233
362
|
|
234
363
|
task :extract => :isolate do
|
235
|
-
ENV["V"] ||=
|
364
|
+
ENV["V"] ||= VERS.last
|
236
365
|
Rake.application[:parser].invoke # this way we can have DEBUG set
|
237
366
|
|
238
|
-
file = ENV["F"] || ENV["FILE"]
|
367
|
+
file = ENV["F"] || ENV["FILE"] || abort("Need to provide F=<path>")
|
239
368
|
|
240
369
|
ruby "-Ilib", "bin/ruby_parse_extract_error", file
|
241
370
|
end
|
242
371
|
|
372
|
+
task :parse => :isolate do
|
373
|
+
ENV["V"] ||= VERS.last
|
374
|
+
Rake.application[:parser].invoke # this way we can have DEBUG set
|
375
|
+
|
376
|
+
file = ENV["F"] || ENV["FILE"] || abort("Need to provide F=<path>")
|
377
|
+
|
378
|
+
ruby "-Ilib", "bin/ruby_parse", file
|
379
|
+
end
|
380
|
+
|
243
381
|
task :bugs do
|
244
|
-
sh "for f in bug*.rb ; do #{Gem.ruby} -S rake debug F=$f && rm $f ; done"
|
382
|
+
sh "for f in bug*.rb bad*.rb ; do #{Gem.ruby} -S rake debug F=$f && rm $f ; done"
|
245
383
|
end
|
246
384
|
|
247
385
|
# 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
|
@@ -1,51 +1,27 @@
|
|
1
1
|
#!/usr/bin/ruby -ws
|
2
2
|
|
3
|
-
$d ||= false
|
4
|
-
$
|
5
|
-
$
|
6
|
-
$
|
7
|
-
$
|
8
|
-
$m ||= ENV["MOVE_TIMEOUT"]
|
9
|
-
$q ||= false
|
10
|
-
$q ||= ENV["QUIET"]
|
11
|
-
$v ||= ENV["V"] || "20"
|
12
|
-
$s ||= ENV["SPEED"] || false
|
3
|
+
$d ||= ENV["DELETE"] || false
|
4
|
+
$t ||= ENV["DELETE_TIMEOUT"] || false
|
5
|
+
$m ||= ENV["MOVE_TIMEOUT"] || false
|
6
|
+
$q ||= ENV["QUIET"] || false
|
7
|
+
$s ||= ENV["SPEED"] || false
|
13
8
|
|
14
9
|
require 'rubygems'
|
15
10
|
require 'ruby_parser'
|
16
11
|
require 'fileutils'
|
17
12
|
|
18
|
-
$parser_class = case $v
|
19
|
-
when "18" then
|
20
|
-
Ruby18Parser
|
21
|
-
when "19" then
|
22
|
-
Ruby19Parser
|
23
|
-
when "20" then
|
24
|
-
Ruby20Parser
|
25
|
-
else
|
26
|
-
abort "Unknown version #{$v.inspect}. Needs to be 18, 19, or 20"
|
27
|
-
end
|
28
|
-
|
29
|
-
class IO
|
30
|
-
RUBY19 = "<3".respond_to? :encoding
|
31
|
-
|
32
|
-
class << self
|
33
|
-
alias :binread :read unless RUBY19
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
13
|
ARGV.push "-" if ARGV.empty?
|
38
14
|
|
39
|
-
class
|
15
|
+
class RubyParser
|
40
16
|
def extract_defs
|
41
|
-
ss = lexer.ss
|
17
|
+
ss = current.lexer.ss
|
42
18
|
|
43
19
|
raise "can't access source. possible encoding issue" unless ss
|
44
20
|
|
45
21
|
src = ss.string
|
46
22
|
pre_error = src[0...ss.pos]
|
47
23
|
|
48
|
-
defs = pre_error.grep(/^ *(?:def|it)/)
|
24
|
+
defs = pre_error.lines.grep(/^ *(?:def|it)/)
|
49
25
|
|
50
26
|
raise "can't figure out where the bad code starts" unless defs.last
|
51
27
|
|
@@ -106,6 +82,7 @@ def process_error parser
|
|
106
82
|
end
|
107
83
|
rescue RuntimeError, Racc::ParseError => e
|
108
84
|
warn "# process error: #{e.message.strip}"
|
85
|
+
warn "# #{e.backtrace.first}"
|
109
86
|
end
|
110
87
|
|
111
88
|
def process file
|
@@ -113,7 +90,7 @@ def process file
|
|
113
90
|
time = (ENV["RP_TIMEOUT"] || 10).to_i
|
114
91
|
|
115
92
|
$stderr.print "# Validating #{file}: "
|
116
|
-
parser =
|
93
|
+
parser = RubyParser.new
|
117
94
|
t0 = Time.now if $s
|
118
95
|
parser.process(ruby, file, time)
|
119
96
|
if $s then
|
@@ -127,9 +104,14 @@ rescue Timeout::Error
|
|
127
104
|
warn "TIMEOUT parsing #{file}. Skipping."
|
128
105
|
|
129
106
|
if $m then
|
130
|
-
|
131
|
-
|
132
|
-
|
107
|
+
base_dir, *rest = file.split("/")
|
108
|
+
base_dir.sub!(/\.slow\.?.*/, "")
|
109
|
+
base_dir += ".slow.#{time}"
|
110
|
+
|
111
|
+
new_file = File.join(base_dir, *rest)
|
112
|
+
|
113
|
+
FileUtils.mkdir_p File.dirname(new_file)
|
114
|
+
FileUtils.move file, new_file, verbose:true
|
133
115
|
elsif $t then
|
134
116
|
File.unlink file
|
135
117
|
end
|
@@ -137,6 +119,7 @@ rescue StandardError, SyntaxError, Racc::ParseError => e
|
|
137
119
|
$exit = 1
|
138
120
|
warn ""
|
139
121
|
warn "# error: #{e.message.strip}" unless $q
|
122
|
+
warn "# #{e.backtrace.first}"
|
140
123
|
warn ""
|
141
124
|
return if $q
|
142
125
|
|
data/compare/normalize.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#!/usr/bin/ruby -w
|
1
|
+
#!/usr/bin/env ruby -w
|
2
2
|
|
3
3
|
good = false
|
4
4
|
|
@@ -8,6 +8,10 @@ order = []
|
|
8
8
|
|
9
9
|
def munge s
|
10
10
|
renames = [
|
11
|
+
# unquote... wtf?
|
12
|
+
/`(.+?)'/, proc { $1 },
|
13
|
+
/"'(.+?)'"/, proc { "\"#{$1}\"" },
|
14
|
+
|
11
15
|
"'='", "tEQL",
|
12
16
|
"'!'", "tBANG",
|
13
17
|
"'%'", "tPERCENT",
|
@@ -53,6 +57,7 @@ def munge s
|
|
53
57
|
|
54
58
|
'"&"', "tAMPER",
|
55
59
|
'"&&"', "tANDOP",
|
60
|
+
'"&."', "tLONELY",
|
56
61
|
'"||"', "tOROP",
|
57
62
|
|
58
63
|
'"..."', "tDOT3",
|
@@ -79,8 +84,10 @@ def munge s
|
|
79
84
|
|
80
85
|
"' '", "tSPACE", # needs to be later to avoid bad hits
|
81
86
|
|
87
|
+
"%empty", "none", # newer bison
|
82
88
|
"/* empty */", "none",
|
83
89
|
/^\s*$/, "none",
|
90
|
+
|
84
91
|
"keyword_BEGIN", "klBEGIN",
|
85
92
|
"keyword_END", "klEND",
|
86
93
|
/keyword_(\w+)/, proc { "k#{$1.upcase}" },
|
@@ -88,7 +95,72 @@ def munge s
|
|
88
95
|
/modifier_(\w+)/, proc { "k#{$1.upcase}_MOD" },
|
89
96
|
"kVARIABLE", "keyword_variable", # ugh
|
90
97
|
|
91
|
-
|
98
|
+
# 2.6 collapses klBEGIN to kBEGIN
|
99
|
+
"klBEGIN", "kBEGIN",
|
100
|
+
"klEND", "kEND",
|
101
|
+
|
102
|
+
/keyword_(\w+)/, proc { "k#{$1.upcase}" },
|
103
|
+
/\bk_([^_][a-z_]+)/, proc { "k#{$1.upcase}" },
|
104
|
+
/modifier_(\w+)/, proc { "k#{$1.upcase}_MOD" },
|
105
|
+
|
106
|
+
"kVARIABLE", "keyword_variable", # ugh: this is a rule name
|
107
|
+
|
108
|
+
# 2.7 changes:
|
109
|
+
|
110
|
+
'"global variable"', "tGVAR",
|
111
|
+
'"operator-assignment"', "tOP_ASGN",
|
112
|
+
'"back reference"', "tBACK_REF",
|
113
|
+
'"numbered reference"', "tNTH_REF",
|
114
|
+
'"local variable or method"', "tIDENTIFIER",
|
115
|
+
'"constant"', "tCONSTANT",
|
116
|
+
|
117
|
+
'"(.."', "tBDOT2",
|
118
|
+
'"(..."', "tBDOT3",
|
119
|
+
'"char literal"', "tCHAR",
|
120
|
+
'"literal content"', "tSTRING_CONTENT",
|
121
|
+
'"string literal"', "tSTRING_BEG",
|
122
|
+
'"symbol literal"', "tSYMBEG",
|
123
|
+
'"backtick literal"', "tXSTRING_BEG",
|
124
|
+
'"regexp literal"', "tREGEXP_BEG",
|
125
|
+
'"word list"', "tWORDS_BEG",
|
126
|
+
'"verbatim word list"', "tQWORDS_BEG",
|
127
|
+
'"symbol list"', "tSYMBOLS_BEG",
|
128
|
+
'"verbatim symbol list"', "tQSYMBOLS_BEG",
|
129
|
+
|
130
|
+
'"float literal"', "tFLOAT",
|
131
|
+
'"imaginary literal"', "tIMAGINARY",
|
132
|
+
'"integer literal"', "tINTEGER",
|
133
|
+
'"rational literal"', "tRATIONAL",
|
134
|
+
|
135
|
+
'"instance variable"', "tIVAR",
|
136
|
+
'"class variable"', "tCVAR",
|
137
|
+
'"terminator"', "tSTRING_END", # TODO: switch this?
|
138
|
+
'"method"', "tFID",
|
139
|
+
'"}"', "tSTRING_DEND",
|
140
|
+
|
141
|
+
'"do for block"', "kDO_BLOCK",
|
142
|
+
'"do for condition"', "kDO_COND",
|
143
|
+
'"do for lambda"', "kDO_LAMBDA",
|
144
|
+
"tLABEL", "kLABEL",
|
145
|
+
|
146
|
+
# UGH
|
147
|
+
"k_LINE__", "k__LINE__",
|
148
|
+
"k_FILE__", "k__FILE__",
|
149
|
+
"k_ENCODING__", "k__ENCODING__",
|
150
|
+
|
151
|
+
'"defined?"', "kDEFINED",
|
152
|
+
|
153
|
+
'"do (for condition)"', "kDO_COND",
|
154
|
+
'"do (for lambda)"', "kDO_LAMBDA",
|
155
|
+
'"do (for block)"', "kDO_BLOCK",
|
156
|
+
|
157
|
+
/\"(\w+) \(?modifier\)?\"/, proc { |x| "k#{$1.upcase}_MOD" },
|
158
|
+
/\"(\w+)\"/, proc { |x| "k#{$1.upcase}" },
|
159
|
+
|
160
|
+
/\$?@(\d+)(\s+|$)/, "", # newer bison
|
161
|
+
|
162
|
+
# TODO: remove for 3.0 work:
|
163
|
+
"lex_ctxt ", "" # 3.0 production that's mostly noise right now
|
92
164
|
]
|
93
165
|
|
94
166
|
renames.each_slice(2) do |(a, b)|
|
@@ -107,7 +179,7 @@ ARGF.each_line do |line|
|
|
107
179
|
|
108
180
|
case line.strip
|
109
181
|
when /^$/ then
|
110
|
-
when /^(\d+) (
|
182
|
+
when /^(\d+) (\$?[@\w]+): (.*)/ then # yacc
|
111
183
|
rule = $2
|
112
184
|
order << rule unless rules.has_key? rule
|
113
185
|
rules[rule] << munge($3)
|
@@ -132,7 +204,7 @@ ARGF.each_line do |line|
|
|
132
204
|
when /^\cL/ then # byacc
|
133
205
|
break
|
134
206
|
else
|
135
|
-
warn "unparsed: #{$.}: #{line.
|
207
|
+
warn "unparsed: #{$.}: #{line.strip.inspect}"
|
136
208
|
end
|
137
209
|
end
|
138
210
|
|