diff --git a/class_dumper_cpp.py b/class_dumper_cpp.py index c62e4ba..85668e3 100644 --- a/class_dumper_cpp.py +++ b/class_dumper_cpp.py @@ -1,255 +1,259 @@ from class_dumper import ClassDumper from class_reader import ClassReader import os, re class ClassDumperCPP(ClassDumper): def __init__(self,output_dir): ClassDumper.__init__(self) self.output_dir = output_dir def dump(self,class_file): cls_reader = ClassReader() classes = cls_reader.read(class_file) for c in classes: self.dumpHeader(c) self.dumpCCFile(c) self.dumpMakefile(classes) return "" def dumpMakefile(self,classes): make_filename = os.path.join(self.output_dir,'Makefile') CC_files = [self.makeBaseFilename(c.name)+ ".cc" for c in classes] obj_files = [self.makeBaseFilename(c.name)+ ".o" for c in classes] header_files = [self.makeBaseFilename(c.name)+ ".hh" for c in classes] print CC_files print header_files sstr = """ CXXFLAGS=-g -Wall CC_FILES = {0} OBJ_FILES = {1} HEADER_FILES = {2} EXEC=main $(EXEC): $(OBJ_FILES) main.o \tg++ -g $(OBJ_FILES) main.o -o $@ .o: $(HEADER_FILES) \tg++ -c $(CXXFLAGS) $^ -o $@ clean: \trm -f *.o *~ $(EXEC) """.format(" ".join(CC_files)," ".join(obj_files)," ".join(header_files)) with open(make_filename,'w') as f: f.write(sstr) main_filename = os.path.join(self.output_dir,"main.cc") with open(main_filename,'w') as f: f.write(""" #include #include #include int main(int argc, char ** argv){ /// ... your code here ... return EXIT_FAILURE; }""") def makeBaseFilename(self,class_name): name = re.sub(r'([0-9]|[A-Z0-9])','_\g<1>',class_name) name = name.lower() if name[0] == '_': name = name[1:] return name def dumpHeader(self,c): basename = self.makeBaseFilename(c.name) header_filename = os.path.join(self.output_dir,basename+".hh") self.stage = 'header' sstr = self.formatClassDeclaration(c) sstr += self.formatConstructors(c) sstr += self.formatMethods(c) sstr += self.formatMembers(c) sstr += "};\n" with open(header_filename,'w') as f: print header_filename f.write("#ifndef __" + basename.upper() + "__HH__\n") f.write("#define __" + basename.upper() + "__HH__\n\n") f.write("/* -------------------------------------------------------------------------- */\n") if c.inheritance is not None: for herit in c.inheritance: f.write("#include \"" + self.makeBaseFilename(herit) + ".hh\"\n") f.write(sstr) f.write("\n/* -------------------------------------------------------------------------- */\n") f.write("#endif //__" + basename.upper() + "__HH__\n") def dumpCCFile(self,c): basename = self.makeBaseFilename(c.name) CC_filename = os.path.join(self.output_dir,basename+".cc") header_filename = os.path.join(self.output_dir,basename+".hh") self.stage = 'CC' sstr = self.formatConstructors(c) sstr += self.formatMethods(c) with open(CC_filename,'w') as f: print CC_filename f.write("#include \"" + os.path.basename(header_filename) + "\"\n") f.write("/* -------------------------------------------------------------------------- */\n\n") f.write(sstr) def formatClassDeclaration(self,c): sstr = "class " + c.name if c.inheritance is not None: sstr += ": public " + ", public ".join(c.inheritance) sstr += "{\n" return sstr def formatConstructors(self,c): sstr = "" for encaps in ['public','private', 'protected']: meths = c.getMethods(encaps) if c.name in meths: if self.stage == 'header': sstr += encaps + ':\n\n' for m in meths[c.name]: sstr += self.formatMethod(c,m) if '~' + c.name in meths: if self.stage == 'header' and sstr == "": sstr += encaps + ':\n\n' for m in meths['~' + c.name]: sstr += self.formatMethod(c,m) if not sstr == "" and self.stage == 'header': sstr = """ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ """ + sstr return sstr def formatMethods(self,c): sstr = "" for encaps in ['public','private', 'protected']: meths = c.getMethods(encaps) meths_names = set(meths.keys()) - set([c.name,'~'+c.name]) meths_names = list(meths_names) if len(meths_names) is not 0: if self.stage == 'header': sstr += encaps + ':\n\n' for n in meths_names: for m in meths[n]: sstr += self.formatMethod(c,m) sstr += "\n" if not sstr == "" and self.stage == 'header': sstr = """ /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ """ + sstr return sstr def formatMembers(self,c): sstr = "" for encaps in ['public','private', 'protected']: membs = c.getMembers(encaps) if len(membs) is not 0: if self.stage == 'header': sstr += encaps + ':\n\n' for n,m in membs.iteritems(): sstr += self.formatMember(c,m) sstr += "\n" if not sstr == "" and self.stage == 'header': sstr = """ /* ------------------------------------------------------------------------ */ /* Members */ /* ------------------------------------------------------------------------ */ """ + sstr return sstr def formatMethod(self,c,m): sstr = "" if self.stage == 'header': sstr = " " + + if m.static: sstr += m.static + " " if m.virtual in ['virtual','pure virtual']: sstr += "virtual " if (not m.ret == ""): sstr += m.ret + " " sstr += m.name + "(" sstr += ", ".join([a + " " + b for b,a in list(m.args.iteritems())]) sstr += ")" if m.virtual == 'pure virtual': sstr += "=0" sstr += ";\n" if self.stage == 'CC': sstr = "" if m.virtual == 'pure virtual': return "" sstr += m.ret + " " + c.name + "::" + m.name + "(" sstr += ", ".join([a + " " + b for b,a in list(m.args.iteritems())]) sstr += "){\n\n}\n\n" sstr += "\n" sstr += """ /* --------------------------------------------------------------------------- */ """ return sstr def formatMember(self,c,m): - sstr = " " + m.type + " " + m.name + ";" + sstr = " " + if m.static == 'static': sstr += 'static ' + sstr += m.type + " " + m.name + ";" return sstr import argparse if __name__ == '__main__': parser = argparse.ArgumentParser(description='CPP project producer for class representation') parser.add_argument('--class_file','-c', help='The class file to process',required=True) parser.add_argument('--output_dir','-o' , help='The directory where to put produced files',required=True) args = parser.parse_args() args = vars(args) os.makedirs(args['output_dir']) dumper_class = ClassDumperCPP(args['output_dir']) dumper_class.dump(args['class_file']) diff --git a/class_reader.py b/class_reader.py index f93f6ac..d63bce2 100644 --- a/class_reader.py +++ b/class_reader.py @@ -1,106 +1,106 @@ import re from class_decriptor import ClassDescriptor class ClassReader: def __init__(self): self.classes = [] self.current_class = None def read(self,filename): f = open(filename,'r') self.line_cpt = 0 for line in f: self.readline(line) self.line_cpt += 1 if self.current_class is not None: self.classes.append(self.current_class) return self.classes def readline(self,line): line = line.split('#')[0] line = line.strip() if line == "": return if self.isNewClassTag(line): return if self.isNewMethodTag(line): return if self.isNewTypedef(line): return if self.isNewMemberTag(line): return else: raise Exception("could not parse line:{0}\n'".format(self.line_cpt) + line + "'") def isNewClassTag(self,line): ret = False m = re.match(r'class\s+(\S*)',line) if m: name = m.group(1) inheritance = None ret = True m = re.match(r'class\s+(\S*)\((.*)\)',line) if m: name = m.group(1).strip() inheritance = m.group(2).strip() inheritance = inheritance.strip().split(',') inheritance = [e.strip() for e in inheritance] ret = True if ret == False: return False if self.current_class is not None: self.classes.append(self.current_class) self.current_class = ClassDescriptor(name,inheritance) return True def isNewMemberTag(self,line): if not line.find("(") == -1: return False if not line.find(")") == -1: return False m = re.match(r'((?:public|protected|private)*)\s*((?:static)?)\s*((?:\S|(?:\s+\*)|(?:\s+\&))+)\s+(.*)',line) if m: encapsulation = m.group(1).strip() static = m.group(2).strip() _type = m.group(3).strip() - name = m.group(3).strip() + name = m.group(4).strip() self.current_class.addMember(name,_type,encapsulation,static) return True return False def isNewTypedef(self,line): if not line.find("(") == -1: return False if not line.find(")") == -1: return False m = re.match(r'((?:public|protected|private)*)\s*typedef\s*(\S+)',line) if m: encapsulation = m.group(1).strip() name = m.group(2).strip() self.current_class.addType(name,encapsulation) return True return False def isNewMethodTag(self,line): m = re.match(r'((?:public|protected|private)*)\s*((?:static)?)\s*((?:virtual|pure virtual)?)\s*(.*)\s+([\S|~]*)\((.*)\)',line) if m: encapsulation = m.group(1).strip() static = m.group(2).strip() virtual = m.group(3).strip() ret = m.group(4).strip() name = m.group(5).strip() args = m.group(6).strip().split(',') args = [tuple(e.strip().split(' ')) for e in args] args = [e for e in args if not e[0] == ''] self.current_class.addMethod(name,args,ret,encapsulation,virtual,static) return True return False if __name__ == '__main__': cls_reader = ClassReader() classes = cls_reader.read('test.classes') for c in classes: print c