ruby_parser 3.13.1 → 3.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.autotest +18 -29
  4. data/History.rdoc +312 -0
  5. data/Manifest.txt +16 -15
  6. data/README.rdoc +13 -9
  7. data/Rakefile +237 -106
  8. data/bin/ruby_parse +3 -1
  9. data/bin/ruby_parse_extract_error +9 -4
  10. data/compare/normalize.rb +54 -6
  11. data/debugging.md +172 -0
  12. data/gauntlet.md +107 -0
  13. data/lib/rp_extensions.rb +15 -36
  14. data/lib/rp_stringscanner.rb +20 -51
  15. data/lib/ruby_lexer.rb +515 -812
  16. data/lib/ruby_lexer.rex +33 -27
  17. data/lib/ruby_lexer.rex.rb +64 -31
  18. data/lib/ruby_lexer_strings.rb +638 -0
  19. data/lib/ruby_parser.rb +46 -36
  20. data/lib/{ruby_parser.yy → ruby_parser2.yy} +1400 -488
  21. data/lib/ruby_parser20.rb +10953 -0
  22. data/lib/ruby_parser21.rb +10978 -0
  23. data/lib/ruby_parser22.rb +11119 -0
  24. data/lib/ruby_parser23.rb +11160 -0
  25. data/lib/ruby_parser24.rb +11209 -0
  26. data/lib/ruby_parser25.rb +11209 -0
  27. data/lib/ruby_parser26.rb +11231 -0
  28. data/lib/ruby_parser27.rb +12960 -0
  29. data/lib/{ruby26_parser.y → ruby_parser3.yy} +1652 -521
  30. data/lib/ruby_parser30.rb +13292 -0
  31. data/lib/ruby_parser31.rb +13625 -0
  32. data/lib/ruby_parser32.rb +13577 -0
  33. data/lib/ruby_parser33.rb +13577 -0
  34. data/lib/ruby_parser_extras.rb +988 -474
  35. data/test/test_ruby_lexer.rb +1339 -1155
  36. data/test/test_ruby_parser.rb +4255 -2103
  37. data/test/test_ruby_parser_extras.rb +39 -4
  38. data/tools/munge.rb +52 -13
  39. data/tools/ripper.rb +24 -6
  40. data.tar.gz.sig +0 -0
  41. metadata +73 -56
  42. metadata.gz.sig +0 -0
  43. data/lib/ruby20_parser.rb +0 -6869
  44. data/lib/ruby20_parser.y +0 -2431
  45. data/lib/ruby21_parser.rb +0 -6944
  46. data/lib/ruby21_parser.y +0 -2449
  47. data/lib/ruby22_parser.rb +0 -6968
  48. data/lib/ruby22_parser.y +0 -2458
  49. data/lib/ruby23_parser.rb +0 -6987
  50. data/lib/ruby23_parser.y +0 -2460
  51. data/lib/ruby24_parser.rb +0 -6994
  52. data/lib/ruby24_parser.y +0 -2466
  53. data/lib/ruby25_parser.rb +0 -6994
  54. data/lib/ruby25_parser.y +0 -2466
  55. data/lib/ruby26_parser.rb +0 -7012
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  # -*- ruby -*-
2
2
 
3
- require "rubygems"
4
3
  require "hoe"
5
4
 
6
5
  Hoe.plugin :seattlerb
@@ -8,29 +7,41 @@ Hoe.plugin :racc
8
7
  Hoe.plugin :isolate
9
8
  Hoe.plugin :rdoc
10
9
 
10
+ Hoe.add_include_dirs "lib"
11
11
  Hoe.add_include_dirs "../../sexp_processor/dev/lib"
12
12
  Hoe.add_include_dirs "../../minitest/dev/lib"
13
13
  Hoe.add_include_dirs "../../oedipus_lex/dev/lib"
14
+ Hoe.add_include_dirs "../../ruby2ruby/dev/lib"
14
15
 
15
- V2 = %w[20 21 22 23 24 25 26]
16
- V2.replace [V2.last] if ENV["FAST"] # HACK
16
+ V2 = %w[20 21 22 23 24 25 26 27]
17
+ V3 = %w[30 31 32 33]
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"]
23
+
24
+ racc_flags = nil
17
25
 
