A semantic search engine for source code https://bitshift.benkurtovic.com/
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

181 lines
4.4 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. processor = CachedWalker.new tree
  14. processor.process(tree)
  15. return processor.to_s
  16. end
  17. end
  18. class CachedWalker < SexpProcessor
  19. attr_accessor :symbols
  20. def initialize(tree)
  21. super()
  22. module_hash = Hash.new {
  23. |hash, key|
  24. hash[key] = { assignments: [], uses: [] }
  25. }
  26. class_hash = module_hash.clone
  27. function_hash = module_hash.clone
  28. var_hash = module_hash.clone
  29. @require_empty = false
  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)
  39. cur_exp = exp
  40. while cur_exp.is_a? Sexp
  41. end_ln = cur_exp.line
  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
  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. while (name = exp.shift).is_a? Sexp
  58. end
  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. while (name = exp.shift).is_a? Sexp
  67. end
  68. symbols[:classes][name][:assignments] << pos
  69. exp.each_sexp {|s| process(s)}
  70. return exp.clear
  71. end
  72. def process_defn(exp)
  73. pos = block_position(exp)
  74. exp.shift
  75. while (name = exp.shift).is_a? Sexp
  76. end
  77. symbols[:functions][name][:assignments] << pos
  78. exp.each_sexp {|s| process(s)}
  79. return exp.clear
  80. end
  81. def process_call(exp)
  82. pos = statement_position(exp)
  83. exp.shift
  84. exp.shift
  85. while (name = exp.shift).is_a? Sexp
  86. end
  87. symbols[:functions][name][:uses] << pos
  88. exp.each_sexp {|s| process(s)}
  89. return exp.clear
  90. end
  91. def process_iasgn(exp)
  92. pos = statement_position(exp)
  93. exp.shift
  94. while (name = exp.shift).is_a? Sexp
  95. end
  96. symbols[:vars][name][:assignments] << pos
  97. exp.each_sexp {|s| process(s)}
  98. return exp.clear
  99. end
  100. def process_lasgn(exp)
  101. pos = statement_position(exp)
  102. exp.shift
  103. while (name = exp.shift).is_a? Sexp
  104. end
  105. symbols[:vars][name][:assignments] << pos
  106. exp.each_sexp {|s| process(s)}
  107. return exp.clear
  108. end
  109. def process_attrasgn(exp)
  110. pos = statement_position(exp)
  111. exp.shift
  112. while (name = exp.shift).is_a? Sexp
  113. end
  114. symbols[:vars][((name.to_s)[0..-2]).to_sym][:assignments] << pos
  115. exp.each_sexp {|s| process(s)}
  116. return exp.clear
  117. end
  118. def process_lvar(exp)
  119. pos = statement_position(exp)
  120. exp.shift
  121. while (name = exp.shift).is_a? Sexp
  122. end
  123. symbols[:vars][name][:uses] << pos
  124. exp.each_sexp {|s| process(s)}
  125. return exp.clear
  126. end
  127. def to_s
  128. new_symbols = Hash.new {|hash, key| hash[key] = Hash.new}
  129. symbols.each do |type, sym_list|
  130. sym_list.each do |name, sym|
  131. new_symbols[type.to_s][name.to_s] = {
  132. "assignments" => sym[:assignments],
  133. "uses" => sym[:uses]}
  134. end
  135. end
  136. str = new_symbols.to_s
  137. str = str.gsub(/=>/, ":")
  138. return str
  139. end
  140. end
  141. end