ast_to_json.rb
1.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env ruby
# Takes an clang-generated AST in stdin
# Outputs a D3-compliant JSON file
require 'json'
class CodeStruct
attr_accessor :name, :starts_at, :size
def initialize(parent, name, starts_at)
@parent = parent
@name = name
@starts_at = starts_at
@size = 0
@children = []
@parent.add_child(self) unless @parent.nil?
end
def ends_at(offset)
@size = offset-@starts_at
end
def add_child(s)
@children.push(s)
end
def as_d3_dict
res = {name: name}
if @children.empty?
res[:value] = size
else
res[:children] = @children.map{|c| c.as_d3_dict}
end
res
end
def log(space = 0)
puts (" "*space) + "#{name} (SIZE=#{size})"
@children.each do |child|
child.log(space+2)
end
end
end
def handleNewLine(line, index, stack)
# Example : " 213736 | class Timer (primary base)"
offset, depth, name = line.match(/\s*([0-9]+)\s\|(\s+)(.*)/).captures
offset = offset.to_i
depth = (depth.size-1)/2
parent = stack[depth-1]
stack[depth..-1].each do |finished|
finished.ends_at(offset)
end
stack = stack[0...depth]
struct = CodeStruct.new(parent, name, offset)
stack.push(struct)
return stack
end
class_name = ARGV[0]
stack = []
ignore_line = true
STDIN.each_line.with_index do |l,i|
if l == " 0 | class #{class_name}\n"
ignore_line = false
end
if l.start_with?(" | ") && ignore_line == false
ignore_line = true
end_offset = l.match(/sizeof=([0-9]+)/).captures.first
end_offset = end_offset.to_i
stack[-1].ends_at(end_offset)
stack[0].ends_at(end_offset)
end
unless ignore_line
stack = handleNewLine(l, i, stack)
end
end
puts JSON.generate(stack[0].as_d3_dict)