-
Notifications
You must be signed in to change notification settings - Fork 609
/
melbourne.rb
102 lines (82 loc) · 2.29 KB
/
melbourne.rb
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
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 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