|
|
@@ -0,0 +1,125 @@ |
|
|
|
require 'socket' |
|
|
|
require 'ruby_parser' |
|
|
|
require 'sexp_processor' |
|
|
|
|
|
|
|
module Bitshift |
|
|
|
class Parser |
|
|
|
def initialize(source) |
|
|
|
@source = source |
|
|
|
end |
|
|
|
|
|
|
|
def parse |
|
|
|
parser = RubyParser.new |
|
|
|
tree = parser.parse(@source) |
|
|
|
offset = tree.line - 1 |
|
|
|
processor = NodeVisitor.new offset |
|
|
|
processor.process tree |
|
|
|
return processor.symbols |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
class NodeVisitor < SexpProcessor |
|
|
|
attr_accessor :symbols |
|
|
|
attr_accessor :offset |
|
|
|
|
|
|
|
def initialize(offset) |
|
|
|
super() |
|
|
|
@require_empty = false |
|
|
|
@offset = offset |
|
|
|
|
|
|
|
module_hash = Hash.new {|hash, key| hash[key] = Hash.new} |
|
|
|
class_hash = module_hash.clone |
|
|
|
function_hash = Hash.new {|hash, key| hash[key] = { calls: [] } } |
|
|
|
var_hash = Hash.new {|hash, key| hash[key] = [] } |
|
|
|
|
|
|
|
@symbols = { |
|
|
|
modules: module_hash, |
|
|
|
classes: class_hash, |
|
|
|
functions: function_hash, |
|
|
|
vars: var_hash |
|
|
|
} |
|
|
|
end |
|
|
|
|
|
|
|
def block_position(exp) |
|
|
|
pos = Hash.new |
|
|
|
end_ln = (start_ln = exp.line - offset) |
|
|
|
cur_exp = exp |
|
|
|
|
|
|
|
while cur_exp.is_a? Sexp |
|
|
|
end_ln = cur_exp.line - offset |
|
|
|
cur_exp = cur_exp.last |
|
|
|
break if cur_exp == nil |
|
|
|
end |
|
|
|
|
|
|
|
pos[:coord] = { |
|
|
|
start_ln: start_ln, |
|
|
|
end_ln: end_ln } |
|
|
|
return pos |
|
|
|
end |
|
|
|
|
|
|
|
def statement_position(exp) |
|
|
|
pos = Hash.new |
|
|
|
end_ln = start_ln = exp.line - offset |
|
|
|
|
|
|
|
pos[:coord] = { |
|
|
|
start_ln: start_ln, |
|
|
|
end_ln: end_ln } |
|
|
|
return pos |
|
|
|
end |
|
|
|
|
|
|
|
def process_module(exp) |
|
|
|
pos = block_position exp |
|
|
|
exp.shift |
|
|
|
name = exp.shift |
|
|
|
symbols[:modules][name] = pos |
|
|
|
exp.each_sexp {|s| process(s)} |
|
|
|
return exp.clear |
|
|
|
end |
|
|
|
|
|
|
|
def process_class(exp) |
|
|
|
pos = block_position exp |
|
|
|
exp.shift |
|
|
|
name = exp.shift |
|
|
|
symbols[:classes][name] = pos |
|
|
|
exp.each_sexp {|s| process(s)} |
|
|
|
return exp.clear |
|
|
|
end |
|
|
|
|
|
|
|
def process_defn(exp) |
|
|
|
pos = block_position exp |
|
|
|
exp.shift |
|
|
|
name = exp.shift |
|
|
|
symbols[:functions][name][:declaration] = pos |
|
|
|
exp.each_sexp {|s| process(s)} |
|
|
|
return exp.clear |
|
|
|
end |
|
|
|
|
|
|
|
def process_call(exp) |
|
|
|
pos = statement_position exp |
|
|
|
exp.shift |
|
|
|
exp.shift |
|
|
|
name = exp.shift |
|
|
|
symbols[:functions][name][:calls] << pos |
|
|
|
exp.each_sexp {|s| process(s)} |
|
|
|
return exp.clear |
|
|
|
end |
|
|
|
|
|
|
|
def process_iasgn(exp) |
|
|
|
pos = statement_position exp |
|
|
|
exp.shift |
|
|
|
name = exp.shift |
|
|
|
symbols[:vars][name] << pos |
|
|
|
exp.each_sexp {|s| process(s)} |
|
|
|
return exp.clear |
|
|
|
end |
|
|
|
|
|
|
|
def process_lasgn(exp) |
|
|
|
pos = statement_position exp |
|
|
|
exp.shift |
|
|
|
name = exp.shift |
|
|
|
symbols[:vars][name] << pos |
|
|
|
exp.each_sexp {|s| process(s)} |
|
|
|
return exp.clear |
|
|
|
end |
|
|
|
end |
|
|
|
end |