A semantic search engine for source code https://bitshift.benkurtovic.com/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

140 lines
3.7 KiB

  1. require 'socket'
  2. require 'ruby_parser'
  3. require 'sexp_processor'
  4. module Bitshift
  5. class Parser
  6. def initialize(source)
  7. @source = source
  8. end
  9. def parse
  10. parser = RubyParser.new
  11. tree = parser.parse(@source)
  12. return '{}' if tree.nil?
  13. offset = tree.line - 1
  14. processor = CachedWalker.new offset, tree
  15. processor.process(tree)
  16. return processor.to_s
  17. end
  18. end
  19. class CachedWalker < SexpProcessor
  20. attr_accessor :symbols
  21. attr_accessor :offset
  22. def initialize(offset, tree)
  23. super()
  24. module_hash = Hash.new {|hash, key|
  25. hash[key] = { assignments: [], uses: [] }}
  26. class_hash = module_hash.clone
  27. function_hash = module_hash.clone
  28. var_hash = module_hash.clone
  29. @require_empty = false
  30. @offset = offset
  31. @symbols = {
  32. modules: module_hash,
  33. classes: class_hash,
  34. functions: function_hash,
  35. vars: var_hash
  36. }
  37. end
  38. def block_position(exp)
  39. end_ln = (start_ln = exp.line - offset)
  40. cur_exp = exp
  41. while cur_exp.is_a? Sexp
  42. end_ln = cur_exp.line - offset
  43. cur_exp = cur_exp.last
  44. break if cur_exp == nil
  45. end
  46. pos = [start_ln, -1, end_ln, -1]
  47. return pos
  48. end
  49. def statement_position(exp)
  50. pos = Hash.new
  51. end_ln = start_ln = exp.line - offset
  52. pos = [start_ln, -1, end_ln, -1]
  53. return pos
  54. end
  55. def process_module(exp)
  56. pos = block_position(exp)
  57. exp.shift
  58. name = exp.shift
  59. symbols[:modules][name][:assignments] << pos
  60. exp.each_sexp {|s| process(s)}
  61. return exp.clear
  62. end
  63. def process_class(exp)
  64. pos = block_position(exp)
  65. exp.shift
  66. name = exp.shift
  67. symbols[:classes][name][:assignments] << pos
  68. exp.each_sexp {|s| process(s)}
  69. return exp.clear
  70. end
  71. def process_defn(exp)
  72. pos = block_position(exp)
  73. exp.shift
  74. name = exp.shift
  75. symbols[:functions][name][:assignments] << pos
  76. exp.each_sexp {|s| process(s)}
  77. return exp.clear
  78. end
  79. def process_call(exp)
  80. pos = statement_position(exp)
  81. exp.shift
  82. exp.shift
  83. name = exp.shift
  84. symbols[:functions][name][:uses] << pos
  85. exp.each_sexp {|s| process(s)}
  86. return exp.clear
  87. end
  88. def process_iasgn(exp)
  89. pos = statement_position(exp)
  90. exp.shift
  91. name = exp.shift
  92. symbols[:vars][name][:assignments] << pos
  93. exp.each_sexp {|s| process(s)}
  94. return exp.clear
  95. end
  96. def process_lasgn(exp)
  97. pos = statement_position(exp)
  98. exp.shift
  99. name = exp.shift
  100. symbols[:vars][name][:assignments] << pos
  101. exp.each_sexp {|s| process(s)}
  102. return exp.clear
  103. end
  104. def to_s
  105. new_symbols = Hash.new {|hash, key| hash[key] = Hash.new}
  106. symbols.each do |type, sym_list|
  107. sym_list.each do |name, sym|
  108. new_symbols[type.to_s][name.to_s] = {
  109. "assignments" => sym[:assignments],
  110. "uses" => sym[:uses]}
  111. end
  112. end
  113. str = new_symbols.to_s
  114. str = str.gsub(/=>/, ":")
  115. return str
  116. end
  117. end
  118. end