A semantic search engine for source code https://bitshift.benkurtovic.com/
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

parser.rb 3.9 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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 to_s
  109. new_symbols = Hash.new {|hash, key| hash[key] = Hash.new}
  110. symbols.each do |type, sym_list|
  111. sym_list.each do |name, sym|
  112. new_symbols[type.to_s][name.to_s] = {
  113. "assignments" => sym[:assignments],
  114. "uses" => sym[:uses]}
  115. end
  116. end
  117. str = new_symbols.to_s
  118. str = str.gsub(/=>/, ":")
  119. return str
  120. end
  121. end
  122. end