From 10cde047856b8e10924d1ba90362b4bb2aab9650 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Sat, 11 Mar 2017 17:04:22 -0800 Subject: [PATCH] + Changed superclasses of all parsers to RubyParser::Parser Fixed requires in a few of the new files + Moved RubyParser from ruby_parser_extras.rb into ruby_parser.rb to fix bootstrap issues. + Subclasses of RubyParser::Parser register themselves into RubyParser::VERSIONS. + RubyParser.for_current_ruby falls back to latest if current not available. + Added RubyParser.latest. + Renamed all parsers to RubyParser::V##. [git-p4: depot-paths = "//src/ruby_parser/dev/": change = 11261] --- Rakefile | 6 ++- lib/rp_extensions.rb | 2 + lib/rp_stringscanner.rb | 2 + lib/ruby_parser.rb | 87 ++++++++++++++++++++++++++++--- lib/ruby_parser_extras.rb | 91 +-------------------------------- test/test_ruby_lexer.rb | 8 ++- test/test_ruby_parser_extras.rb | 10 ++-- 7 files changed, 98 insertions(+), 108 deletions(-) diff --git a/Rakefile b/Rakefile index c0d23453..c0644845 100644 --- a/Rakefile +++ b/Rakefile @@ -37,7 +37,11 @@ Hoe.spec "ruby_parser" do end end - self.racc_flags << " -t" if plugin?(:racc) && ENV["DEBUG"] + if plugin?(:racc) + self.racc_flags << " -t" if ENV["DEBUG"] + self.racc_flags << " --superclass RubyParser::Parser" + # self.racc_flags << " --runtime ruby_parser" # TODO: broken in racc + end end V2.each do |n| diff --git a/lib/rp_extensions.rb b/lib/rp_extensions.rb index a37cea18..34ad9ec5 100644 --- a/lib/rp_extensions.rb +++ b/lib/rp_extensions.rb @@ -40,6 +40,8 @@ class String attr_accessor :lineno end +require "sexp" + class Sexp attr_writer :paren diff --git a/lib/rp_stringscanner.rb b/lib/rp_stringscanner.rb index bebcfca1..4bbd6d1a 100644 --- a/lib/rp_stringscanner.rb +++ b/lib/rp_stringscanner.rb @@ -1,3 +1,5 @@ +require "strscan" + class RPStringScanner < StringScanner # if ENV['TALLY'] then # alias :old_getch :getch diff --git a/lib/ruby_parser.rb b/lib/ruby_parser.rb index ce35f7be..e4f70bb8 100644 --- a/lib/ruby_parser.rb +++ b/lib/ruby_parser.rb @@ -1,7 +1,80 @@ -require 'ruby18_parser' -require 'ruby19_parser' -require 'ruby20_parser' -require 'ruby21_parser' -require 'ruby22_parser' -require 'ruby23_parser' -require 'ruby_parser_extras' +require "ruby_parser_extras" +require "racc/parser" + +## +# RubyParser is a compound parser that uses all known versions to +# attempt to parse. + +class RubyParser + + VERSIONS = [] + + class Parser < Racc::Parser + include RubyParserStuff + + def self.inherited x + RubyParser::VERSIONS << x + end + end + + class SyntaxError < RuntimeError; end + + def process s, f = "(string)", t = 10 + e = nil + VERSIONS.each do |klass| + parser = klass.new + begin + return parser.process s, f, t + rescue Racc::ParseError, RubyParser::SyntaxError => exc + e = exc + end + end + raise e + end + + alias :parse :process + + def reset + # do nothing + end + + def self.latest + VERSIONS.first.new + end + + def self.for_current_ruby + name = "V#{RUBY_VERSION[/^\d+\.\d+/].delete "."}" + klass = if const_defined? name then + const_get name + else + latest = VERSIONS.first + warn "NOTE: RubyParser::#{name} undefined, using #{latest}." + latest + end + + klass.new + end +end + +## +# Unfortunately a problem with racc is that it won't let me namespace +# properly, so instead of RubyParser::V18, I still have to generate +# the old Ruby23Parser and shove it in as V23. + +require "ruby18_parser" +require "ruby19_parser" +require "ruby20_parser" +require "ruby21_parser" +require "ruby22_parser" +require "ruby23_parser" + +class RubyParser # HACK + VERSIONS.clear # also a HACK caused by racc namespace issues + + class V23 < ::Ruby23Parser; end + class V22 < ::Ruby22Parser; end + class V21 < ::Ruby21Parser; end + class V20 < ::Ruby20Parser; end + class V19 < ::Ruby19Parser; end + class V18 < ::Ruby18Parser; end +end diff --git a/lib/ruby_parser_extras.rb b/lib/ruby_parser_extras.rb index d9d18142..7bf95ff2 100644 --- a/lib/ruby_parser_extras.rb +++ b/lib/ruby_parser_extras.rb @@ -1,10 +1,7 @@ # encoding: ASCII-8BIT -require 'stringio' -require 'racc/parser' -require 'sexp' -require 'strscan' -require 'ruby_lexer' +require "sexp" +require "ruby_lexer" require "timeout" require "rp_extensions" require "rp_stringscanner" @@ -1356,87 +1353,3 @@ def restore oldstate end end end - -class Ruby23Parser < Racc::Parser - include RubyParserStuff -end - -class Ruby22Parser < Racc::Parser - include RubyParserStuff -end - -class Ruby21Parser < Racc::Parser - include RubyParserStuff -end - -class Ruby20Parser < Racc::Parser - include RubyParserStuff -end - -class Ruby19Parser < Racc::Parser - include RubyParserStuff -end - -class Ruby18Parser < Racc::Parser - include RubyParserStuff -end - -## -# RubyParser is a compound parser that first attempts to parse using -# the 1.9 syntax parser and falls back to the 1.8 syntax parser on a -# parse error. - -class RubyParser - class SyntaxError < RuntimeError; end - - def initialize - @p18 = Ruby18Parser.new - @p19 = Ruby19Parser.new - @p20 = Ruby20Parser.new - @p21 = Ruby21Parser.new - @p22 = Ruby22Parser.new - @p23 = Ruby23Parser.new - end - - def process s, f = "(string)", t = 10 - e = nil - [@p23, @p22, @p21, @p20, @p19, @p18].each do |parser| - begin - return parser.process s, f, t - rescue Racc::ParseError, RubyParser::SyntaxError => exc - e = exc - end - end - raise e - end - - alias :parse :process - - def reset - @p18.reset - @p19.reset - @p20.reset - @p21.reset - @p22.reset - @p23.reset - end - - def self.for_current_ruby - case RUBY_VERSION - when /^1\.8/ then - Ruby18Parser.new - when /^1\.9/ then - Ruby19Parser.new - when /^2.0/ then - Ruby20Parser.new - when /^2.1/ then - Ruby21Parser.new - when /^2.2/ then - Ruby22Parser.new - when /^2.3/ then - Ruby23Parser.new - else - raise "unrecognized RUBY_VERSION #{RUBY_VERSION}" - end - end -end diff --git a/test/test_ruby_lexer.rb b/test/test_ruby_lexer.rb index 97f1e83f..83f831d3 100755 --- a/test/test_ruby_lexer.rb +++ b/test/test_ruby_lexer.rb @@ -1,10 +1,8 @@ # encoding: US-ASCII -require 'rubygems' -require 'minitest/autorun' -require 'ruby_lexer' -require 'ruby18_parser' -require 'ruby20_parser' +require "minitest/autorun" +require "ruby_lexer" +require "ruby_parser" class TestRubyLexer < Minitest::Test attr_accessor :processor, :lex, :parser_class, :lex_state diff --git a/test/test_ruby_parser_extras.rb b/test/test_ruby_parser_extras.rb index 1edd949e..b94843cd 100644 --- a/test/test_ruby_parser_extras.rb +++ b/test/test_ruby_parser_extras.rb @@ -1,10 +1,8 @@ # encoding: US-ASCII -require 'rubygems' -require 'minitest/autorun' -require 'ruby_parser_extras' - -require 'minitest/test' +require "minitest/autorun" +require "ruby_parser_extras" +require "ruby_parser" class TestStackState < Minitest::Test attr_reader :s @@ -15,7 +13,7 @@ def setup def assert_encoding str, default = false orig_str = str.dup - p = Ruby19Parser.new + p = RubyParser.latest s = nil out, err = capture_io do