-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathgenerate.py
152 lines (106 loc) · 4.13 KB
/
generate.py
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import re
import os
import sys
# types for which no getters/ setter should be generated
SKIPTYPES = ("World",
"Route")
class ClassType:
def __init__(self, name):
self.name = name
self.parent = None
self.pure_virtual = False
self.setters = None
self.getters = None
def __repr__(self):
return "{}->{}".format(self.name, self.parent)
class MemberFun:
def __init__(self, name, type):
self.name = name
self.type = type
def __repr__(self):
return "{}({})".format(self.name, self.type)
def parse_hdr(hdr):
# class and inherited name pattern. Uses first parent in case of multiple inheritance
cls = re.compile(".*class ([^:^\s]+)\s*(?::\s*public\s+(\S+)\s*)?.*{.*")
# inherited class pattern
# prt = re.compile("\s*public\s+(\S+)\s*{.*")
# member setter method
setr = re.compile(".*void\s+(\S+)\(const\s*(\S+)&\s*[^,]+\s*\)")
# deprected setter pattern that also matches raw pointers
# setr = re.compile("\s*void\s+(\S+)\((?:const)?\s*(\S+)[\*&]\s*[^,]+\s*\)")
# member getter method
getr = re.compile("\s*const\s+(\S+)&\s*(\S+)\(\s*\).*const.*")
# pure virtual pattern
pvirt = re.compile(".*virtual.*=\s*0\s*;.*")
f = open(hdr)
n = None
public_section = False
setters = []
getters = []
for l in f:
if "public:" in l:
public_section = True
if "private:" in l or "protected:" in l:
public_section = False
if pvirt.match(l):
n.pure_virtual = True
if public_section:
m = setr.match(l)
if m:
setters.append(MemberFun(m.group(1), m.group(2)))
continue
m = getr.match(l)
if m:
getters.append(MemberFun(m.group(2), m.group(1)))
continue
# get class name and parent
m = cls.match(l)
if not m:
continue
type = m.group(1)
n = ClassType(type)
if m.lastindex > 1:
n.parent = m.group(2)
n.setters = setters
n.getters = getters
n.include = hdr
return n
def reflect_typeinfo(cls_type):
meminfo = []
for setter in cls_type.setters:
if setter.type in SKIPTYPES:
print("skipping", setter)
continue
meminfo.append(' ti.addSetter<{0}, &{2}::{1}>("{1}");'.format(setter.type, setter.name, cls_type.name))
for getter in cls_type.getters:
if getter.type in SKIPTYPES:
print("skipping", getter)
continue
meminfo.append(' ti.addGetter<{0}, &{2}::{1}>("{1}");'.format(getter.type, getter.name, cls_type.name))
setter = """ {{static TypeInfo<{0}> ti("{0}", "{1}");\n{2}}}""".format(cls_type.name, cls_type.parent, "\n".join(meminfo))
return setter
def generate_reflect_db(parsed):
includes = []
constructors = []
nnodes = 0
# node in vector of nodes
for n in parsed:
if n.pure_virtual:
#print "skipping class '{}' because it is pure virtual".format(n.name)
#continue
pass
path, header = os.path.split(n.include)
path, module = os.path.split(path)
includes.append("#include <{}/{}>".format(module, header))
constructors.append(reflect_typeinfo(n))
nnodes += 1
#constructors.insert(0, " _typeDB.reserve({0})\n".format(nnodes))
#constructors.insert(0, " _rttiDB.reserve({0})\n".format(nnodes))
db_in = open("db.cpp.in").read()
db_in = db_in.replace("<<includes>>", "\n".join(includes))
db_in = db_in.replace("<<constructors>>", "\n".join(constructors))
print("DB with {} Nodes created".format(nnodes))
open("db.cpp", "w").write(db_in)
if __name__ == "__main__":
parsed = [parse_hdr(h) for h in sys.argv[1:]]
generate_reflect_db(parsed)