18
26
  Hoe.spec "ruby_parser" do
19
27
  developer "Ryan Davis", "ryand-ruby@zenspider.com"
20
28
 
21
29
  license "MIT"
22
30
 
23
- dependency "sexp_processor", "~> 4.9"
24
- dependency "rake", "< 11", :developer
25
- dependency "oedipus_lex", "~> 2.5", :developer
31
+ dependency "sexp_processor", "~> 4.16"
32
+ dependency "racc", "~> 1.5"
33
+ dependency "rake", [">= 10", "< 15"], :developer
34
+ dependency "oedipus_lex", "~> 2.6", :developer
35
+
36
+ require_ruby_version [">= 2.6", "< 4"]
26
37
 
27
38
  if plugin? :perforce then # generated files
28
- V2.each do |n|
29
- self.perforce_ignore << "lib/ruby#{n}_parser.rb"
39
+ VERS.each do |n|
40
+ self.perforce_ignore << "lib/ruby_parser#{n}.rb"
30
41
  end
31
42
 
32
- V2.each do |n|
33
- self.perforce_ignore << "lib/ruby#{n}_parser.y"
43
+ VERS.each do |n|
44
+ self.perforce_ignore << "lib/ruby_parser#{n}.y"
34
45
  end
35
46
 
36
47
  self.perforce_ignore << "lib/ruby_lexer.rex.rb"
@@ -39,27 +50,68 @@ Hoe.spec "ruby_parser" do
39
50
  if plugin?(:racc)
40
51
  self.racc_flags << " -t" if ENV["DEBUG"]
41
52
  self.racc_flags << " --superclass RubyParser::Parser"
42
- # self.racc_flags << " --runtime ruby_parser" # TODO: broken in racc
53
+ racc_flags = self.racc_flags
43
54
  end
44
55
  end
45
56
 
46
- V2.each do |n|
47
- file "lib/ruby#{n}_parser.y" => "lib/ruby_parser.yy" do |t|
48
- cmd = 'unifdef -tk -DV=%s -UDEAD %s > %s || true' % [n, t.source, t.name]
49
- sh cmd
57
+ def maybe_add_to_top path, string
58
+ file = File.read path
59
+
60
+ return if file.start_with? string
61
+
62
+ warn "Altering top of #{path}"
63
+ tmp_path = "#{path}.tmp"
64
+ File.open(tmp_path, "w") do |f|
65
+ f.puts string
66
+ f.puts
67
+
68
+ f.write file
69
+ # TODO: make this deal with encoding comments properly?
50
70
  end
71
+ File.rename tmp_path, path
72
+ end
73
+
74
+ def unifdef?
75
+ @unifdef ||= system("which unifdef") or abort <<~EOM
76
+ unifdef not found!
77
+
78
+ Please install 'unifdef' package on your system or `rake generate` on a mac.
79
+ EOM
80
+ end
81
+
82
+ def racc?
83
+ @racc ||= system("which racc") or abort <<~EOM
84
+ racc not found! `gem install racc`
85
+ EOM
86
+ end
51
87
 
52
- file "lib/ruby#{n}_parser.rb" => "lib/ruby#{n}_parser.y"
88
+ generate_parser = proc do |t|
89
+ unifdef?
90
+ racc?
91
+ n = t.name[/\d+/]
92
+ sh "unifdef -tk -DV=%s %s | racc %s /dev/stdin -o %s" % [n, t.source, racc_flags, t.name]
93
+ maybe_add_to_top t.name, "# frozen_string_literal: true"
94
+ end
95
+
96
+ V2.each do |n|
97
+ file "lib/ruby_parser#{n}.rb" => "lib/ruby_parser2.yy", &generate_parser
98
+ end
99
+
100
+ V3.each do |n|
101
+ file "lib/ruby_parser#{n}.rb" => "lib/ruby_parser3.yy", &generate_parser
53
102
  end
54
103
 
55
104
  file "lib/ruby_lexer.rex.rb" => "lib/ruby_lexer.rex"
56
105
 
106
+ task :generate => [:lexer, :parser]
107
+
57
108
  task :clean do
