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.
 
 
 
 
 
 

126 lines
3.3 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 = NodeVisitor.new offset
  14. processor.process tree
  15. return processor.symbols
  16. end
  17. end
  18. class NodeVisitor < SexpProcessor
  19. attr_accessor :symbols
  20. attr_accessor :offset
  21. def initialize(offset)
  22. super()
  23. @require_empty = false
  24. @offset = offset
  25. module_hash = Hash.new {|hash, key| hash[key] = Hash.new}
  26. class_hash = module_hash.clone
  27. function_hash = Hash.new {|hash, key| hash[key] = { calls: [] } }
  28. var_hash = Hash.new {|hash, key| hash[key] = [] }
  29. @symbols = {
  30. modules: module_hash,
  31. classes: class_hash,
  32. functions: function_hash,
  33. vars: var_hash
  34. }
  35. end
  36. def block_position(exp)
  37. pos = Hash.new
  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[:coord] = {
  46. start_ln: start_ln,
  47. end_ln: end_ln }
  48. return pos
  49. end
  50. def statement_position(exp)
  51. pos = Hash.new
  52. end_ln = start_ln = exp.line - offset
  53. pos[:coord] = {
  54. start_ln: start_ln,
  55. end_ln: end_ln }
  56. return pos
  57. end
  58. def process_module(exp)
  59. pos = block_position exp
  60. exp.shift
  61. name = exp.shift
  62. symbols[:modules][name] = pos
  63. exp.each_sexp {|s| process(s)}
  64. return exp.clear
  65. end
  66. def process_class(exp)
  67. pos = block_position exp
  68. exp.shift
  69. name = exp.shift
  70. symbols[:classes][name] = pos
  71. exp.each_sexp {|s| process(s)}
  72. return exp.clear
  73. end
  74. def process_defn(exp)
  75. pos = block_position exp
  76. exp.shift
  77. name = exp.shift
  78. symbols[:functions][name][:declaration] = pos
  79. exp.each_sexp {|s| process(s)}
  80. return exp.clear
  81. end
  82. def process_call(exp)
  83. pos = statement_position exp
  84. exp.shift
  85. exp.shift
  86. name = exp.shift
  87. symbols[:functions][name][:calls] << 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. name = exp.shift
  95. symbols[:vars][name] << pos
  96. exp.each_sexp {|s| process(s)}
  97. return exp.clear
  98. end
  99. def process_lasgn(exp)
  100. pos = statement_position exp
  101. exp.shift
  102. name = exp.shift
  103. symbols[:vars][name] << pos
  104. exp.each_sexp {|s| process(s)}
  105. return exp.clear
  106. end
  107. end
  108. end