Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 133 lines (105 sloc) 3.177 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
base = File.expand_path "../", __FILE__

unless Object.const_defined?(:RUBY_ENGINE) && RUBY_ENGINE == "rbx"
  ext_dir = "ruby"
  require base + "/mri_bridge"
else
  ext_dir = Object.const_get :RUBY_ENGINE
end

require base + "/ext/melbourne/#{ext_dir}/melbourne"
require base + "/melbourne/processor"

class String
  def to_ast(name="(eval)", line=1)
    Rubinius::Melbourne.parse_string self, name, line
  end

  def to_sexp(name="(eval)", line=1)
    to_ast(name, line).to_sexp
  end
end

class File
  def self.to_ast(name, line=1)
    Rubinius::Melbourne.parse_file name, line
  end

  def self.to_sexp(name, line=1)
    to_ast(name, line).to_sexp
  end
end

module Rubinius
  class Melbourne
    attr_accessor :transforms
    attr_accessor :magic_handler

    def self.parse_string(string, name="(eval)", line=1)
      new(name, line).parse_string string
    end

    def self.parse_file(name, line=1)
      new(name, line).parse_file
    end

    def self.remove_selected_parser
      remove_method :file_to_ast if method_defined? :file_to_ast
      remove_method :string_to_ast if method_defined? :string_to_ast
    end

    def self.select_18
      remove_selected_parser

      alias_method :file_to_ast, :file_to_ast_18
      alias_method :string_to_ast, :string_to_ast_18
    end

    def self.select_19
      STDERR.puts "NOTE: The 1.9 syntax parser is disabled while under construction"
      return

      remove_selected_parser

      alias_method :file_to_ast, :file_to_ast_19
      alias_method :string_to_ast, :string_to_ast_19
    end

    # Select the default parser language
    if Rubinius.ruby19? || Rubinius.ruby20?
      STDERR.puts "NOTE: The 1.9 syntax parser is disabled while under construction"
      select_18
    else
      select_18
    end

    def initialize(name, line, transforms=[])
      @name = name
      @line = line
      @transforms = transforms
      @magic_handler = nil
      @data_offset = nil

      # There can be multiple reported, we need to track them all.
      @syntax_errors = []
    end

    attr_reader :syntax_errors

    def add_magic_comment(str)
      if @magic_handler
        @magic_handler.add_magic_comment str
      end
    end

    def process_data(offset)
      @data_offset = offset
    end

    def syntax_error
      raise @syntax_errors[0] unless @syntax_errors.empty?
    end

    def parse_string(string)
      syntax_error unless ast = string_to_ast(string, @name, @line)
      ast
    end

    def parse_file
      unless @name and File.exists? @name
        raise Errno::ENOENT, @name.inspect
      end

      syntax_error unless ast = file_to_ast(@name, @line)
      ast = AST::EndData.new @data_offset, ast if @data_offset
      ast
    end

    def process_transforms(line, receiver, name, arguments, privately=false)
      @transforms.each do |transform|
        next unless transform.transform_kind == :call

        if node = transform.match?(line, receiver, name, arguments, privately)
          unless node.kind_of? AST::Node
            node = transform.new line, receiver, name, arguments, privately
          end
          return node
        end
      end
      nil
    end
  end
end
Something went wrong with that request. Please try again.