58
109
  rm_rf(Dir["**/*~"] +
59
110
  Dir["diff.diff"] + # not all diffs. bit me too many times
60
111
  Dir["coverage.info"] +
61
112
  Dir["coverage"] +
62
- Dir["lib/ruby2*_parser.y"] +
113
+ Dir["lib/ruby_parser2*.y"] +
114
+ Dir["lib/ruby_parser3*.y"] +
63
115
  Dir["lib/*.output"])
64
116
  end
65
117
 
@@ -73,127 +125,187 @@ task :huh? do
73
125
  puts "ruby #{Hoe::RUBY_FLAGS} bin/ruby_parse -q -g ..."
74
126
  end
75
127
 
76
- task :irb => [:isolate] do
77
- sh "GEM_HOME=#{Gem.path.first} irb -rubygems -Ilib -rruby_parser;"
78
- end
79
-
80
128
  def (task(:phony)).timestamp
81
129
  Time.at 0
82
130
  end
83
131
 
84
132
  task :isolate => :phony
85
133
 
86
- def in_compare
87
- Dir.chdir "compare" do
88
- yield
89
- end
90
- end
91
-
92
- def dl v
134
+ def dl v, f
93
135
  dir = v[/^\d+\.\d+/]
94
- url = "https://cache.ruby-lang.org/pub/ruby/#{dir}/ruby-#{v}.tar.bz2"
95
- path = File.basename url
96
- unless File.exist? path then
97
- system "curl -O #{url}"
98
- end
136
+ url = "https://cache.ruby-lang.org/pub/ruby/#{dir}/ruby-#{v}.tar.xz"
137
+
138
+ warn "Downloading ruby #{v}"
139
+ system "curl -s -o #{f} #{url}"
99
140
  end
100
141
 
142
+ task :parser => :isolate
143
+
144
+ multitask :compare_build
145
+ task :compare_build => :generate
146
+ task :compare => :compare_build
147
+
101
148
  def ruby_parse version
102
149
  v = version[/^\d+\.\d+/].delete "."
103
- rp_txt = "rp#{v}.txt"
104
- mri_txt = "mri#{v}.txt"
105
- parse_y = "parse#{v}.y"
106
- tarball = "ruby-#{version}.tar.bz2"
107
- ruby_dir = "ruby-#{version}"
108
- diff = "diff#{v}.diff"
109
- rp_out = "lib/ruby#{v}_parser.output"
110
- rp_y = "lib/ruby#{v}_parser.y"
111
- rp_y_rb = "lib/ruby#{v}_parser.rb"
112
-
113
- c_diff = "compare/#{diff}"
114
- c_rp_txt = "compare/#{rp_txt}"
115
- c_mri_txt = "compare/#{mri_txt}"
116
- c_parse_y = "compare/#{parse_y}"
117
- c_tarball = "compare/#{tarball}"
150
+ diff = "compare/diff#{v}.diff"
151
+ rp_txt = "compare/rp#{v}.txt"
152
+ mri_txt = "compare/mri#{v}.txt"
153
+ parse_y = "compare/parse#{v}.y"
154
+ tarball = "compare/ruby-#{version}.tar.xz"
155
+ ruby_dir = "compare/ruby-#{version}"
156
+ rp_out = "lib/ruby_parser#{v}.output"
157
+ rp_y_rb = "lib/ruby_parser#{v}.rb"
118
158
  normalize = "compare/normalize.rb"
119
159
 
120
- file c_tarball do
121
- in_compare do
122
- dl version
123
- end
160
+ file tarball do
161
+ dl version, tarball
124
162
  end
125
163
 
