HeaderFileLoader.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. using System.Collections.Generic;
  2. using NTERA.Core;
  3. using NTERA.EmuEra.Game.EraEmu.GameData;
  4. using NTERA.EmuEra.Game.EraEmu.GameData.Variable;
  5. using NTERA.EmuEra.Game.EraEmu.Sub;
  6. namespace NTERA.EmuEra.Game.EraEmu.GameProc
  7. {
  8. internal sealed class HeaderFileLoader
  9. {
  10. public HeaderFileLoader(IConsole main, IdentifierDictionary idDic, Process proc)
  11. {
  12. output = main;
  13. parentProcess = proc;
  14. this.idDic = idDic;
  15. }
  16. readonly Process parentProcess;
  17. readonly IConsole output;
  18. readonly IdentifierDictionary idDic;
  19. bool noError = true;
  20. /// <summary>
  21. ///
  22. /// </summary>
  23. /// <param name="erbDir"></param>
  24. /// <param name="displayReport"></param>
  25. /// <returns></returns>
  26. public bool LoadHeaderFiles(string headerDir, bool displayReport)
  27. {
  28. List<KeyValuePair<string, string>> headerFiles = Config.Config.GetFiles(headerDir, "*.ERH");
  29. bool noError = true;
  30. try
  31. {
  32. for (int i = 0; i < headerFiles.Count; i++)
  33. {
  34. string filename = headerFiles[i].Key;
  35. string file = headerFiles[i].Value;
  36. if (displayReport)
  37. output.PrintSystemLine("Loading " + filename + "...");
  38. noError = loadHeaderFile(file, filename);
  39. if (!noError)
  40. break;
  41. }
  42. }
  43. finally
  44. {
  45. ParserMediator.FlushWarningList();
  46. }
  47. return noError;
  48. }
  49. private bool loadHeaderFile(string filepath, string filename)
  50. {
  51. StringStream st = null;
  52. ScriptPosition position = null;
  53. //EraStreamReader eReader = new EraStreamReader(false);
  54. //1815修正 _rename.csvの適用
  55. //eramakerEXの仕様的には.ERHに適用するのはおかしいけど、もうEmueraの仕様になっちゃってるのでしかたないか
  56. EraStreamReader eReader = new EraStreamReader(true);
  57. if (!eReader.Open(filepath, filename))
  58. {
  59. throw new CodeEE(eReader.Filename + "のオープンに失敗しました");
  60. //return false;
  61. }
  62. try
  63. {
  64. while ((st = eReader.ReadEnabledLine()) != null)
  65. {
  66. if (!noError)
  67. return false;
  68. position = new ScriptPosition(filename, eReader.LineNo, st.RowString);
  69. LexicalAnalyzer.SkipWhiteSpace(st);
  70. if (st.Current != '#')
  71. throw new CodeEE("ヘッダーの中に#で始まらない行があります", position);
  72. st.ShiftNext();
  73. string sharpID = LexicalAnalyzer.ReadSingleIdentifier(st);
  74. if (sharpID == null)
  75. {
  76. ParserMediator.Warn("解釈できない#行です", position, 1);
  77. return false;
  78. }
  79. if (Config.Config.ICFunction)
  80. sharpID = sharpID.ToUpper();
  81. LexicalAnalyzer.SkipWhiteSpace(st);
  82. switch (sharpID)
  83. {
  84. case "DEFINE":
  85. analyzeSharpDefine(st, position);
  86. break;
  87. case "FUNCTION":
  88. case "FUNCTIONS":
  89. analyzeSharpFunction(st, position, sharpID == "FUNCTIONS");
  90. break;
  91. case "DIM":
  92. case "DIMS":
  93. analyzeSharpDim(st, position, sharpID == "DIMS");
  94. break;
  95. default:
  96. throw new CodeEE("#" + sharpID + "は解釈できないプリプロセッサです", position);
  97. }
  98. }
  99. }
  100. catch (CodeEE e)
  101. {
  102. if (e.Position != null)
  103. position = e.Position;
  104. ParserMediator.Warn(e.Message, position, 2);
  105. return false;
  106. }
  107. finally
  108. {
  109. eReader.Close();
  110. }
  111. return true;
  112. }
  113. //#define FOO (~~) id to wc
  114. //#define BAR($1) (~~) idwithargs to wc(replaced)
  115. //#diseble FOOBAR
  116. //#dim piyo, i
  117. //#dims puyo, j
  118. //static List<string> keywordsList = new List<string>();
  119. private void analyzeSharpDefine(StringStream st, ScriptPosition position)
  120. {
  121. //LexicalAnalyzer.SkipWhiteSpace(st);呼び出し前に行う。
  122. string srcID = LexicalAnalyzer.ReadSingleIdentifier(st);
  123. if (srcID == null)
  124. throw new CodeEE("置換元の識別子がありません", position);
  125. if (Config.Config.ICVariable)
  126. srcID = srcID.ToUpper();
  127. //ここで名称重複判定しないと、大変なことになる
  128. string errMes = "";
  129. int errLevel = -1;
  130. idDic.CheckUserMacroName(ref errMes, ref errLevel, srcID);
  131. if (errLevel >= 0)
  132. {
  133. ParserMediator.Warn(errMes, position, errLevel);
  134. if (errLevel >= 2)
  135. {
  136. noError = false;
  137. return;
  138. }
  139. }
  140. bool hasArg = st.Current == '(';//引数を指定する場合には直後に(が続いていなければならない。ホワイトスペースも禁止。
  141. //1808a3 代入演算子許可(関数宣言用)
  142. WordCollection wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment);
  143. if (wc.EOL)
  144. {
  145. //throw new CodeEE("置換先の式がありません", position);
  146. //1808a3 空マクロの許可
  147. DefineMacro nullmac = new DefineMacro(srcID, new WordCollection(), 0);
  148. idDic.AddMacro(nullmac);
  149. return;
  150. }
  151. List<string> argID = new List<string>();
  152. if (hasArg)//関数型マクロの引数解析
  153. {
  154. wc.ShiftNext();//'('を読み飛ばす
  155. if (wc.Current.Type == ')')
  156. throw new CodeEE("関数型マクロの引数を0個にすることはできません", position);
  157. while (!wc.EOL)
  158. {
  159. IdentifierWord word = wc.Current as IdentifierWord;
  160. if (word == null)
  161. throw new CodeEE("置換元の引数指定の書式が間違っています", position);
  162. word.SetIsMacro();
  163. string id = word.Code;
  164. if (argID.Contains(id))
  165. throw new CodeEE("置換元の引数に同じ文字が2回以上使われています", position);
  166. argID.Add(id);
  167. wc.ShiftNext();
  168. if (wc.Current.Type == ',')
  169. {
  170. wc.ShiftNext();
  171. continue;
  172. }
  173. if (wc.Current.Type == ')')
  174. break;
  175. throw new CodeEE("置換元の引数指定の書式が間違っています", position);
  176. }
  177. if (wc.EOL)
  178. throw new CodeEE("')'が閉じられていません", position);
  179. wc.ShiftNext();
  180. }
  181. if (wc.EOL)
  182. throw new CodeEE("置換先の式がありません", position);
  183. WordCollection destWc = new WordCollection();
  184. while (!wc.EOL)
  185. {
  186. destWc.Add(wc.Current);
  187. wc.ShiftNext();
  188. }
  189. if (hasArg)//関数型マクロの引数セット
  190. {
  191. while (!destWc.EOL)
  192. {
  193. IdentifierWord word = destWc.Current as IdentifierWord;
  194. if (word == null)
  195. {
  196. destWc.ShiftNext();
  197. continue;
  198. }
  199. for (int i = 0; i < argID.Count; i++)
  200. {
  201. if (string.Equals(word.Code, argID[i], Config.Config.SCVariable))
  202. {
  203. destWc.Remove();
  204. destWc.Insert(new MacroWord(i));
  205. break;
  206. }
  207. }
  208. destWc.ShiftNext();
  209. }
  210. destWc.Pointer = 0;
  211. }
  212. if (hasArg)//1808a3 関数型マクロの封印
  213. throw new CodeEE("関数型マクロは宣言できません", position);
  214. DefineMacro mac = new DefineMacro(srcID, destWc, argID.Count);
  215. idDic.AddMacro(mac);
  216. }
  217. private void analyzeSharpDim(StringStream st, ScriptPosition position, bool dims)
  218. {
  219. WordCollection wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment);
  220. UserDefinedVariableData data = UserDefinedVariableData.Create(wc, dims, false, position);
  221. if (data.Reference)
  222. throw new NotImplCodeEE();
  223. VariableToken var = null;
  224. if (data.CharaData)
  225. var = parentProcess.VEvaluator.VariableData.CreateUserDefCharaVariable(data);
  226. else
  227. var = parentProcess.VEvaluator.VariableData.CreateUserDefVariable(data);
  228. idDic.AddUseDefinedVariable(var);
  229. }
  230. private void analyzeSharpFunction(StringStream st, ScriptPosition position, bool funcs)
  231. {
  232. throw new NotImplCodeEE();
  233. //WordCollection wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment);
  234. //UserDefinedFunctionData data = UserDefinedFunctionData.Create(wc, funcs, position);
  235. //idDic.AddRefMethod(UserDefinedRefMethod.Create(data));
  236. }
  237. }
  238. }