ruby_parser 3.13.1 → 3.21.0

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.
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