126
- file c_parse_y => c_tarball do
127
- in_compare do
128
- system "tar yxf #{tarball} #{ruby_dir}/{id.h,parse.y,tool/{id2token.rb,vpath.rb}}"
129
- Dir.chdir ruby_dir do
130
- if File.exist? "tool/id2token.rb" then
131
- sh "ruby tool/id2token.rb --path-separator=.:./ id.h parse.y | expand > ../#{parse_y}"
132
- else
133
- sh "expand parse.y > ../#{parse_y}"
134
- end
135
- end
136
- sh "rm -rf #{ruby_dir}"
164
+ desc "fetch all tarballs"
165
+ task :fetch => tarball
166
+
167
+ file parse_y => tarball do
168
+ extract_glob = case
169
+ when version > "3.3" then
170
+ "{id.h,parse.y,tool/{id2token.rb,lrama},defs/id.def}"
171
+ when version > "3.2" then
172
+ "{id.h,parse.y,tool/id2token.rb,defs/id.def}"
173
+ when version > "2.7" then
174
+ "{id.h,parse.y,tool/{id2token.rb,lib/vpath.rb}}"
175
+ else
176
+ "{id.h,parse.y,tool/{id2token.rb,vpath.rb}}"
177
+ end
178
+ system "tar xf #{tarball} -C compare #{File.basename ruby_dir}/#{extract_glob}"
179
+
180
+ # Debugging a new parse build system:
181
+ #
182
+ # Unpack the ruby tarball in question, configure, and run the following:
183
+ #
184
+ # % touch parse.y; make -n parse.c
185
+ # ...
186
+ # echo generating parse.c
187
+ # /Users/ryan/.rubies.current/bin/ruby --disable=gems ./tool/id2token.rb parse.y | \
188
+ # ruby ./tool/lrama/exe/lrama -oparse.c -Hparse.h - parse.y
189
+ #
190
+ # Then integrate these commands into the mess below:
191
+
192
+ d = ruby_dir
193
+ cmd = if version > "3.2" then
194
+ "ruby #{d}/tool/id2token.rb #{d}/parse.y | expand > #{parse_y}"
195
+ else
196
+ "ruby #{d}/tool/id2token.rb --path-separator=.:./ #{d}/id.h #{d}/parse.y | expand | ruby -pe 'gsub(/^%pure-parser/, \"%define api.pure\")' > #{parse_y}"
197
+ end
198
+
199
+ sh cmd
200
+
201
+ if File.exist? "#{d}/tool/lrama" then # UGH: this is dumb
202
+ rm_rf "compare/lrama"
203
+ sh "mv #{d}/tool/lrama compare"
137
204
  end
205
+ sh "rm -rf #{d}"
138
206
  end
139
207
 
140
- file c_mri_txt => [c_parse_y, normalize] do
141
- in_compare do
142
- sh "bison -r all #{parse_y}"
143
- sh "./normalize.rb parse#{v}.output > #{mri_txt}"
144
- rm ["parse#{v}.output", "parse#{v}.tab.c"]
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 mri_txt => [parse_y, normalize] do
214
+ if version > "3.3" then
215
+ sh "./compare/lrama/exe/lrama -r all -ocompare/parse#{v}.tab.c #{parse_y}"
216
+ else
217
+ sh "#{bison} -r all #{parse_y}"
218
+ mv Dir["parse#{v}.*"], "compare"
145
219
  end
220
+
221
+ sh "#{normalize} compare/parse#{v}.output > #{mri_txt}"
222
+ rm ["compare/parse#{v}.output", "compare/parse#{v}.tab.c"]
146
223
  end
147
224
 
148
225
  file rp_out => rp_y_rb
149
226
 
150
- file c_rp_txt => [rp_out, normalize] do
151
- in_compare do
152
- sh "./normalize.rb ../#{rp_out} > #{rp_txt}"
153
- end
227
+ file rp_txt => [rp_out, normalize] do
228
+ sh "#{normalize} #{rp_out} > #{rp_txt}"
154
229
  end
155
230
 
156
231
  compare = "compare#{v}"
232
+ compare_build = "compare_build#{v}"
157
233
 
158
234
  desc "Compare all grammars to MRI"
159
235
  task :compare => compare
236
+ task :compare_build => compare_build
160
237
 
161
- file c_diff => [c_mri_txt, c_rp_txt] do
162
- in_compare do
163
- sh "diff -du #{mri_txt} #{rp_txt} > #{diff}; true"
164
- end
238
+ task compare_build => diff
239
+
240
+ file diff => [mri_txt, rp_txt] do
241
+ sh "diff -du #{mri_txt} #{rp_txt} > #{diff}; true"
165
242
  end
166
243
 
167
244
  desc "Compare #{v} grammar to MRI #{version}"
168
- task compare => c_diff do
169
- in_compare do
170
- system "wc -l #{diff}"
171
- end
245
+ task compare => diff do
246
+ system "wc -l #{diff}"
172
247
  end
173
248
 
