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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.autotest +18 -29
  4. data/History.rdoc +283 -0
  5. data/Manifest.txt +12 -4
  6. data/README.rdoc +4 -3
  7. data/Rakefile +189 -51
  8. data/bin/ruby_parse +3 -1
  9. data/bin/ruby_parse_extract_error +19 -36
  10. data/compare/normalize.rb +76 -4
  11. data/debugging.md +190 -0
  12. data/gauntlet.md +106 -0
  13. data/lib/rp_extensions.rb +14 -42
  14. data/lib/rp_stringscanner.rb +20 -51
  15. data/lib/ruby20_parser.rb +4659 -4218
  16. data/lib/ruby20_parser.y +953 -602
  17. data/lib/ruby21_parser.rb +4723 -4308
  18. data/lib/ruby21_parser.y +956 -605
  19. data/lib/ruby22_parser.rb +4762 -4337
  20. data/lib/ruby22_parser.y +960 -612
  21. data/lib/ruby23_parser.rb +4761 -4342
  22. data/lib/ruby23_parser.y +961 -613
  23. data/lib/ruby24_parser.rb +4791 -4341
  24. data/lib/ruby24_parser.y +968 -612
  25. data/lib/ruby25_parser.rb +4791 -4341
  26. data/lib/ruby25_parser.y +968 -612
  27. data/lib/ruby26_parser.rb +7287 -0
  28. data/lib/ruby26_parser.y +2749 -0
  29. data/lib/ruby27_parser.rb +8517 -0
  30. data/lib/ruby27_parser.y +3346 -0
  31. data/lib/ruby30_parser.rb +8751 -0
  32. data/lib/ruby30_parser.y +3472 -0
  33. data/lib/ruby3_parser.yy +3476 -0
  34. data/lib/ruby_lexer.rb +611 -826
  35. data/lib/ruby_lexer.rex +48 -40
  36. data/lib/ruby_lexer.rex.rb +122 -46
  37. data/lib/ruby_lexer_strings.rb +638 -0
  38. data/lib/ruby_parser.rb +38 -34
  39. data/lib/ruby_parser.yy +1710 -704
  40. data/lib/ruby_parser_extras.rb +987 -553
  41. data/test/test_ruby_lexer.rb +1718 -1539
  42. data/test/test_ruby_parser.rb +3957 -2164
  43. data/test/test_ruby_parser_extras.rb +39 -4
  44. data/tools/munge.rb +250 -0
  45. data/tools/ripper.rb +44 -0
  46. data.tar.gz.sig +0 -0
  47. metadata +68 -47
  48. metadata.gz.sig +0 -0
  49. data/lib/ruby18_parser.rb +0 -5793
  50. data/lib/ruby18_parser.y +0 -1908
  51. data/lib/ruby19_parser.rb +0 -6185
  52. 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
- V1 = %w[18 19]
18
- V2 = %w[20 21 22 23 24 25]
19
- V1_2 = V1 + V2
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.9"
27
- dependency "rake", "< 11", :developer
28
- dependency "oedipus_lex", "~> 2.5", :developer
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
- V1_2.each do |n|
43
+ VERS.each do |n|
32
44
  self.perforce_ignore << "lib/ruby#{n}_parser.rb"
33
45
  end
34
46
 
35
- V2.each do |n|
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
- V1_2.each do |n|
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.bz2"
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.bz2"
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 tarball do
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
- system "tar yxf #{tarball} #{ruby_dir}/{id.h,parse.y,tool/{id2token.rb,vpath.rb}}"
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
- cp "parse.y", "../#{parse_y}"
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
- file c_mri_txt => c_parse_y do
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 => :parser
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
- task c_diff => [c_mri_txt, c_rp_txt] do
234
+ file c_diff => [c_mri_txt, c_rp_txt] do
164
235
  in_compare do
165
- system "diff -du #{mri_txt} #{rp_txt} > #{diff}"
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[c_parse_y, c_mri_txt, c_rp_txt]
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.9"
189
- ruby_parse "2.2.6"
190
- ruby_parse "2.3.3"
191
- # TODO ruby_parse "2.4.0"
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"] ||= V1_2.last
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
- $: << "lib"
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 :debug_ruby do
230
- file = ENV["F"] || ENV["FILE"]
231
- sh "/Users/ryan/Desktop/DVDs/debugparser/miniruby -cwy #{file} 2>&1 | ./yuck.rb"
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"] ||= V1_2.last
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.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
@@ -1,51 +1,27 @@
1
1
  #!/usr/bin/ruby -ws
2
2
 
3
- $d ||= false
4
- $d ||= ENV["DELETE"]
5
- $t ||= false
6
- $t ||= ENV["DELETE_TIMEOUT"]
7
- $m ||= false
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 Racc::Parser
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 = $parser_class.new
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
- dir = File.join $m, File.dirname(file)
131
- FileUtils.mkdir_p dir
132
- 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
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
- /@(\d+)\s+/, "",
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+) (\$?\w+): (.*)/ then # yacc
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.chomp}"
207
+ warn "unparsed: #{$.}: #{line.strip.inspect}"
136
208
  end
137
209
  end
138
210