/// <summary> /// コード生成 /// </summary> /// <param name="mergedLSFile">マージ済みのレイヤ構造ファイル</param> private void GenerateCode(LayerStructureFile mergedLSFile) { // ソースコードディレクトリのルートパスを取得 string includeFilePath = OutputFile; if (SourceRootPath != "/") { string generateCodePath = Path.GetFullPath(OutputFile); string sourceRootPath = Path.GetFullPath(SourceRootPath); if (generateCodePath.StartsWith(sourceRootPath)) { includeFilePath = generateCodePath.Substring(sourceRootPath.Length); includeFilePath = includeFilePath.Replace('\\', '/'); includeFilePath = "./" + includeFilePath; } } // コードジェネレート var result = _RTCOPCodeGenerator.GenerateCode(mergedLSFile, includeFilePath); foreach (string filename in result.CodeDictionary.Keys) { string filepath = OutputFile + filename; string dirpath = Path.GetDirectoryName(filepath); if (!Directory.Exists(dirpath)) { Directory.CreateDirectory(dirpath); } using (StreamWriter sw = new StreamWriter(filepath, false, Encoding)) { sw.Write(result.CodeDictionary[filename]); } } }
/// <summary> /// コンフィグファイルの反映 /// </summary> /// <param name="lsFile">レイヤ構造ファイル</param> /// <returns>反映後のレイヤ構造ファイル</returns> private LayerStructureFile ReflectConfigFile(LayerStructureFile lsFile) { if (_RTCOPConfigFile != null) { // 実行優先度に基づいたソート List <LayerStructure> newLayerStructureList = new List <LayerStructure>(); foreach (var lconfig in _RTCOPConfigFile.LayerConfigs) { var ls = lsFile.LayerStructures.Find((obj) => obj.LayerName == lconfig.LayerName); if (ls != null) { newLayerStructureList.Add(ls); lsFile.LayerStructures.Remove(ls); } } // コンフィグファイルに載ってなかったものを突っ込む if (lsFile.LayerStructures.Count > 0) { newLayerStructureList.AddRange(lsFile.LayerStructures); lsFile.LayerStructures.Clear(); } // ソート済みのものを入れなおす lsFile.LayerStructures.AddRange(newLayerStructureList); } return(lsFile); }
/// <summary> /// コンパイル実行。 /// </summary> public void Compile() { // ソースファイルが無い場合 if (SourceFiles.Count <= 0) { // エラー throw new Exception("ソースファイルが1つも無いです。"); } // ソースファイルの読み込み List <LayerStructureFile> lstrs = new List <LayerStructureFile>(); foreach (string fileName in SourceFiles) { if (Path.GetExtension(fileName) == ".lcpp") { // .lcppをコンパイル LayerStructureFile result = CompileLCppToObjectFile(fileName); lstrs.Add(result); } else { // レイヤ構造ファイルを読み込み LayerStructureFile result = LayerStructureFile.LoadFile(fileName); lstrs.Add(result); } } // レイヤ構造ファイルのマージ LayerStructureFile mergedLSFile = _RTCOPCompiler.MergeObjectFiles(lstrs); // 出力ファイルがC++のソースコードか、レイヤ構造ファイルかを確認 bool outputIsCpp = OutputFile.EndsWith("/") || OutputFile.EndsWith("\\"); if (!outputIsCpp && (Path.GetExtension(OutputFile) == "")) { // 拡張子無しの場合フォルダと判断 outputIsCpp = true; OutputFile += "/"; } // ソースコード出力 if (outputIsCpp) { GenerateCode(mergedLSFile); } // レイヤ構造出力 else { LayerStructureFile.SaveFile(OutputFile, mergedLSFile); } }
public static void Test() { string src = @" baselayer { // ベースクラス base class Sample { public: Sample(); virtual ~Sample(); }; } "; var text = RTCOPParser.BaseLayerDefinition.TokenWithSkipComment().Many().Parse(src); //var text = PreprocessParser.DirectiveOrLine.TokenWithSkipCommentForPreprocessParser().Many().Parse(src2); //var text = RTCOPParser.BaseLayerDefinition.TokenWithSkipComment().Many().Parse(src); //var text = TokenParser.Token.TokenWithSkipComment().Many().Parse(src); //var text = PreprocessParser.Directive.TokenWithSkipCommentForPreprocessParser().Many().Parse(src); //foreach (var t in text) Console.WriteLine(t); //Console.WriteLine(text); RTCOPSourceFile f = new RTCOPSourceFile("a.lcpp", src); RTCOPPreprocessor p = new RTCOPPreprocessor(new string[0], new List <string>(), Encoding.UTF8); var f2 = p.Run(f); Console.WriteLine(f2.Text); RTCOPCompiler c = new RTCOPCompiler(null); var of = c.Compile(f2); LayerStructureFile.SaveFile(@"C:\Users\Ikuta\Desktop\aaa.lobj", of); var of2 = LayerStructureFile.LoadFile(@"C:\Users\Ikuta\Desktop\aaa.lobj"); }
/// <summary> /// コード生成 /// </summary> /// <param name="mergedLSFile">マージ済みのレイヤ構造ファイル</param> /// <param name="includeFilePath">インクルードファイルパス</param> /// <returns>生成後のソースコード</returns> public GeneratedCodes GenerateCode(LayerStructureFile mergedLSFile, string includeFilePath) { GeneratedCodes result = new GeneratedCodes(); // ライブラリのヘッダファイルを追加 result.CodeDictionary[@"Layer_Private.h"] = Properties.Resources.Layer_Private_Header; result.CodeDictionary[@"LayerdObject_Private.h"] = Properties.Resources.LayerdObject_Private_Header; // ベースクラスを調べる LayerStructure baselayerStructure = mergedLSFile.BaseLayerStructure; if (baselayerStructure == null) { // ベースレイヤは定義されていなくても、自動的に生成される baselayerStructure = new LayerStructure("baselayer"); mergedLSFile.BaseLayerStructure = baselayerStructure; } List <string> baseClassNameList = new List <string>(); List <List <LayerdMethodDefinition> > baseMethodLists = new List <List <LayerdMethodDefinition> >(); List <List <ConstructorDefinition> > constructorLists = new List <List <ConstructorDefinition> >(); List <int> superClassIDs = new List <int>(); Action <IEnumerable <object>, string, int> createBaseClassAndMethodList = null; createBaseClassAndMethodList = (items, nspace, classId) => { foreach (object item in items) { if (item is LayerDefinition) { var ld = (LayerDefinition)item; string nspace2 = "baselayer"; createBaseClassAndMethodList(ld.Contents, nspace2, -1); } else if (item is NamespaceDefinition) { var nd = (NamespaceDefinition)item; string nspace2 = nd.Name; if (nspace != "") { nspace2 = nspace + "::" + nspace2; } createBaseClassAndMethodList(nd.Contents, nspace2, -1); } else if (item is LayerdClassDefinition) { var lcd = (LayerdClassDefinition)item; string classname = lcd.Name; if (nspace != "") { classname = nspace + "::" + classname; } if (!baseClassNameList.Contains(classname)) { baseClassNameList.Add(classname); baseMethodLists.Add(new List <LayerdMethodDefinition>()); constructorLists.Add(new List <ConstructorDefinition>()); int id = baseClassNameList.IndexOf(classname); if (lcd.SuperClasses.Count >= 1) { string superclassFullname = lcd.SuperClasses[0].ClassName; if (nspace != "") { superclassFullname = nspace + "::" + superclassFullname; } string[] superclassNspaces = superclassFullname.Split(new string[] { "::" }, StringSplitOptions.None); string sname = superclassFullname; int superId = -1; for (int i = 0; i < superclassNspaces.Length; ++i) { int id2 = baseClassNameList.IndexOf(sname); if (id2 != -1) { baseMethodLists[id].AddRange(baseMethodLists[id2]); superId = id2; break; } sname = sname.Remove(0, (superclassNspaces[i].Length + 2)); } superClassIDs.Add(superId); } else { superClassIDs.Add(-1); } createBaseClassAndMethodList(lcd.Contents, classname, id); // デストラクタ無ければ追加 var baseMethodList = baseMethodLists[id]; if (!baseMethodList.Exists((obj) => obj == null)) { baseMethodList.Add(null); } } else { throw new Exception("クラス" + classname + "の定義が重複しています"); } } else if (item is ConstructorDefinition) { var cd = (ConstructorDefinition)item; var list = constructorLists[classId]; list.Add(cd); } else if (item is DestructorDefinition) { var dd = (DestructorDefinition)item; if (dd.IsVirtual || dd.IsPureVirtual) { var methodList = baseMethodLists[classId]; if (!methodList.Exists((obj) => obj == null)) { methodList.Add(null); } } } else if (item is LayerdMethodDefinition) { if (classId == -1) { continue; } var lmd = (LayerdMethodDefinition)item; if (((lmd.IsBase != null) && lmd.IsBase.Value) || lmd.IsVirtual || lmd.IsPureVirtual) { var methodList = baseMethodLists[classId]; if (!methodList.Exists((obj) => (obj != null) && (obj.CompareMethod(lmd)))) { methodList.Add(lmd); } } } } }; createBaseClassAndMethodList(baselayerStructure.HeaderFileItems, "", -1); createBaseClassAndMethodList(baselayerStructure.SourceFileItems, "", -1); createBaseClassAndMethodList(mergedLSFile.BaseClassHeaderItems, "", -1); // レイヤ、クラス、メソッドの数を調べる int numOfLayers = mergedLSFile.LayerStructures.Count + 1; int numOfClasses = baseClassNameList.Count; int[] numOfMethods = new int[numOfClasses]; for (int i = 0; i < numOfClasses; ++i) { numOfMethods[i] = baseMethodLists[i].Count; } //======================================= // ↓これらは別ファイルで定義 //======================================= // RTCOPAppInitializerの生成 GenerateRTCOPAppInitializer(result, numOfLayers, numOfClasses, numOfMethods, mergedLSFile.LayerStructures, includeFilePath); // API.h、COPNewForApp.h、ActivationForApp.hの生成 GenerateAPIHeaders(result, mergedLSFile.LayerStructures, baseClassNameList, includeFilePath); // ベースレイヤの生成 GenerateBaseLayer(result, baselayerStructure, mergedLSFile.LayerStructures, baseClassNameList, baseMethodLists, superClassIDs, includeFilePath); // 各レイヤの生成 GenerateLayers(result, baselayerStructure, mergedLSFile.LayerStructures, baseClassNameList, baseMethodLists, constructorLists, superClassIDs, includeFilePath); // 環境依存コードの生成 GenerateDependentCode(result, baselayerStructure, mergedLSFile.LayerStructures, baseClassNameList, baseMethodLists, includeFilePath); // 結果を返す return(result); }
/// <summary> /// コンパイル /// </summary> /// <param name="sourceFile">ソースファイル</param> /// <returns>レイヤ構造ファイル</returns> public LayerStructureFile Compile(RTCOPSourceFile sourceFile) { // 結果を格納するためのレイヤ構造ファイル LayerStructureFile result = new LayerStructureFile(); // パーサに通す string sourceCode = sourceFile.Text; var items = RTCOPParser.RTCOPSourceFile.Parse(sourceCode); // 各レイヤ共通のアイテム List <object> commonItemsS = new List <object>(); List <object> commonItemsH = new List <object>(); // 要素の解釈 foreach (object item in items) { // レイヤ定義の場合 if (item is LayerDefinition) { var layerDefinition = (LayerDefinition)item; if (layerDefinition.Name == "baselayer") { if (result.BaseLayerStructure == null) { result.BaseLayerStructure = new LayerStructure("baselayer"); } result.BaseLayerStructure.SourceFileItems.Add(layerDefinition); } else { var layerStructure = result.LayerStructures.Find((obj) => obj.LayerName == layerDefinition.Name); if (layerStructure == null) { layerStructure = new LayerStructure(layerDefinition.Name); result.LayerStructures.Add(layerStructure); } layerStructure.SourceFileItems.Add(layerDefinition); } } // それ以外 else { commonItemsS.Add(item); } } // 各レイヤ共通のアイテムの反映 if (result.BaseLayerStructure != null) { result.BaseLayerStructure.SourceFileItems.InsertRange(0, commonItemsS); } foreach (var layerStructure in result.LayerStructures) { layerStructure.SourceFileItems.InsertRange(0, commonItemsS); } // ヘッダファイルの解釈 Action <RTCOPSourceFile> InterpretImportedFiles = null; InterpretImportedFiles = (src) => { foreach (RTCOPSourceFile impFile in src.ImportedFiles) { // .lh内でさらに読み込まれているファイルをチェック InterpretImportedFiles(impFile); // パーサに通す string impFileCode = impFile.Text; var impFileItems = RTCOPParser.RTCOPSourceFile.Parse(impFileCode); // ファイルの種類によって処理方法を変える if (Path.GetExtension(impFile.FilePath) == ".lh") { List <string> layerNames = new List <string>(); // 要素の解釈 foreach (object item in impFileItems) { // レイヤ定義の場合 if (item is LayerDefinition) { var layerDefinition = (LayerDefinition)item; layerNames.Add(layerDefinition.Name); // ヘッダ要素の追加 if (layerDefinition.Name == "baselayer") { // ベースレイヤ if (result.BaseLayerStructure == null) { result.BaseLayerStructure = new LayerStructure("baselayer"); } ImportedFileInfomation ifi = result.BaseLayerStructure.ImportedLhInfomation.Find((obj) => obj.FilePath == impFile.FilePath); if (ifi == null) { ifi = new ImportedFileInfomation(impFile.FilePath); ifi.StartIndex = result.BaseLayerStructure.HeaderFileItems.Count; ifi.NumOfItems = 0; result.BaseLayerStructure.ImportedLhInfomation.Add(ifi); } ++ifi.NumOfItems; result.BaseLayerStructure.HeaderFileItems.Add(layerDefinition); } else { // ベースレイヤ以外 var layerStructure = result.LayerStructures.Find((obj) => obj.LayerName == layerDefinition.Name); if (layerStructure == null) { layerStructure = new LayerStructure(layerDefinition.Name); result.LayerStructures.Add(layerStructure); } ImportedFileInfomation ifi = layerStructure.ImportedLhInfomation.Find((obj) => obj.FilePath == impFile.FilePath); if (ifi == null) { ifi = new ImportedFileInfomation(impFile.FilePath); ifi.StartIndex = layerStructure.HeaderFileItems.Count; ifi.NumOfItems = 0; layerStructure.ImportedLhInfomation.Add(ifi); } ++ifi.NumOfItems; layerStructure.HeaderFileItems.Add(layerDefinition); } } // それ以外 else { commonItemsH.Add(item); } } // 各レイヤ共通のアイテムの反映 if (layerNames.Contains("baselayer")) { ImportedFileInfomation ifi = result.BaseLayerStructure.ImportedLhInfomation.Find((obj) => obj.FilePath == impFile.FilePath); ifi.NumOfItems += commonItemsH.Count; result.BaseLayerStructure.HeaderFileItems.InsertRange(ifi.StartIndex, commonItemsH); } foreach (var layerStructure in result.LayerStructures) { if (layerNames.Contains(layerStructure.LayerName)) { ImportedFileInfomation ifi = layerStructure.ImportedLhInfomation.Find((obj) => obj.FilePath == impFile.FilePath); ifi.NumOfItems += commonItemsH.Count; layerStructure.HeaderFileItems.InsertRange(ifi.StartIndex, commonItemsH); } } } // .lhファイル以外 else { ImportedFileInfomation ifi = new ImportedFileInfomation(impFile.FilePath); ifi.StartIndex = result.BaseClassHeaderItems.Count; ifi.NumOfItems = impFileItems.Count(); result.ImportedBaseClassHeaderInfomation.Add(ifi); result.BaseClassHeaderItems.AddRange(impFileItems); } } }; InterpretImportedFiles(sourceFile); // 結果を返す return(result); }
/// <summary> /// レイヤ構造ファイルのマージ /// </summary> /// <param name="structureFiles">マージしたいレイヤ構造ファイル</param> /// <returns>マージされたレイヤ構造ファイル</returns> public LayerStructureFile MergeObjectFiles(IEnumerable <LayerStructureFile> structureFiles) { // 結果を格納するためのオブジェクトファイル LayerStructureFile result = new LayerStructureFile(); // マージ foreach (var structureFile in structureFiles) { // ベースクラスヘッダを重複を防いでマージ foreach (var ifi in structureFile.ImportedBaseClassHeaderInfomation) { var ifi2 = result.ImportedBaseClassHeaderInfomation.Find((obj) => obj.FilePath == ifi.FilePath); if (ifi2 == null) { ifi2 = new ImportedFileInfomation(ifi.FilePath); ifi2.StartIndex = result.BaseClassHeaderItems.Count; ifi2.NumOfItems = ifi.NumOfItems; result.ImportedBaseClassHeaderInfomation.Add(ifi2); var range = structureFile.BaseClassHeaderItems.GetRange(ifi.StartIndex, ifi.NumOfItems); result.BaseClassHeaderItems.AddRange(range); } } // ベースレイヤ if (structureFile.BaseLayerStructure != null) { if (result.BaseLayerStructure == null) { result.BaseLayerStructure = new LayerStructure("baselayer"); } result.BaseLayerStructure.SourceFileItems.AddRange(structureFile.BaseLayerStructure.SourceFileItems); // ヘッダ重複を防いでマージ foreach (var ifi in structureFile.BaseLayerStructure.ImportedLhInfomation) { var ifi2 = result.BaseLayerStructure.ImportedLhInfomation.Find((obj) => obj.FilePath == ifi.FilePath); if (ifi2 == null) { ifi2 = new ImportedFileInfomation(ifi.FilePath); ifi2.StartIndex = result.BaseLayerStructure.HeaderFileItems.Count; ifi2.NumOfItems = ifi.NumOfItems; result.BaseLayerStructure.ImportedLhInfomation.Add(ifi2); var range = structureFile.BaseLayerStructure.HeaderFileItems.GetRange(ifi.StartIndex, ifi.NumOfItems); result.BaseLayerStructure.HeaderFileItems.AddRange(range); } } } // ベースレイヤ以外 foreach (var layerStructure in structureFile.LayerStructures) { var rld = result.LayerStructures.Find((obj) => obj.LayerName == layerStructure.LayerName); if (rld == null) { rld = new LayerStructure(layerStructure.LayerName); result.LayerStructures.Add(rld); } rld.SourceFileItems.AddRange(layerStructure.SourceFileItems); // ヘッダ重複を防いでマージ foreach (var ifi in layerStructure.ImportedLhInfomation) { var ifi2 = rld.ImportedLhInfomation.Find((obj) => obj.FilePath == ifi.FilePath); if (ifi2 == null) { ifi2 = new ImportedFileInfomation(ifi.FilePath); ifi2.StartIndex = rld.HeaderFileItems.Count; ifi2.NumOfItems = ifi.NumOfItems; rld.ImportedLhInfomation.Add(ifi2); var range = layerStructure.HeaderFileItems.GetRange(ifi.StartIndex, ifi.NumOfItems); rld.HeaderFileItems.AddRange(range); } } } } // レイヤコンフィグの反映 //result = ReflectConfigFile(result); // 結果を返す return(result); }