|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- 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
|