| @@ -1,6 +1,5 @@ | |||||
| require 'socket' | |||||
| require 'ruby_parser' | |||||
| require 'sexp_processor' | |||||
| require 'ripper' | |||||
| require 'pp' | |||||
| module Bitshift | module Bitshift | ||||
| class Parser | class Parser | ||||
| @@ -9,156 +8,119 @@ module Bitshift | |||||
| end | end | ||||
| def parse | def parse | ||||
| parser = RubyParser.new | |||||
| tree = parser.parse(@source) | |||||
| return '{}' if tree.nil? | |||||
| processor = CachedWalker.new tree | |||||
| processor.process(tree) | |||||
| return processor.to_s | |||||
| # new stuff | |||||
| walker = TreeWalker.new(@source) | |||||
| walker.parse | |||||
| return walker.to_s | |||||
| end | end | ||||
| end | end | ||||
| class CachedWalker < SexpProcessor | |||||
| class TreeWalker < Ripper::SexpBuilder | |||||
| attr_accessor :symbols | attr_accessor :symbols | ||||
| def initialize(tree) | |||||
| super() | |||||
| def initialize(source) | |||||
| ns_hash = Hash.new { | ns_hash = Hash.new { | ||||
| |hash, key| | |hash, key| | ||||
| hash[key] = { assignments: [], uses: [] } | |||||
| hash[key] = { | |||||
| :assignments => [], :uses => [] | |||||
| } | |||||
| } | } | ||||
| class_hash = ns_hash.clone | class_hash = ns_hash.clone | ||||
| function_hash = ns_hash.clone | function_hash = ns_hash.clone | ||||
| var_hash = ns_hash.clone | var_hash = ns_hash.clone | ||||
| @require_empty = false | |||||
| @symbols = { | @symbols = { | ||||
| namespaces: ns_hash, | |||||
| classes: class_hash, | |||||
| functions: function_hash, | |||||
| vars: var_hash | |||||
| :namespaces => ns_hash, | |||||
| :classes => class_hash, | |||||
| :functions => function_hash, | |||||
| :vars => var_hash | |||||
| } | } | ||||
| end | |||||
| def block_position(exp) | |||||
| end_ln = (start_ln = exp.line) | |||||
| cur_exp = exp | |||||
| while cur_exp.is_a? Sexp | |||||
| end_ln = cur_exp.line | |||||
| cur_exp = cur_exp.last | |||||
| break if cur_exp == nil | |||||
| end | |||||
| pos = [start_ln, -1, end_ln, -1] | |||||
| return pos | |||||
| super(source) | |||||
| end | end | ||||
| def statement_position(exp) | |||||
| pos = Hash.new | |||||
| end_ln = start_ln = exp.line | |||||
| pos = [start_ln, -1, end_ln, -1] | |||||
| return pos | |||||
| end | |||||
| def block_position(node) | |||||
| last_node = node[0] | |||||
| while last_node.is_a? Array | |||||
| sp = last_node | |||||
| while not (last_el = last_node[last_node.count - 1]) or | |||||
| (last_el.is_a? Array and last_el[last_el.count - 1].nil?) | |||||
| last_node = last_node[0..last_node.count - 2] | |||||
| end | |||||
| last_node = last_el | |||||
| end | |||||
| def process_module(exp) | |||||
| pos = block_position(exp) | |||||
| exp.shift | |||||
| last_node = node[0] | |||||
| while last_node.is_a? Array | |||||
| ep = last_node | |||||
| while not (last_el = last_node[last_node.count - 1]) or | |||||
| (last_el.is_a? Array and last_el[last_el.count - 1].nil?) | |||||
| last_node = last_node[0..last_node.count - 2] | |||||
| end | |||||
| last_node = last_el | |||||
| end | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| if sp == ep | |||||
| return sp + [sp[0], -1] | |||||
| end | end | ||||
| return sp + ep | |||||
| end | |||||
| def on_module(*node) | |||||
| pos = block_position(node) | |||||
| name = node[0][1][1] | |||||
| symbols[:namespaces][name][:assignments] << pos | symbols[:namespaces][name][:assignments] << pos | ||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| return node | |||||
| end | end | ||||
| def process_class(exp) | |||||
| pos = block_position(exp) | |||||
| exp.shift | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| end | |||||
| def on_class(*node) | |||||
| pos = block_position(node) | |||||
| name = node[0][1][1] | |||||
| symbols[:classes][name][:assignments] << pos | symbols[:classes][name][:assignments] << pos | ||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| return node | |||||
| end | end | ||||
| def process_defn(exp) | |||||
| pos = block_position(exp) | |||||
| exp.shift | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| end | |||||
| def on_def(*node) | |||||
| pos = block_position(node) | |||||
| name = node[0][1] | |||||
| symbols[:functions][name][:assignments] << pos | symbols[:functions][name][:assignments] << pos | ||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| return node | |||||
| end | end | ||||
| def process_call(exp) | |||||
| pos = statement_position(exp) | |||||
| exp.shift | |||||
| exp.shift | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| end | |||||
| def on_call(*node) | |||||
| pos = block_position(node) | |||||
| name = node[node.count - 1][1] | |||||
| symbols[:functions][name][:uses] << pos | symbols[:functions][name][:uses] << pos | ||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| return node | |||||
| end | end | ||||
| def process_iasgn(exp) | |||||
| pos = statement_position(exp) | |||||
| exp.shift | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| end | |||||
| symbols[:vars][name][:assignments] << pos | |||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| def on_vcall(*node) | |||||
| pos = block_position(node) | |||||
| name = node[0][1] | |||||
| symbols[:functions][name][:uses] << pos | |||||
| return node | |||||
| end | end | ||||
| def process_lasgn(exp) | |||||
| pos = statement_position(exp) | |||||
| exp.shift | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| end | |||||
| def on_assign(*node) | |||||
| pos = block_position(node) | |||||
| return node if not node[0][0].is_a? Array | |||||
| name = node[0][0][1] | |||||
| symbols[:vars][name][:assignments] << pos | symbols[:vars][name][:assignments] << pos | ||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| return node | |||||
| end | end | ||||
| def process_attrasgn(exp) | |||||
| pos = statement_position(exp) | |||||
| exp.shift | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| end | |||||
| symbols[:vars][((name.to_s)[0..-2]).to_sym][:assignments] << pos | |||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| def on_var_field(*node) | |||||
| pos = block_position(node) | |||||
| name = node[0][1] | |||||
| symbols[:vars][name][:uses] << pos | |||||
| return node | |||||
| end | end | ||||
| def process_lvar(exp) | |||||
| pos = statement_position(exp) | |||||
| exp.shift | |||||
| while (name = exp.shift).is_a? Sexp | |||||
| end | |||||
| def on_var_ref(*node) | |||||
| pos = block_position(node) | |||||
| name = node[0][1] | |||||
| symbols[:vars][name][:uses] << pos | symbols[:vars][name][:uses] << pos | ||||
| exp.each_sexp {|s| process(s)} | |||||
| return exp.clear | |||||
| return node | |||||
| end | end | ||||
| def to_s | def to_s | ||||