174
249
  task :clean do
175
- rm_f Dir[c_mri_txt, c_rp_txt]
250
+ rm_f Dir[mri_txt, rp_txt]
176
251
  end
177
252
 
178
253
  task :realclean do
179
- rm_f Dir[c_parse_y, tarball]
254
+ rm_f Dir[parse_y, tarball]
255
+ end
256
+ end
257
+
258
+ task :versions do
259
+ require "open-uri"
260
+ require "net/http" # avoid require issues in threads
261
+ require "net/https"
262
+
263
+ versions = VERS.map { |s| s.split(//).join "." }
264
+
265
+ base_url = "https://cache.ruby-lang.org/pub/ruby"
266
+
267
+ class Array
268
+ def human_sort
269
+ sort_by { |item| item.to_s.split(/(\d+)/).map { |e| [e.to_i, e] } }
270
+ end
180
271
  end
272
+
273
+ versions = versions.map { |ver|
274
+ Thread.new {
275
+ URI
276
+ .parse("#{base_url}/#{ver}/")
277
+ .read
278
+ .scan(/ruby-\d+\.\d+\.\d+[-\w.]*?.tar.gz/)
279
+ .reject { |s| s =~ /-(?:rc|preview)\d/ }
280
+ .human_sort
281
+ .last
282
+ .delete_prefix("ruby-")
283
+ .delete_suffix ".tar.gz"
284
+ }
285
+ }.map(&:value).sort
286
+
287
+ puts versions.map { |v| "ruby_parse %p" % [v] }
181
288
  end
182
289
 
183
290
  ruby_parse "2.0.0-p648"
184
- ruby_parse "2.1.9"
185
- ruby_parse "2.2.9"
291
+ ruby_parse "2.1.10"
292
+ ruby_parse "2.2.10"
186
293
  ruby_parse "2.3.8"
187
- ruby_parse "2.4.5"
188
- ruby_parse "2.5.3"
189
- ruby_parse "2.6.1"
294
+ ruby_parse "2.4.10"
295
+ ruby_parse "2.5.9"
296
+ ruby_parse "2.6.10"
297
+ ruby_parse "2.7.8"
298
+ ruby_parse "3.0.6"
299
+ ruby_parse "3.1.4"
300
+ ruby_parse "3.2.2"
301
+ ruby_parse "3.3.0"
190
302
 
191
303
  task :debug => :isolate do
192
- ENV["V"] ||= V2.last
304
+ ENV["V"] ||= VERS.last
193
305
  Rake.application[:parser].invoke # this way we can have DEBUG set
194
306
  Rake.application[:lexer].invoke # this way we can have DEBUG set
195
307
 
196
- $: << "lib"
308
+ $:.unshift "lib"
197
309
  require "ruby_parser"
198
310
  require "pp"
199
311
 
@@ -204,19 +316,21 @@ task :debug => :isolate do
204
316
  time = (ENV["RP_TIMEOUT"] || 10).to_i
205
317
 
206
318
  n = ENV["BUG"]
207
- file = (n && "bug#{n}.rb") || ENV["F"] || ENV["FILE"]
319
+ file = (n && "bug#{n}.rb") || ENV["F"] || ENV["FILE"] || "debug.rb"
320
+ ruby = ENV["R"] || ENV["RUBY"]
321
+
322
+ if ruby then
323
+ file = "env"
324
+ else
325
+ ruby = File.read file
326
+ end
208
327
 
209
- ruby = if file then
210
- File.read(file)
211
- else
212
- file = "env"
213
- ENV["R"] || ENV["RUBY"]
214
- end
215
328
 
216
329
  begin
217
330
  pp parser.process(ruby, file, time)
218
- rescue Racc::ParseError => e
331
+ rescue ArgumentError, Racc::ParseError => e
219
332
  p e
333
+ puts e.backtrace.join "\n "
220
334
  ss = parser.lexer.ss
221
335
  src = ss.string
222
336
  lines = src[0..ss.pos].split(/\n/)
@@ -225,18 +339,26 @@ task :debug => :isolate do
225
339
  end
226
340
 
227
341
  task :debug3 do
228
- file = ENV["F"]
229
- verbose = ENV["V"] ? "-v" : ""
342
+ file = ENV["F"] || "debug.rb"
343
+ version = ENV["V"] || ""
344
+ verbose = ENV["VERBOSE"] ? "-v" : ""
230
345
  munge = "./tools/munge.rb #{verbose}"
231
346
 
232
347
  abort "Need a file to parse, via: F=path.rb" unless file
233
348
 
234
349
  ENV.delete "V"
235
350
 
236
- sh "ruby -y #{file} 2>&1 | #{munge} > tmp/ruby"
237
- sh "./tools/ripper.rb -d #{file} | #{munge} > tmp/rip"
238
- sh "rake debug F=#{file} DEBUG=1 V=25 2>&1 | #{munge} > tmp/rp"
239
- sh "diff -U 999 -d tmp/{rip,rp}"
351
+ ruby = "ruby#{version}"
352
+
353
+ sh "#{ruby} -v"
354
+ sh "#{ruby} -y #{file} 2>&1 | #{munge} > tmp/ruby"
355
+ sh "#{ruby} ./tools/ripper.rb -d #{file} | #{munge} > tmp/rip"
356
+ sh "rake debug F=#{file} DEBUG=1 2>&1 | #{munge} > tmp/rp"
357
+ sh "diff -U 999 -d tmp/{ruby,rp}"
358
+ end
359
+
360
+ task :cmp do
361
+ sh %(emacsclient --eval '(ediff-files "tmp/ruby" "tmp/rp")')
240
362
  end
241
363
 
242
364
  task :cmp3 do
@@ -244,16 +366,25 @@ task :cmp3 do
244
366
  end
245
367
 
246
368
  task :extract => :isolate do
247
- ENV["V"] ||= V2.last
369
+ ENV["V"] ||= VERS.last
248
370
  Rake.application[:parser].invoke # this way we can have DEBUG set
249
371
 
250
- file = ENV["F"] || ENV["FILE"]
372
+ file = ENV["F"] || ENV["FILE"] || abort("Need to provide F=<path>")
251
373
 
252
374
  ruby "-Ilib", "bin/ruby_parse_extract_error", file
253
375
  end
254
376
 
377
+ task :parse => :isolate do
378
+ ENV["V"] ||= VERS.last
379
+ Rake.application[:parser].invoke # this way we can have DEBUG set
380
+
381
+ file = ENV["F"] || ENV["FILE"] || abort("Need to provide F=<path>")
382
+
383
+ ruby "-Ilib", "bin/ruby_parse", file
384
+ end
385
+
255
386
  task :bugs do
256
- sh "for f in bug*.rb ; do #{Gem.ruby} -S rake debug F=$f && rm $f ; done"
387
+ sh "for f in bug*.rb bad*.rb ; do #{Gem.ruby} -S rake debug F=$f && rm $f ; done"
257
388
  end
258
389
 
259
390
  # 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.parse(File.binread(file), file)
50
+ r = rp.process(File.binread(file), file, time)
49
51
  pp r unless $q
50
52
  good += 1
51
53
  rescue SyntaxError => e
@@ -21,7 +21,7 @@ class RubyParser
21
21
  src = ss.string
22
22
  pre_error = src[0...ss.pos]
23
23
 
24
- defs = pre_error.grep(/^ *(?:def|it)/)
24
+ defs = pre_error.lines.grep(/^ *(?:def|it)/)
25
25
 
26
26
  raise "can't figure out where the bad code starts" unless defs.last
27
27
 
@@ -104,9 +104,14 @@ rescue Timeout::Error
104
104
  warn "TIMEOUT parsing #{file}. Skipping."
105
105
 
106
106
  if $m then
107
- dir = File.join $m, File.dirname(file)
108
- FileUtils.mkdir_p dir
109
- FileUtils.move file, dir
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
110
115
  elsif $t then
111
116
  File.unlink file
112
117
  end
data/compare/normalize.rb CHANGED
@@ -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",
@@ -80,6 +84,8 @@ def munge s
80
84
 
81
85
  "' '", "tSPACE", # needs to be later to avoid bad hits
82
86
 
87
+ "ε", "none", # bison 3+
88
+ "%empty", "none", # newer bison
83
89
  "/* empty */", "none",
84
90
  /^\s*$/, "none",
85
91
 
@@ -100,6 +106,44 @@ def munge s
100
106
 
101
107
  "kVARIABLE", "keyword_variable", # ugh: this is a rule name
102
108
 
109
+ # 2.7 changes:
110
+
111
+ '"global variable"', "tGVAR",
112
+ '"operator-assignment"', "tOP_ASGN",
113
+ '"back reference"', "tBACK_REF",
114
+ '"numbered reference"', "tNTH_REF",
115
+ '"local variable or method"', "tIDENTIFIER",
116
+ '"constant"', "tCONSTANT",
117
+
118
+ '"(.."', "tBDOT2",
119
+ '"(..."', "tBDOT3",
120
+ '"char literal"', "tCHAR",
121
+ '"literal content"', "tSTRING_CONTENT",
122
+ '"string literal"', "tSTRING_BEG",
123
+ '"symbol literal"', "tSYMBEG",
124
+ '"backtick literal"', "tXSTRING_BEG",
125
+ '"regexp literal"', "tREGEXP_BEG",
126
+ '"word list"', "tWORDS_BEG",
127
+ '"verbatim word list"', "tQWORDS_BEG",
128
+ '"symbol list"', "tSYMBOLS_BEG",
129
+ '"verbatim symbol list"', "tQSYMBOLS_BEG",
130
+
131
+ '"float literal"', "tFLOAT",
132
+ '"imaginary literal"', "tIMAGINARY",
133
+ '"integer literal"', "tINTEGER",
134
+ '"rational literal"', "tRATIONAL",
135
+
136
+ '"instance variable"', "tIVAR",
137
+ '"class variable"', "tCVAR",
138
+ '"terminator"', "tSTRING_END", # TODO: switch this?
139
+ '"method"', "tFID",
140
+ '"}"', "tSTRING_DEND",
141
+
142
+ '"do for block"', "kDO_BLOCK",
143
+ '"do for condition"', "kDO_COND",
144
+ '"do for lambda"', "kDO_LAMBDA",
145
+ "tLABEL", "kLABEL",
146
+
103
147
  # UGH
104
148
  "k_LINE__", "k__LINE__",
105
149
  "k_FILE__", "k__FILE__",
@@ -107,15 +151,17 @@ def munge s
107
151
 
108
152
  '"defined?"', "kDEFINED",
109
153
 
110
-
111
154
  '"do (for condition)"', "kDO_COND",
112
155
  '"do (for lambda)"', "kDO_LAMBDA",
113
156
  '"do (for block)"', "kDO_BLOCK",
114
157
 
115
- /\"(\w+) \(modifier\)\"/, proc { |x| "k#{$1.upcase}_MOD" },
116
- /\"(\w+)\"/, proc { |x| "k#{$1.upcase}" },
158
+ /\"(\w+) \(?modifier\)?\"/, proc { |x| "k#{$1.upcase}_MOD" },
159
+ /\"(\w+)\"/, proc { |x| "k#{$1.upcase}" },
117
160
 
118
- /@(\d+)(\s+|$)/, "",
161
+ /\$?@(\d+)(\s+|$)/, "", # newer bison
162
+
163
+ # TODO: remove for 3.0 work:
164
+ "lex_ctxt ", "" # 3.0 production that's mostly noise right now
119
165
  ]
120
166
 
121
167
  renames.each_slice(2) do |(a, b)|
@@ -134,7 +180,7 @@ ARGF.each_line do |line|
134
180
 
135
181
  case line.strip
136
182
  when /^$/ then
137
- when /^(\d+) (\$?\w+): (.*)/ then # yacc
183
+ when /^(\d+) (\$?[@\w]+): (.*)/ then # yacc
138
184
  rule = $2
139
185
  order << rule unless rules.has_key? rule
140
186
  rules[rule] << munge($3)
@@ -156,10 +202,12 @@ ARGF.each_line do |line|
156
202
  break
157
203
  when /^Terminals/ then # yacc
158
204
  break
205
+ when /^State \d/ then # lrama
206
+ break
159
207
  when /^\cL/ then # byacc
160
208
  break
161
209
  else
162
- warn "unparsed: #{$.}: #{line.chomp}"
210
+ warn "unparsed: #{$.}: #{line.strip.inspect}"
163
211
  end
164
212
  end
165
213