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.
 
 
 
 
 
 

147 lines
4.0 KiB

  1. require 'ripper'
  2. require 'pp'
  3. module Bitshift
  4. class Parser
  5. def initialize(source)
  6. @source = source
  7. end
  8. def parse
  9. # new stuff
  10. walker = TreeWalker.new(@source)
  11. walker.parse
  12. return walker.to_s
  13. end
  14. end
  15. class TreeWalker < Ripper::SexpBuilder
  16. attr_accessor :symbols
  17. def initialize(source)
  18. ns_hash = Hash.new {
  19. |hash, key|
  20. hash[key] = {
  21. :assignments => [], :uses => []
  22. }
  23. }
  24. class_hash = ns_hash.clone
  25. function_hash = ns_hash.clone
  26. var_hash = ns_hash.clone
  27. @symbols = {
  28. :namespaces => ns_hash,
  29. :classes => class_hash,
  30. :functions => function_hash,
  31. :vars => var_hash
  32. }
  33. super(source)
  34. end
  35. def block_position(node)
  36. last_node = node[0]
  37. while last_node.is_a? Array
  38. sp = last_node
  39. while not (last_el = last_node[last_node.count - 1]) or
  40. (last_el.is_a? Array and last_el[last_el.count - 1].nil?)
  41. last_node = last_node[0..last_node.count - 2]
  42. end
  43. last_node = last_el
  44. end
  45. last_node = node[0]
  46. while last_node.is_a? Array
  47. ep = last_node
  48. while not (last_el = last_node[last_node.count - 1]) or
  49. (last_el.is_a? Array and last_el[last_el.count - 1].nil?)
  50. last_node = last_node[0..last_node.count - 2]
  51. end
  52. last_node = last_el
  53. end
  54. if sp == ep
  55. return sp + [sp[0], -1]
  56. end
  57. return sp + ep
  58. end
  59. def on_module(*node)
  60. pos = block_position(node)
  61. name = node[0][1][1]
  62. symbols[:namespaces][name][:assignments] << pos
  63. return node
  64. end
  65. def on_class(*node)
  66. pos = block_position(node)
  67. name = node[0][1][1]
  68. symbols[:classes][name][:assignments] << pos
  69. return node
  70. end
  71. def on_def(*node)
  72. pos = block_position(node)
  73. name = node[0][1]
  74. symbols[:functions][name][:assignments] << pos
  75. return node
  76. end
  77. def on_call(*node)
  78. pos = block_position(node)
  79. name = node[node.count - 1][1]
  80. symbols[:functions][name][:uses] << pos
  81. return node
  82. end
  83. def on_vcall(*node)
  84. pos = block_position(node)
  85. name = node[0][1]
  86. symbols[:functions][name][:uses] << pos
  87. return node
  88. end
  89. def on_assign(*node)
  90. pos = block_position(node)
  91. return node if not node[0][0].is_a? Array
  92. name = node[0][0][1]
  93. symbols[:vars][name][:assignments] << pos
  94. return node
  95. end
  96. def on_var_field(*node)
  97. pos = block_position(node)
  98. name = node[0][1]
  99. symbols[:vars][name][:uses] << pos
  100. return node
  101. end
  102. def on_var_ref(*node)
  103. pos = block_position(node)
  104. name = node[0][1]
  105. symbols[:vars][name][:uses] << pos
  106. return node
  107. end
  108. def on_command(*node)
  109. # catch require statements
  110. end
  111. def to_s
  112. new_symbols = Hash.new {|hash, key| hash[key] = Hash.new}
  113. symbols.each do |type, sym_list|
  114. sym_list.each do |name, sym|
  115. new_symbols[type.to_s][name.to_s] = {
  116. "assignments" => sym[:assignments],
  117. "uses" => sym[:uses]}
  118. end
  119. end
  120. str = new_symbols.to_s
  121. str = str.gsub(/=>/, ":")
  122. return str
  123. end
  124. end
  125. end