import re, os, shutil, string, sys def generateElements(elementFiles, outputCpp, outputH): elementClasses = {} baseClasses = {} elementHeader = """// This file is automatically generated by generator.py #ifndef ELEMENTCLASSES_H #define ELEMENTCLASSES_H #include #include "simulation/Element.h" #include "simulation/elements/Element.h" """ directives = [] for elementFile in elementFiles: try: f = open(elementFile, "r") except: f = open("src/simulation/elements/"+elementFile, "r") fileData = f.read() f.close() directiveMatcher = '//#TPT-Directive\s+([^\r\n]+)' matcher = re.compile(directiveMatcher) directiveMatches = matcher.findall(fileData) for match in directiveMatches: directives.append(match.split(" ")) classDirectives = [] usedIDs = [] for d in directives: if d[0] == "ElementClass": d[3] = int(d[3]) classDirectives.append(d) if d[3] in usedIDs: print("WARNING: duplicate element ID {} ({})".format(d[3],d[2])) usedIDs.append(d[3]) elementIDs = sorted(classDirectives, key=lambda directive: directive[3]) for d in elementIDs: tmpClass = d[1] newClass = "" baseClass = "Element" if ':' in tmpClass: classBits = tmpClass.split(':') newClass = classBits[0] baseClass = classBits[1] else: newClass = tmpClass elementClasses[newClass] = [] baseClasses[newClass] = baseClass elementHeader += "#define %s %s\n" % (d[2], d[3]) for d in directives: if d[0] == "ElementHeader": tmpClass = d[1] newClass = "" baseClass = "Element" if ':' in tmpClass: classBits = tmpClass.split(':') newClass = classBits[0] baseClass = classBits[1] else: newClass = tmpClass elementClasses[newClass].append(" ".join(d[2:])+";") #for className, classMembers in elementClasses.items(): for d in elementIDs: tmpClass = d[1] newClass = "" baseClass = "Element" if ':' in tmpClass: classBits = tmpClass.split(':') newClass = classBits[0] baseClass = classBits[1] else: newClass = tmpClass className = newClass classMembers = elementClasses[newClass] elementBase = baseClass elementHeader += """ class {0}: public {1} {{ public: {0}(); virtual ~{0}(); {2} }}; """.format(className, elementBase, str.join("\n\t", classMembers)) elementHeader += """ std::vector GetElements(); #endif """ elementContent = """#include "ElementClasses.h" std::vector GetElements() { std::vector elements; """; for d in elementIDs: tmpClass = d[1] newClass = "" baseClass = "Element" if ':' in tmpClass: classBits = tmpClass.split(':') newClass = classBits[0] baseClass = classBits[1] else: newClass = tmpClass elementContent += """elements.push_back(%s()); """ % (newClass) elementContent += """return elements; } """; outputPath, outputFile = os.path.split(outputH) if not os.path.exists(outputPath): os.makedirs(outputPath) f = open(outputH, "w") f.write(elementHeader) f.close() f = open(outputCpp, "w") f.write(elementContent) f.close() def generateTools(toolFiles, outputCpp, outputH): toolClasses = {} toolHeader = """#ifndef TOOLCLASSES_H #define TOOLCLASSES_H #include #include "simulation/simtools/SimTool.h" """ directives = [] for toolFile in toolFiles: try: f = open(toolFile, "r") except: f = open("src/simulation/simtools/"+toolFile, "r") fileData = f.read() f.close() directiveMatcher = '//#TPT-Directive\s+([^\r\n]+)' matcher = re.compile(directiveMatcher) directiveMatches = matcher.findall(fileData) for match in directiveMatches: directives.append(match.split(" ")) classDirectives = [] usedIDs = [] for d in directives: if d[0] == "ToolClass": toolClasses[d[1]] = [] toolHeader += "#define %s %s\n" % (d[2], d[3]) d[3] = int(d[3]) classDirectives.append(d) if d[3] in usedIDs: print("WARNING: duplicate tool ID {} ({})".format(d[3],d[2])) usedIDs.append(d[3]) for d in directives: if d[0] == "ToolHeader": toolClasses[d[1]].append(" ".join(d[2:])+";") for className, classMembers in list(toolClasses.items()): toolHeader += """ class {0}: public SimTool {{ public: {0}(); virtual ~{0}(); int Perform(Simulation * sim, Particle * cpart, int x, int y, int brushX, int brushY, float strength) override; }}; """.format(className, str.join("\n", classMembers)) toolHeader += """ std::vector GetTools(); #endif """ toolContent = """#include "ToolClasses.h" std::vector GetTools() { std::vector tools; """; toolIDs = sorted(classDirectives, key=lambda directive: directive[3]) for d in toolIDs: toolContent += """ tools.push_back(new %s()); """ % (d[1]) toolContent += """ return tools; } """; outputPath, outputFile = os.path.split(outputH) if not os.path.exists(outputPath): os.makedirs(outputPath) f = open(outputH, "w") f.write(toolHeader) f.close() f = open(outputCpp, "w") f.write(toolContent) f.close() generateElements(os.listdir("src/simulation/elements"), "generated/ElementClasses.cpp", "generated/ElementClasses.h") generateTools(os.listdir("src/simulation/simtools"), "generated/ToolClasses.cpp", "generated/ToolClasses.h")