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