static void CollectDirectory(string dir, CodeGenerationManifest manifest) { dir = Path.GetFullPath(dir); if (!Directory.Exists(dir)) { Error("Directory \"{0}\" doesn't exist", dir); } // Get all header files string[] files = Directory.GetFiles(dir); foreach (string file in files) { if (Path.GetExtension(file) != ".h") { continue; } FileParser.Parse(file, manifest); } // Continue recursively string[] childDirs = Directory.GetDirectories(dir); foreach (string child in childDirs) { CollectDirectory(child, manifest); } }
public static void ProcessComponent(Component comp, CodeGenerationManifest manifest) { string serializeSource = "", initializeSource = "", staticTypeSource = ""; List <Function> generatedFunctions = new List <Function>(); //---------- Type binder { StringWriter sourceWriter = new StringWriter(); sourceWriter.WriteLine("namespace {"); sourceWriter.WriteLine("ComponentType::Bind<{0}> {0}_BIND( \"{0}\", {1} );", comp.Name, comp.Id); sourceWriter.WriteLine("}"); comp.GeneratedTypeBinder = sourceWriter.ToString(); } //---------- Serialize Function if (!comp.HasUserSerialize) { const string SERIALIZE_FORMAT = "archive.Serialize<{0}>(\"{1}\", {2});"; StringWriter sourceWriter = new StringWriter(); sourceWriter.WriteLine("{0}::Serialize( archive );", comp.Parent); foreach (Property prop in comp.Properties) { if (Array.IndexOf(prop.MetaData, "Serialize") == -1) { continue; } sourceWriter.WriteLine(SERIALIZE_FORMAT, prop.Parameter.Type, prop.CleanName, prop.Parameter.Name); } sourceWriter.WriteLine("OnSerialized();"); serializeSource = sourceWriter.ToString(); generatedFunctions.Add(ConstructFunction("public", "void", "Serialize", "", "override", serializeSource, ConstructParameter("NamedArchive&", "archive"))); } //---------- Initialize function { StringWriter sourceWriter = new StringWriter(); sourceWriter.WriteLine("{0}::InitializeInternal();", comp.Parent, comp.Id); sourceWriter.WriteLine("m_Type = StaticType();"); foreach (Property prop in comp.Properties) { sourceWriter.WriteLine("RegisterProperty<{0}>( \"{1}\", &{2} );", prop.Parameter.Type, prop.CleanName, prop.Parameter.Name); } initializeSource = sourceWriter.ToString(); generatedFunctions.Add(ConstructFunction("public", "void", "InitializeInternal", "", "override", initializeSource)); } //---------- Static Type function { StringWriter sourceWriter = new StringWriter(); sourceWriter.WriteLine("return {0}_BIND.ToType();", comp.Name); staticTypeSource = sourceWriter.ToString(); generatedFunctions.Add(ConstructFunction("public", "const ComponentType&", "StaticType", "static", "", staticTypeSource)); } comp.GeneratedFunctions = generatedFunctions.ToArray(); }
static int Main(string[] args) { if (args.Length < 2) { Utils.Print("Usage: CodeGen source target [/G] [/V]\n /G - Allow generating new files. Otherwise will error if new files have to be created.\n /V - Verbal, will display additional debug information."); Utils.Print("\nSupplied {0} arguments:", args.Length); foreach (string arg in args) { Utils.Print("\t{0}", arg); } return(1); } GenData = new GenerationData(); GenData.SourcePath = Path.GetFullPath(args[0]); GenData.TargetPath = Path.GetFullPath(args[1]); GenData.CanGenerate = args.Contains("/G"); GenData.Verbal = args.Contains("/V"); if (Path.HasExtension(GenData.SourcePath) || Path.HasExtension(GenData.TargetPath)) { Utils.Print("Using a file as source/target is invalid, only directories are supported"); return(1); } if (!Directory.Exists(GenData.SourcePath)) { Utils.Print("Couldn't find source directory \"{0}\"", GenData.SourcePath); return(1); } Utils.Print("-- GENERATING FILES --\n\"{0}\" => \"{1}\"", GenData.SourcePath, GenData.TargetPath, GenData.CanGenerate); Utils.PrintVerbal("CanGenerate: {2}", GenData.SourcePath, GenData.TargetPath, GenData.CanGenerate); if (!Directory.Exists(GenData.TargetPath)) { Directory.CreateDirectory(GenData.TargetPath); Utils.Print("Created directory \"{0}\"", GenData.TargetPath); } if (!Directory.Exists(GenData.CachePath)) { Directory.CreateDirectory(GenData.CachePath); Utils.Print("Created directory \"{0}\"", GenData.CachePath); } // Collect manifest CodeGenerationManifest manifest = new CodeGenerationManifest(); manifest.Components = new List <Component>(); CollectDirectory(GenData.SourcePath, manifest); manifest.Print(); Utils.PrintVerbal("\n- Generating..."); // Process foreach (Component comp in manifest.Components) { Process.ProcessComponent(comp, manifest); } // Generate if (GenData.CanGenerate) { // If generate is enabled, clean the directory first string[] files = Directory.GetFiles(GenData.TargetPath); foreach (string file in files) { File.Delete(file); } } foreach (Component comp in manifest.Components) { if (!comp.File.IsDirty) { continue; } // Source using (FileStream fileStream = OpenSource(comp.File)) { SourceWriter writer = new SourceWriter(comp.File, fileStream); writer.WriteComponent(comp); writer.Flush(); writer.Close(); Utils.Print(comp.File.GenSrcFileName); } // Header using (FileStream fileStream = OpenHeader(comp.File)) { HeaderWriter writer = new HeaderWriter(comp.File, fileStream); writer.WriteComponent(comp); writer.Flush(); writer.Close(); Utils.Print(comp.File.GenHeaderFileName); } } Utils.Print("-- GENERATION DONE --"); return(0); }
public static void Parse(string sourcePath, CodeGenerationManifest manifest) { if (!File.Exists(sourcePath)) { CodeGen.Error("File \"{0}\" does not exist.", sourcePath); return; } SourceFile file = new SourceFile(); file.FileName = Path.GetFileName(sourcePath); file.FullPath = sourcePath; file.Source = File.ReadAllText(sourcePath).Replace("\r", ""); file.IsDirty = false; CurrentFile = file; bool fileShouldBeGenerated = false; // ----------------------------- Collect Components MatchCollection match = COMP_RGX.Matches(file.Source); if (match.Count > 0) { fileShouldBeGenerated = true; string[] namespaces = Utils.FindNamespaces(file.Source, match[0].Index); string[] metadata = ParseMetadata(match[0].Groups[1].Value); Component comp = new Component(); comp.File = file; comp.Name = match[0].Groups[2].Value; comp.Parent = match[0].Groups[3].Value; comp.MetaData = metadata; comp.Namespaces = namespaces; comp.Id = manifest.Components.Count; comp.HasUserSerialize = SERIALIZE_RGX.Match(match[0].Groups[4].Value).Success; // Parse functions { MatchCollection funcMatch = FUNC_RGX.Matches(match[0].Value); Function[] compFunctions = new Function[funcMatch.Count]; for (int f = 0; f < funcMatch.Count; ++f) { string[] funcMetaData = ParseMetadata(funcMatch[f].Groups[1].Value); Function func = new Function(); func.Name = funcMatch[f].Groups[3].Value; func.ReturnType = funcMatch[f].Groups[2].Value; func.Arguments = ParseParameters(funcMatch[f].Groups[4].Value); func.MetaData = funcMetaData; compFunctions[f] = func; } comp.Functions = compFunctions; } // Parse properties { MatchCollection propMatch = PROP_RGX.Matches(match[0].Value); Property[] compProperties = new Property[propMatch.Count]; for (int p = 0; p < propMatch.Count; ++p) { string[] propMetaData = ParseMetadata(propMatch[p].Groups[1].Value); Property prop = new Property(); prop.Parameter.Type = propMatch[p].Groups[2].Value; prop.Parameter.Name = propMatch[p].Groups[3].Value; prop.CleanName = CleanPropertyName(prop.Parameter.Name); prop.MetaData = propMetaData; compProperties[p] = prop; } comp.Properties = compProperties; } Utils.PrintVerbal("({0}) Parsed component \"{1}\"...", file.FileName, comp.Name); manifest.Components.Add(comp); } if (fileShouldBeGenerated) { file.IsDirty = GetFileIsDirty(file); } }