ErbLoader.cs 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Media;
  5. using Microsoft.VisualBasic;
  6. using NTERA.Core;
  7. using NTERA.EmuEra.Game.EraEmu.Config;
  8. using NTERA.EmuEra.Game.EraEmu.GameData;
  9. using NTERA.EmuEra.Game.EraEmu.GameData.Expression;
  10. using NTERA.EmuEra.Game.EraEmu.GameData.Variable;
  11. using NTERA.EmuEra.Game.EraEmu.GameProc.Function;
  12. using NTERA.EmuEra.Game.EraEmu.Sub;
  13. namespace NTERA.EmuEra.Game.EraEmu.GameProc
  14. {
  15. internal sealed class ErbLoader
  16. {
  17. public ErbLoader(IConsole main, ExpressionMediator exm, Process proc)
  18. {
  19. output = main;
  20. parentProcess = proc;
  21. this.exm = exm;
  22. }
  23. readonly Process parentProcess;
  24. readonly ExpressionMediator exm;
  25. readonly IConsole output;
  26. List<string> ignoredFNFWarningFileList = new List<string>();
  27. int ignoredFNFWarningCount;
  28. int enabledLineCount;
  29. LabelDictionary labelDic;
  30. bool noError = true;
  31. /// <summary>
  32. /// 複数のファイルを読む
  33. /// </summary>
  34. /// <param name="erbDir"></param>
  35. /// <param name="displayReport"></param>
  36. /// <param name="labelDictionary"></param>
  37. public bool LoadErbFiles(string erbDir, bool displayReport, LabelDictionary labelDictionary)
  38. {
  39. //1.713 labelDicをnewする位置を変更。
  40. //checkScript();の時点でExpressionPerserがProcess.instance.LabelDicを必要とするから。
  41. labelDic = labelDictionary;
  42. labelDic.Initialized = false;
  43. List<KeyValuePair<string, string>> erbFiles = Config.Config.GetFiles(erbDir, "*.ERB");
  44. List<string> isOnlyEvent = new List<string>();
  45. noError = true;
  46. Stopwatch stopwatch = new Stopwatch();
  47. stopwatch.Start();
  48. try
  49. {
  50. labelDic.RemoveAll();
  51. for (int i = 0; i < erbFiles.Count; i++)
  52. {
  53. string filename = erbFiles[i].Key;
  54. string file = erbFiles[i].Value;
  55. #if DEBUG
  56. if (displayReport)
  57. output.PrintSystemLine("Elapsed time: " + stopwatch.ElapsedMilliseconds.ToString("D4") + "ms:" + filename + " is being loaded...");
  58. #else
  59. if (displayReport)
  60. output.PrintSystemLine("Loading " + filename + "...");
  61. #endif
  62. loadErb(file, filename, isOnlyEvent);
  63. }
  64. ParserMediator.FlushWarningList();
  65. #if DEBUG
  66. output.PrintSystemLine("Elapsed time: " + stopwatch.ElapsedMilliseconds.ToString("D4") + "ms:");
  67. #endif
  68. if (displayReport)
  69. output.PrintSystemLine("Building a list of user-defined functions...");
  70. setLabelsArg();
  71. ParserMediator.FlushWarningList();
  72. labelDic.Initialized = true;
  73. #if DEBUG
  74. output.PrintSystemLine("Elapsed time: " + stopwatch.ElapsedMilliseconds.ToString("D4") + "ms:");
  75. #endif
  76. if (displayReport)
  77. output.PrintSystemLine("Script syntax checking...");
  78. checkScript();
  79. ParserMediator.FlushWarningList();
  80. #if DEBUG
  81. output.PrintSystemLine("Elapsed time: " + stopwatch.ElapsedMilliseconds.ToString("D4") + "ms:");
  82. #endif
  83. if (displayReport)
  84. output.PrintSystemLine("Load is complete");
  85. stopwatch.Stop();
  86. }
  87. catch (Exception e)
  88. {
  89. ParserMediator.FlushWarningList();
  90. SystemSounds.Hand.Play();
  91. output.PrintError("An unexpected error has occurred: " + Program.ExeName);
  92. output.PrintError(e.GetType() + ":" + e.Message);
  93. return false;
  94. }
  95. finally
  96. {
  97. parentProcess.scaningLine = null;
  98. }
  99. isOnlyEvent.Clear();
  100. return noError;
  101. }
  102. /// <summary>
  103. /// 指定されたファイルを読み込む
  104. /// </summary>
  105. /// <param name="filename"></param>
  106. public bool LoadErbs(List<string> path, LabelDictionary labelDictionary)
  107. {
  108. var isOnlyEvent = new List<string>();
  109. noError = true;
  110. labelDic = labelDictionary;
  111. labelDic.Initialized = false;
  112. foreach (string fpath in path)
  113. {
  114. string fname;
  115. if (fpath.StartsWith(Program.ErbDir, Config.Config.SCIgnoreCase) && !Program.AnalysisMode)
  116. fname = fpath.Substring(Program.ErbDir.Length);
  117. else
  118. fname = fpath;
  119. if (Program.AnalysisMode)
  120. output.PrintSystemLine("Loading " + fname + "...");
  121. loadErb(fpath, fname, isOnlyEvent);
  122. }
  123. if (Program.AnalysisMode)
  124. output.NewLine();
  125. ParserMediator.FlushWarningList();
  126. setLabelsArg();
  127. ParserMediator.FlushWarningList();
  128. labelDic.Initialized = true;
  129. checkScript();
  130. ParserMediator.FlushWarningList();
  131. parentProcess.scaningLine = null;
  132. isOnlyEvent.Clear();
  133. return noError;
  134. }
  135. private sealed class PPState
  136. {
  137. bool skip;
  138. bool done;
  139. public bool Disabled;
  140. readonly Stack<bool> disabledStack = new Stack<bool>();
  141. Stack<bool> doneStack = new Stack<bool>();
  142. Stack<string> ppMatch = new Stack<string>();
  143. internal void AddKeyWord(string token, string token2, ScriptPosition position)
  144. {
  145. bool token2enabled = string.IsNullOrEmpty(token2);
  146. switch (token)
  147. {
  148. case "SKIPSTART":
  149. if (!string.IsNullOrEmpty(token2))
  150. {
  151. ParserMediator.Warn("There\'s an extra argument in " + token, position, 1);
  152. break;
  153. }
  154. if (skip)
  155. {
  156. ParserMediator.Warn("[SKIPSTART] is being used twice or overlapping", position, 1);
  157. break;
  158. }
  159. ppMatch.Push("SKIPEND");
  160. disabledStack.Push(Disabled);
  161. doneStack.Push(done);
  162. skip = true;
  163. Disabled = true;
  164. done = false;
  165. break;
  166. case "IF_DEBUG":
  167. if (!string.IsNullOrEmpty(token2))
  168. {
  169. ParserMediator.Warn("There\'s an extra argument in " + token, position, 1);
  170. break;
  171. }
  172. ppMatch.Push("ELSEIF");
  173. disabledStack.Push(Disabled);
  174. doneStack.Push(done);
  175. Disabled = !Program.DebugMode;
  176. done = !Disabled;
  177. break;
  178. case "IF_NDEBUG":
  179. if (!string.IsNullOrEmpty(token2))
  180. {
  181. ParserMediator.Warn("There\'s an extra argument in " + token, position, 1);
  182. break;
  183. }
  184. ppMatch.Push("ELSEIF");
  185. disabledStack.Push(Disabled);
  186. doneStack.Push(done);
  187. Disabled = Program.DebugMode;
  188. done = !Disabled;
  189. break;
  190. case "IF":
  191. if (string.IsNullOrEmpty(token2))
  192. {
  193. ParserMediator.Warn("Argument is missing in " + token, position, 1);
  194. break;
  195. }
  196. ppMatch.Push("ELSEIF");
  197. disabledStack.Push(Disabled);
  198. doneStack.Push(done);
  199. Disabled = GlobalStatic.IdentifierDictionary.GetMacro(token2) == null;
  200. done = !Disabled;
  201. break;
  202. case "ELSEIF":
  203. if (string.IsNullOrEmpty(token2))
  204. {
  205. ParserMediator.Warn("Argument is missing in " + token, position, 1);
  206. break;
  207. }
  208. if (ppMatch.Count == 0 || ppMatch.Pop() != "ELSEIF")
  209. {
  210. ParserMediator.Warn("Inappropriate [ELSEIF] detected", position, 1);
  211. break;
  212. }
  213. ppMatch.Push("ELSEIF");
  214. Disabled = done || (GlobalStatic.IdentifierDictionary.GetMacro(token2) == null);
  215. done |= !Disabled;
  216. break;
  217. case "ELSE":
  218. if (!string.IsNullOrEmpty(token2))
  219. {
  220. ParserMediator.Warn("There\'s an extra argument in " + token, position, 1);
  221. break;
  222. }
  223. if (ppMatch.Count == 0 || ppMatch.Pop() != "ELSEIF")
  224. {
  225. ParserMediator.Warn("Inappropriate [ELSE] detected", position, 1);
  226. break;
  227. }
  228. ppMatch.Push("ENDIF");
  229. Disabled = done;
  230. done = true;
  231. break;
  232. case "SKIPEND":
  233. {
  234. if (!string.IsNullOrEmpty(token2))
  235. {
  236. ParserMediator.Warn("There\'s an extra argument in " + token, position, 1);
  237. break;
  238. }
  239. string match = ppMatch.Count == 0 ? "" : ppMatch.Pop();
  240. if (match != "SKIPEND")
  241. {
  242. ParserMediator.Warn("[SKIPSTART] should be closed with [SKIPEND]", position, 1);
  243. break;
  244. }
  245. skip = false;
  246. Disabled = disabledStack.Pop();
  247. done = doneStack.Pop();
  248. }
  249. break;
  250. case "ENDIF":
  251. {
  252. if (!string.IsNullOrEmpty(token2))
  253. {
  254. ParserMediator.Warn("There\'s an extra argument in " + token, position, 1);
  255. break;
  256. }
  257. string match = ppMatch.Count == 0 ? "" : ppMatch.Pop();
  258. if (match != "ENDIF" && match != "ELSEIF")
  259. {
  260. ParserMediator.Warn("[IF] doesn\'t have a corresponding [ENDIF]", position, 1);
  261. break;
  262. }
  263. Disabled = disabledStack.Pop();
  264. done = doneStack.Pop();
  265. }
  266. break;
  267. default:
  268. ParserMediator.Warn("An unrecognized preprocessor", position, 1);
  269. break;
  270. }
  271. if (skip)
  272. Disabled = true;
  273. }
  274. internal void FileEnd(ScriptPosition position)
  275. {
  276. if (ppMatch.Count != 0)
  277. {
  278. string match = ppMatch.Pop();
  279. if (match == "ELSEIF")
  280. match = "ENDIF";
  281. ParserMediator.Warn("[" + match + "]がありません", position, 1);
  282. }
  283. }
  284. }
  285. /// <summary>
  286. /// ファイル一つを読む
  287. /// </summary>
  288. /// <param name="filepath"></param>
  289. private void loadErb(string filepath, string filename, List<string> isOnlyEvent)
  290. {
  291. //読み込んだファイルのパスを記録
  292. //一部ファイルの再読み込み時の処理用
  293. labelDic.AddFilename(filename);
  294. EraStreamReader eReader = new EraStreamReader(Config.Config.UseRenameFile && ParserMediator.RenameDic != null);
  295. if (!eReader.Open(filepath, filename))
  296. {
  297. output.PrintError("Failed to open " + eReader.Filename);
  298. return;
  299. }
  300. try
  301. {
  302. PPState ppstate = new PPState();
  303. LogicalLine nextLine = new NullLine();
  304. LogicalLine lastLine = new NullLine();
  305. FunctionLabelLine lastLabelLine = null;
  306. StringStream st = null;
  307. string rowLine = null;
  308. ScriptPosition position = null;
  309. int funcCount = 0;
  310. if (Program.AnalysisMode)
  311. output.PrintSystemLine(" ");
  312. while ((st = eReader.ReadEnabledLine()) != null)
  313. {
  314. rowLine = st.RowString;
  315. position = new ScriptPosition(eReader.Filename, eReader.LineNo, rowLine);
  316. //rename処理をEraStreamReaderに移管
  317. //変換できなかった[[~~]]についてはLexAnalyzerがエラーを投げる
  318. if (st.Current == '[' && st.Next != '[')
  319. {
  320. st.ShiftNext();
  321. string token = LexicalAnalyzer.ReadSingleIdentifier(st);
  322. LexicalAnalyzer.SkipWhiteSpace(st);
  323. string token2 = LexicalAnalyzer.ReadSingleIdentifier(st);
  324. if ((string.IsNullOrEmpty(token)) || (st.Current != ']'))
  325. ParserMediator.Warn("Illegal use of []", position, 1);
  326. ppstate.AddKeyWord(token, token2, position);
  327. st.ShiftNext();
  328. if (!st.EOS)
  329. ParserMediator.Warn("[" + token + "]の後ろは無視されます。", position, 1);
  330. continue;
  331. }
  332. //if ((skip) || (Program.DebugMode && ifndebug) || (!Program.DebugMode && ifdebug))
  333. // continue;
  334. if (ppstate.Disabled)
  335. continue;
  336. //ここまでプリプロセッサ
  337. if (st.Current == '#')
  338. {
  339. if ((lastLine == null) || !(lastLine is FunctionLabelLine))
  340. {
  341. ParserMediator.Warn("関数宣言の直後以外で#行が使われています", position, 1);
  342. continue;
  343. }
  344. if (!LogicalLineParser.ParseSharpLine((FunctionLabelLine)lastLine, st, position, isOnlyEvent))
  345. noError = false;
  346. continue;
  347. }
  348. if ((st.Current == '$') || (st.Current == '@'))
  349. {
  350. bool isFunction = (st.Current == '@');
  351. nextLine = LogicalLineParser.ParseLabelLine(st, position, output);
  352. if (isFunction)
  353. {
  354. FunctionLabelLine label = (FunctionLabelLine)nextLine;
  355. lastLabelLine = label;
  356. if (label is InvalidLabelLine)
  357. {
  358. noError = false;
  359. ParserMediator.Warn(nextLine.ErrMes, position, 2);
  360. labelDic.AddInvalidLabel(label);
  361. }
  362. else// if (label is FunctionLabelLine)
  363. {
  364. labelDic.AddLabel(label);
  365. if (!label.IsEvent && (Config.Config.WarnNormalFunctionOverloading || Program.AnalysisMode))
  366. {
  367. FunctionLabelLine seniorLabel = labelDic.GetSameNameLabel(label);
  368. if (seniorLabel != null)
  369. {
  370. //output.NewLine();
  371. ParserMediator.Warn("関数@" + label.LabelName + "は既に定義(" + seniorLabel.Position.Filename + "の" + seniorLabel.Position.LineNo + "行目)されています", position, 1);
  372. funcCount = -1;
  373. }
  374. }
  375. funcCount++;
  376. if (Program.AnalysisMode && (Config.Config.PrintCPerLine > 0 && (funcCount % Config.Config.PrintCPerLine) == 0))
  377. {
  378. output.NewLine();
  379. output.PrintSystemLine(" ");
  380. }
  381. }
  382. }
  383. else
  384. {
  385. if (nextLine is GotoLabelLine)
  386. {
  387. GotoLabelLine gotoLabel = (GotoLabelLine)nextLine;
  388. gotoLabel.ParentLabelLine = lastLabelLine;
  389. if (lastLabelLine != null && !labelDic.AddLabelDollar(gotoLabel))
  390. {
  391. ScriptPosition pos = labelDic.GetLabelDollar(gotoLabel.LabelName, lastLabelLine).Position;
  392. ParserMediator.Warn("ラベル名$" + gotoLabel.LabelName + "は既に同じ関数内(" + pos.Filename + "の" + pos.LineNo + "行目)で使用されています", position, 2);
  393. }
  394. }
  395. }
  396. if (nextLine is InvalidLine)
  397. {
  398. noError = false;
  399. ParserMediator.Warn(nextLine.ErrMes, position, 2);
  400. }
  401. }
  402. else
  403. {
  404. //1808alpha006 処理位置変更
  405. ////全置換はここで対応
  406. ////1756beta1+++ 最初に全置換してしまうと関数定義を_Renameでとか論外なことができてしまうので永久封印した
  407. //if (ParserMediator.RenameDic != null && st.CurrentEqualTo("[[") && (rowLine.TrimEnd().IndexOf("]]") == rowLine.TrimEnd().Length - 2))
  408. //{
  409. // string replacedLine = st.Substring();
  410. // foreach (KeyValuePair<string, string> pair in ParserMediator.RenameDic)
  411. // replacedLine = replacedLine.Replace(pair.Key, pair.Value);
  412. // st = new StringStream(replacedLine);
  413. //}
  414. nextLine = LogicalLineParser.ParseLine(st, position, output);
  415. if (nextLine == null)
  416. continue;
  417. if (nextLine is InvalidLine)
  418. {
  419. noError = false;
  420. ParserMediator.Warn(nextLine.ErrMes, position, 2);
  421. }
  422. }
  423. if (lastLabelLine == null)
  424. ParserMediator.Warn("関数が定義されるより前に行があります", position, 1);
  425. nextLine.ParentLabelLine = lastLabelLine;
  426. lastLine = addLine(nextLine, lastLine);
  427. }
  428. addLine(new NullLine(), lastLine);
  429. position = new ScriptPosition(eReader.Filename, -1, null);
  430. ppstate.FileEnd(position);
  431. }
  432. finally
  433. {
  434. eReader.Close();
  435. }
  436. }
  437. private LogicalLine addLine(LogicalLine nextLine, LogicalLine lastLine)
  438. {
  439. if (nextLine == null)
  440. return null;
  441. enabledLineCount++;
  442. lastLine.NextLine = nextLine;
  443. return nextLine;
  444. }
  445. private void setLabelsArg()
  446. {
  447. List<FunctionLabelLine> labelList = labelDic.GetAllLabels(false);
  448. foreach (FunctionLabelLine label in labelList)
  449. {
  450. try
  451. {
  452. if (label.Arg != null)
  453. continue;
  454. parentProcess.scaningLine = label;
  455. parseLabel(label);
  456. }
  457. catch (Exception exc)
  458. {
  459. SystemSounds.Hand.Play();
  460. string errmes = exc.Message;
  461. if (!(exc is EmueraException))
  462. errmes = exc.GetType() + ":" + errmes;
  463. ParserMediator.Warn("関数@" + label.LabelName + " の引数のエラー:" + errmes, label, 2, true, false);
  464. label.ErrMes = "ロード時に解析に失敗した関数が呼び出されました";
  465. label.IsError = true;
  466. }
  467. finally
  468. {
  469. parentProcess.scaningLine = null;
  470. }
  471. }
  472. labelDic.SortLabels();
  473. }
  474. private void parseLabel(FunctionLabelLine label)
  475. {
  476. WordCollection wc = label.PopRowArgs();
  477. string errMes = null;
  478. SingleTerm[] subNames = new SingleTerm[0];
  479. VariableTerm[] args = new VariableTerm[0];
  480. SingleTerm[] defs = new SingleTerm[0];
  481. int maxArg = -1;
  482. int maxArgs = -1;
  483. //1807 非イベント関数のシステム関数については警告レベル低下&エラー解除&引数を設定するように。
  484. if (label.IsEvent)
  485. {
  486. if (!wc.EOL)
  487. ParserMediator.Warn("イベント関数@" + label.LabelName + " に引数は設定できません", label, 2, true, false);
  488. //label.SubNames = subNames;
  489. label.Arg = args;
  490. label.Def = defs;
  491. label.ArgLength = -1;
  492. label.ArgsLength = -1;
  493. return;
  494. }
  495. if (!wc.EOL)
  496. {
  497. if (label.IsSystem)
  498. ParserMediator.Warn("システム関数@" + label.LabelName + " に引数が設定されています", label, 1, false, false);
  499. SymbolWord symbol = wc.Current as SymbolWord;
  500. wc.ShiftNext();
  501. if (symbol == null)
  502. { errMes = "引数の書式が間違っています"; goto err; }
  503. if (symbol.Type == '[')//TODO:subNames 結局実装しないかも
  504. {
  505. IOperandTerm[] subNamesRow = ExpressionParser.ReduceArguments(wc, ArgsEndWith.RightBracket, false);
  506. if (subNamesRow.Length == 0)
  507. { errMes = "関数定義の[]内の引数は空にできません"; goto err; }
  508. subNames = new SingleTerm[subNamesRow.Length];
  509. for (int i = 0; i < subNamesRow.Length; i++)
  510. {
  511. if (subNamesRow[i] == null)
  512. { errMes = "関数定義の引数は省略できません"; goto err; }
  513. IOperandTerm term = subNamesRow[i].Restructure(exm);
  514. subNames[i] = term as SingleTerm;
  515. if (subNames[i] == null)
  516. { errMes = "関数定義の[]内の引数は定数のみ指定できます"; goto err; }
  517. }
  518. symbol = wc.Current as SymbolWord;
  519. if ((!wc.EOL) && (symbol == null))
  520. { errMes = "引数の書式が間違っています"; goto err; }
  521. wc.ShiftNext();
  522. }
  523. if (!wc.EOL)
  524. {
  525. IOperandTerm[] argsRow = null;
  526. if (symbol.Type == ',')
  527. argsRow = ExpressionParser.ReduceArguments(wc, ArgsEndWith.EoL, true);
  528. else if (symbol.Type == '(')
  529. argsRow = ExpressionParser.ReduceArguments(wc, ArgsEndWith.RightParenthesis, true);
  530. else
  531. { errMes = "引数の書式が間違っています"; goto err; }
  532. int length = argsRow.Length / 2;
  533. args = new VariableTerm[length];
  534. defs = new SingleTerm[length];
  535. for (int i = 0; i < length; i++)
  536. {
  537. VariableTerm vTerm = null;
  538. SingleTerm def = null;
  539. IOperandTerm term = argsRow[i * 2];
  540. //引数読み取り時点で判別されないといけない
  541. //if (term == null)
  542. //{ errMes = "関数定義の引数は省略できません"; goto err; }
  543. vTerm = term.Restructure(exm) as VariableTerm;
  544. if ((vTerm == null) || (vTerm.Identifier.IsConst))
  545. { errMes = "関数定義の引数には代入可能な変数を指定してください"; goto err; }
  546. if (!vTerm.Identifier.IsReference)//参照型なら添え字不要
  547. {
  548. if (vTerm is VariableNoArgTerm)
  549. { errMes = "関数定義の参照型でない引数\"" + vTerm.Identifier.Name + "\"に添え字が指定されていません"; goto err; }
  550. if (!vTerm.isAllConst)
  551. { errMes = "関数定義の引数の添え字には定数を指定してください"; goto err; }
  552. }
  553. for (int j = 0; j < i; j++)
  554. {
  555. if (vTerm.checkSameTerm(args[j]))
  556. ParserMediator.Warn("第" + Strings.StrConv((i + 1).ToString(), VbStrConv.Wide, Config.Config.Language) + "引数\"" + vTerm.GetFullString() + "\"はすでに第" + Strings.StrConv((j + 1).ToString(), VbStrConv.Wide, Config.Config.Language) + "引数として宣言されています", label, 1, false, false);
  557. }
  558. if (vTerm.Identifier.Code == VariableCode.ARG)
  559. {
  560. if (maxArg < vTerm.getEl1forArg + 1)
  561. maxArg = vTerm.getEl1forArg + 1;
  562. }
  563. else if (vTerm.Identifier.Code == VariableCode.ARGS)
  564. {
  565. if (maxArgs < vTerm.getEl1forArg + 1)
  566. maxArgs = vTerm.getEl1forArg + 1;
  567. }
  568. bool canDef = (vTerm.Identifier.Code == VariableCode.ARG || vTerm.Identifier.Code == VariableCode.ARGS || vTerm.Identifier.IsPrivate);
  569. term = argsRow[i * 2 + 1];
  570. if (term is NullTerm)
  571. {
  572. if (canDef)// && label.ArgOptional)
  573. {
  574. if (vTerm.GetOperandType() == typeof(Int64))
  575. def = new SingleTerm(0);
  576. else
  577. def = new SingleTerm("");
  578. }
  579. }
  580. else
  581. {
  582. def = term.Restructure(exm) as SingleTerm;
  583. if (def == null)
  584. { errMes = "引数の初期値には定数のみを指定できます"; goto err; }
  585. if (!canDef)
  586. { errMes = "引数の初期値を定義できるのは\"ARG\"、\"ARGS\"またはプライベート変数のみです"; goto err; }
  587. if (vTerm.Identifier.IsReference)
  588. { errMes = "参照渡しの引数に初期値は定義できません"; goto err; }
  589. if (vTerm.GetOperandType() != def.GetOperandType())
  590. { errMes = "引数の型と初期値の型が一致していません"; goto err; }
  591. }
  592. args[i] = vTerm;
  593. defs[i] = def;
  594. }
  595. }
  596. }
  597. if (!wc.EOL)
  598. { errMes = "引数の書式が間違っています"; goto err; }
  599. //label.SubNames = subNames;
  600. label.Arg = args;
  601. label.Def = defs;
  602. label.ArgLength = maxArg;
  603. label.ArgsLength = maxArgs;
  604. return;
  605. err:
  606. ParserMediator.Warn("関数@" + label.LabelName + " の引数のエラー:" + errMes, label, 2, true, false);
  607. }
  608. public bool useCallForm;
  609. /// <summary>
  610. /// 読込終わったファイルをチェックする
  611. /// </summary>
  612. private void checkScript()
  613. {
  614. int usedLabelCount = 0;
  615. int labelDepth = -1;
  616. List<FunctionLabelLine> labelList = labelDic.GetAllLabels(true);
  617. while (true)
  618. {
  619. labelDepth++;
  620. int countInDepth = 0;
  621. foreach (FunctionLabelLine label in labelList)
  622. {
  623. if (label.Depth != labelDepth)
  624. continue;
  625. //1756beta003 なんで追加したんだろう デバグ中になんかやったのか とりあえずコメントアウトしておく
  626. //if (label.LabelName == "EVENTTURNEND")
  627. // useCallForm = true;
  628. usedLabelCount++;
  629. countInDepth++;
  630. checkFunctionWithCatch(label);
  631. }
  632. if (countInDepth == 0)
  633. break;
  634. }
  635. labelDepth = -1;
  636. List<string> ignoredFNCWarningFileList = new List<string>();
  637. int ignoredFNCWarningCount = 0;
  638. bool ignoreAll = false;
  639. DisplayWarningFlag notCalledWarning = Config.Config.FunctionNotCalledWarning;
  640. switch (notCalledWarning)
  641. {
  642. case DisplayWarningFlag.IGNORE:
  643. case DisplayWarningFlag.LATER:
  644. ignoreAll = true;
  645. break;
  646. }
  647. if (useCallForm)
  648. {//callform系が使われたら全ての関数が呼び出されたとみなす。
  649. if (Program.AnalysisMode)
  650. output.PrintSystemLine("CALLFORM系命令が使われたため、呼び出されない関数のチェックは行われません。");
  651. foreach (FunctionLabelLine label in labelList)
  652. {
  653. if (label.Depth != labelDepth)
  654. continue;
  655. checkFunctionWithCatch(label);
  656. }
  657. }
  658. else
  659. {
  660. bool ignoreUncalledFunction = Config.Config.IgnoreUncalledFunction;
  661. foreach (FunctionLabelLine label in labelList)
  662. {
  663. if (label.Depth != labelDepth)
  664. continue;
  665. //解析モード時は呼ばれなかったものをここで解析
  666. if (Program.AnalysisMode)
  667. checkFunctionWithCatch(label);
  668. bool ignore = false;
  669. if (notCalledWarning == DisplayWarningFlag.ONCE)
  670. {
  671. string filename = label.Position.Filename.ToUpper();
  672. if (!string.IsNullOrEmpty(filename))
  673. {
  674. if (ignoredFNCWarningFileList.Contains(filename))
  675. {
  676. ignore = true;
  677. }
  678. else
  679. {
  680. ignore = false;
  681. ignoredFNCWarningFileList.Add(filename);
  682. }
  683. }
  684. //break;
  685. }
  686. if (ignoreAll || ignore)
  687. ignoredFNCWarningCount++;
  688. else
  689. ParserMediator.Warn("関数@" + label.LabelName + "は定義されていますが一度も呼び出されません", label, 1, false, false);
  690. if (!ignoreUncalledFunction)
  691. checkFunctionWithCatch(label);
  692. else
  693. {
  694. if (!(label.NextLine is NullLine) && !(label.NextLine is FunctionLabelLine))
  695. {
  696. if (!label.NextLine.IsError)
  697. {
  698. label.NextLine.IsError = true;
  699. label.NextLine.ErrMes = "呼び出されないはずの関数が呼ばれた";
  700. }
  701. }
  702. }
  703. }
  704. }
  705. if (Program.AnalysisMode && (warningDic.Keys.Count > 0 || GlobalStatic.tempDic.Keys.Count > 0))
  706. {
  707. output.PrintError("・定義が見つからなかった関数: 他のファイルで定義されている場合はこの警告は無視できます");
  708. if (warningDic.Keys.Count > 0)
  709. {
  710. output.PrintError(" ○一般関数:");
  711. foreach (string labelName in warningDic.Keys)
  712. {
  713. output.PrintError("  " + labelName + ": " + warningDic[labelName] + "回");
  714. }
  715. }
  716. if (GlobalStatic.tempDic.Keys.Count > 0)
  717. {
  718. output.PrintError(" ○文中関数:");
  719. foreach (string labelName in GlobalStatic.tempDic.Keys)
  720. {
  721. output.PrintError("  " + labelName + ": " + GlobalStatic.tempDic[labelName] + "回");
  722. }
  723. }
  724. }
  725. else
  726. {
  727. if ((ignoredFNCWarningCount > 0) && (Config.Config.DisplayWarningLevel <= 1) && (notCalledWarning != DisplayWarningFlag.IGNORE))
  728. output.PrintError(string.Format("警告Lv1:定義された関数が一度も呼び出されていない事に関する警告を{0}件無視しました", ignoredFNCWarningCount));
  729. if ((ignoredFNFWarningCount > 0) && (Config.Config.DisplayWarningLevel <= 2) && (notCalledWarning != DisplayWarningFlag.IGNORE))
  730. output.PrintError(string.Format("警告Lv2:定義されていない関数を呼び出した事に関する警告を{0}件無視しました", ignoredFNFWarningCount));
  731. }
  732. ParserMediator.FlushWarningList();
  733. if (Config.Config.DisplayReport)
  734. output.PrintError(string.Format("Number of non-comment lines: {0}, All functions total: {1}, Total called functions: {2}", enabledLineCount, labelDic.Count, usedLabelCount));
  735. if (Config.Config.AllowFunctionOverloading && Config.Config.WarnFunctionOverloading)
  736. {
  737. List<string> overloadedList = GlobalStatic.IdentifierDictionary.GetOverloadedList(labelDic);
  738. if (overloadedList.Count > 0)
  739. {
  740. output.NewLine();
  741. output.PrintError("*****警告*****");
  742. foreach (string funcname in overloadedList)
  743. {
  744. output.PrintSystemLine(" システム関数\"" + funcname + "\"がユーザー定義関数によって上書きされています");
  745. }
  746. output.PrintSystemLine(" 上記の関数を利用するスクリプトは意図通りに動かない可能性があります");
  747. output.NewLine();
  748. output.PrintSystemLine(" ※この警告は該当する式中関数を利用しているEmuera専用スクリプト向けの警告です。");
  749. output.PrintSystemLine(" eramaker用のスクリプトの動作には影響しません。");
  750. output.PrintSystemLine(" 今後この警告が不要ならばコンフィグの「システム関数が上書きされたとき警告を表示する」をOFFにして下さい。");
  751. output.PrintSystemLine("************");
  752. }
  753. }
  754. }
  755. public Dictionary<string, Int64> warningDic = new Dictionary<string, Int64>();
  756. private void printFunctionNotFoundWarning(string str, LogicalLine line, int level, bool isError)
  757. {
  758. if (Program.AnalysisMode)
  759. {
  760. if (warningDic.ContainsKey(str))
  761. warningDic[str]++;
  762. else
  763. warningDic.Add(str, 1);
  764. return;
  765. }
  766. if (isError)
  767. {
  768. line.IsError = true;
  769. line.ErrMes = str;
  770. }
  771. if (level < Config.Config.DisplayWarningLevel)
  772. return;
  773. bool ignore = false;
  774. DisplayWarningFlag warnFlag = Config.Config.FunctionNotFoundWarning;
  775. if (warnFlag == DisplayWarningFlag.IGNORE)
  776. ignore = true;
  777. else if (warnFlag == DisplayWarningFlag.DISPLAY)
  778. ignore = false;
  779. else if (warnFlag == DisplayWarningFlag.ONCE)
  780. {
  781. string filename = line.Position.Filename.ToUpper();
  782. if (!string.IsNullOrEmpty(filename))
  783. {
  784. if (ignoredFNFWarningFileList.Contains(filename))
  785. {
  786. ignore = true;
  787. }
  788. else
  789. {
  790. ignore = false;
  791. ignoredFNFWarningFileList.Add(filename);
  792. }
  793. }
  794. }
  795. if (ignore && !Program.AnalysisMode)
  796. {
  797. ignoredFNFWarningCount++;
  798. return;
  799. }
  800. ParserMediator.Warn(str, line, level, isError, false);
  801. }
  802. private void checkFunctionWithCatch(FunctionLabelLine label)
  803. {//ここでエラーを捕まえることは本来はないはず。ExeEE相当。
  804. try
  805. {
  806. string filename = label.Position.Filename.ToUpper();
  807. setArgument(label);
  808. nestCheck(label);
  809. setJumpTo(label);
  810. }
  811. catch (Exception exc)
  812. {
  813. SystemSounds.Hand.Play();
  814. //1756beta2+v6.1 修正の効率化のために何かパース関係でハンドリングできてないエラーが出た場合はスタックトレースを投げるようにした
  815. string errmes = (exc is EmueraException) ? exc.Message : exc.GetType() + ":" + exc.Message;
  816. ParserMediator.Warn("@" + label.LabelName + " の解析中にエラー:" + errmes, label, 2, true, false, !(exc is EmueraException) ? exc.StackTrace : null);
  817. label.ErrMes = "ロード時に解析に失敗した関数が呼び出されました";
  818. }
  819. finally
  820. {
  821. parentProcess.scaningLine = null;
  822. }
  823. }
  824. private void setArgument(FunctionLabelLine label)
  825. {
  826. //1周目/3周
  827. //引数の解析とか
  828. LogicalLine nextLine = label;
  829. bool inMethod = label.IsMethod;
  830. while (true)
  831. {
  832. nextLine = nextLine.NextLine;
  833. parentProcess.scaningLine = nextLine;
  834. if (!(nextLine is InstructionLine func))
  835. {
  836. if ((nextLine is NullLine) || (nextLine is FunctionLabelLine))
  837. break;
  838. continue;
  839. }
  840. if (inMethod)
  841. {
  842. if (!func.Function.IsMethodSafe())
  843. {
  844. ParserMediator.Warn(func.Function.Name + "命令は#FUNCTION中で使うことはできません", nextLine, 2, true, false);
  845. continue;
  846. }
  847. }
  848. if (Config.Config.NeedReduceArgumentOnLoad || Program.AnalysisMode || func.Function.IsForceSetArg())
  849. ArgumentParser.SetArgumentTo(func);
  850. }
  851. }
  852. private void nestCheck(FunctionLabelLine label)
  853. {
  854. //2周目/3周
  855. //IF-ELSEIF-ENDIF、REPEAT-RENDの対応チェックなど
  856. //PRINTDATA系もここでチェック
  857. LogicalLine nextLine = label;
  858. List<InstructionLine> tempLineList = new List<InstructionLine>();
  859. Stack<InstructionLine> nestStack = new Stack<InstructionLine>();
  860. Stack<InstructionLine> SelectcaseStack = new Stack<InstructionLine>();
  861. InstructionLine pairLine = null;
  862. while (true)
  863. {
  864. nextLine = nextLine.NextLine;
  865. parentProcess.scaningLine = nextLine;
  866. if ((nextLine is NullLine) || (nextLine is FunctionLabelLine))
  867. break;
  868. if (!(nextLine is InstructionLine))
  869. {
  870. if (nextLine is GotoLabelLine)
  871. {
  872. InstructionLine currentBaseFunc = nestStack.Count == 0 ? null : nestStack.Peek();
  873. if (currentBaseFunc != null)
  874. {
  875. if ((currentBaseFunc.FunctionCode == FunctionCode.PRINTDATA)
  876. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAL)
  877. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAW)
  878. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAD)
  879. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATADL)
  880. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATADW)
  881. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAK)
  882. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAKL)
  883. || (currentBaseFunc.FunctionCode == FunctionCode.PRINTDATAKW)
  884. || (currentBaseFunc.FunctionCode == FunctionCode.STRDATA)
  885. || (currentBaseFunc.FunctionCode == FunctionCode.DATALIST)
  886. || (currentBaseFunc.FunctionCode == FunctionCode.TRYCALLLIST)
  887. || (currentBaseFunc.FunctionCode == FunctionCode.TRYJUMPLIST)
  888. || (currentBaseFunc.FunctionCode == FunctionCode.TRYGOTOLIST))
  889. //|| (currentBaseFunc.FunctionCode == FunctionCode.SELECTCASE))
  890. {
  891. ParserMediator.Warn(currentBaseFunc.Function.Name + "構文中に$ラベルを定義することはできません", nextLine, 2, true, false);
  892. }
  893. }
  894. }
  895. continue;
  896. }
  897. InstructionLine func = (InstructionLine)nextLine;
  898. pairLine = null;
  899. InstructionLine baseFunc = nestStack.Count == 0 ? null : nestStack.Peek();
  900. if (baseFunc != null)
  901. {
  902. if ((baseFunc.Function.IsPrintData() || baseFunc.FunctionCode == FunctionCode.STRDATA) )
  903. {
  904. if ((func.FunctionCode != FunctionCode.DATA) && (func.FunctionCode != FunctionCode.DATAFORM) && (func.FunctionCode != FunctionCode.DATALIST)
  905. && (func.FunctionCode != FunctionCode.ENDLIST) && (func.FunctionCode != FunctionCode.ENDDATA))
  906. {
  907. ParserMediator.Warn(baseFunc.Function.Name + "構文に使用できない命令\'" + func.Function.Name + "\'が含まれています", func, 2, true, false);
  908. continue;
  909. }
  910. }
  911. else if (baseFunc.FunctionCode == FunctionCode.DATALIST)
  912. {
  913. if ((func.FunctionCode != FunctionCode.DATA) && (func.FunctionCode != FunctionCode.DATAFORM) && (func.FunctionCode != FunctionCode.ENDLIST))
  914. {
  915. ParserMediator.Warn("DATALIST構文に使用できない命令\'" + func.Function.Name + "\'が含まれています", func, 2, true, false);
  916. continue;
  917. }
  918. }
  919. else if ((baseFunc.FunctionCode == FunctionCode.TRYCALLLIST) || (baseFunc.FunctionCode == FunctionCode.TRYJUMPLIST) || (baseFunc.FunctionCode == FunctionCode.TRYGOTOLIST))
  920. {
  921. if ((func.FunctionCode != FunctionCode.FUNC) && (func.FunctionCode != FunctionCode.ENDFUNC))
  922. {
  923. ParserMediator.Warn(baseFunc.Function.Name + "構文に使用できない命令\'" + func.Function.Name + "\'が含まれています", func, 2, true, false);
  924. continue;
  925. }
  926. }
  927. else if (baseFunc.FunctionCode == FunctionCode.SELECTCASE)
  928. {
  929. if ((baseFunc.IfCaseList.Count == 0) && (func.FunctionCode != FunctionCode.CASE) && (func.FunctionCode != FunctionCode.CASEELSE) && (func.FunctionCode != FunctionCode.ENDSELECT))
  930. {
  931. ParserMediator.Warn("SELECTCASE構文の分岐の外に命令\'" + func.Function.Name + "\'が含まれています", func, 2, true, false);
  932. continue;
  933. }
  934. }
  935. }
  936. switch (func.FunctionCode)
  937. {
  938. case FunctionCode.REPEAT:
  939. foreach (InstructionLine iLine in nestStack)
  940. {
  941. if (iLine.FunctionCode == FunctionCode.REPEAT)
  942. {
  943. ParserMediator.Warn("REPEAT statements cannot be nested", func, 2, true, false);
  944. break;
  945. }
  946. }
  947. if (func.IsError)
  948. break;
  949. nestStack.Push(func);
  950. break;
  951. case FunctionCode.IF:
  952. nestStack.Push(func);
  953. func.IfCaseList = new List<InstructionLine>();
  954. func.IfCaseList.Add(func);
  955. break;
  956. case FunctionCode.SELECTCASE:
  957. nestStack.Push(func);
  958. func.IfCaseList = new List<InstructionLine>();
  959. SelectcaseStack.Push(func);
  960. break;
  961. case FunctionCode.FOR:
  962. case FunctionCode.WHILE:
  963. case FunctionCode.TRYCGOTO:
  964. case FunctionCode.TRYCJUMP:
  965. case FunctionCode.TRYCCALL:
  966. case FunctionCode.TRYCGOTOFORM:
  967. case FunctionCode.TRYCJUMPFORM:
  968. case FunctionCode.TRYCCALLFORM:
  969. case FunctionCode.DO:
  970. nestStack.Push(func);
  971. break;
  972. case FunctionCode.BREAK:
  973. case FunctionCode.CONTINUE:
  974. InstructionLine[] array = nestStack.ToArray();
  975. for (int i = 0; i < array.Length; i++)
  976. {
  977. if ((array[i].FunctionCode == FunctionCode.REPEAT)
  978. || (array[i].FunctionCode == FunctionCode.FOR)
  979. || (array[i].FunctionCode == FunctionCode.WHILE)
  980. || (array[i].FunctionCode == FunctionCode.DO))
  981. {
  982. pairLine = array[i];
  983. break;
  984. }
  985. }
  986. if (pairLine == null)
  987. {
  988. ParserMediator.Warn("REPEAT, FOR, WHILE, DOの中以外で" + func.Function.Name + "文が使われました", func, 2, true, false);
  989. break;
  990. }
  991. func.JumpTo = pairLine;
  992. break;
  993. case FunctionCode.ELSEIF:
  994. case FunctionCode.ELSE:
  995. {
  996. //1.725 Stack<T>.Peek()はStackが空の時はnullを返す仕様だと思いこんでおりました。
  997. InstructionLine ifLine = nestStack.Count == 0 ? null : nestStack.Peek();
  998. if ((ifLine == null) || (ifLine.FunctionCode != FunctionCode.IF))
  999. {
  1000. ParserMediator.Warn("IF~ENDIFの外で" + func.Function.Name + "文が使われました", func, 2, true, false);
  1001. break;
  1002. }
  1003. if (ifLine.IfCaseList[ifLine.IfCaseList.Count - 1].FunctionCode == FunctionCode.ELSE)
  1004. ParserMediator.Warn("ELSE文より後で" + func.Function.Name + "文が使われました", func, 1, false, false);
  1005. ifLine.IfCaseList.Add(func);
  1006. }
  1007. break;
  1008. case FunctionCode.ENDIF:
  1009. {
  1010. InstructionLine ifLine = nestStack.Count == 0 ? null : nestStack.Peek();
  1011. if ((ifLine == null) || (ifLine.FunctionCode != FunctionCode.IF))
  1012. {
  1013. ParserMediator.Warn("対応するIFの無いENDIF文です", func, 2, true, false);
  1014. break;
  1015. }
  1016. foreach (InstructionLine ifelseifLine in ifLine.IfCaseList)
  1017. {
  1018. ifelseifLine.JumpTo = func;
  1019. }
  1020. nestStack.Pop();
  1021. }
  1022. break;
  1023. case FunctionCode.CASE:
  1024. case FunctionCode.CASEELSE:
  1025. {
  1026. InstructionLine selectLine = nestStack.Count == 0 ? null : nestStack.Peek();
  1027. if ((selectLine == null) || (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count == 0))
  1028. {
  1029. ParserMediator.Warn("SELECTCASE~ENDSELECTの外で" + func.Function.Name + "文が使われました", func, 2, true, false);
  1030. break;
  1031. }
  1032. if (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count > 0)
  1033. {
  1034. do
  1035. {
  1036. ParserMediator.Warn(selectLine.Function.Name + "文に対応する" + FunctionIdentifier.getMatchFunction(selectLine.FunctionCode) + "がない状態で" + func.Function.Name + "文に到達しました", func, 2, true, false);
  1037. //これを跨いでIF等が閉じられることがないようにする。
  1038. nestStack.Pop();
  1039. //if (nestStack.Count > 0) //空になってるかは下で判定できるので、これを見る必要がない
  1040. selectLine = nestStack.Count == 0 ? null : nestStack.Peek(); //ちなみにnullになることはない(SELECTCASEがない場合は上で弾けるから)
  1041. } while (selectLine != null && selectLine.FunctionCode != FunctionCode.SELECTCASE);
  1042. break;
  1043. }
  1044. if ((selectLine.IfCaseList.Count > 0) &&
  1045. (selectLine.IfCaseList[selectLine.IfCaseList.Count - 1].FunctionCode == FunctionCode.CASEELSE))
  1046. ParserMediator.Warn("CASEELSE文より後で" + func.Function.Name + "文が使われました", func, 1, false, false);
  1047. selectLine.IfCaseList.Add(func);
  1048. }
  1049. break;
  1050. case FunctionCode.ENDSELECT:
  1051. {
  1052. InstructionLine selectLine = nestStack.Count == 0 ? null : nestStack.Peek();
  1053. if ((selectLine == null) || (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count == 0))
  1054. {
  1055. ParserMediator.Warn("対応するSELECTCASEの無いENDSELECT文です", func, 2, true, false);
  1056. break;
  1057. }
  1058. if (selectLine.FunctionCode != FunctionCode.SELECTCASE && SelectcaseStack.Count > 0)
  1059. {
  1060. do
  1061. {
  1062. ParserMediator.Warn(selectLine.Function.Name + "文に対応する" + FunctionIdentifier.getMatchFunction(selectLine.FunctionCode) + "がない状態で" + func.Function.Name + "文に到達しました", func, 2, true, false);
  1063. //これを跨いでIF等が閉じられることがないようにする。
  1064. nestStack.Pop();
  1065. //if (nestStack.Count > 0) //空になってるかは下で判定できるので、これを見る必要がない
  1066. selectLine = nestStack.Count == 0 ? null : nestStack.Peek(); //ちなみにnullになることはない(SELECTCASEがない場合は上で弾けるから)
  1067. } while (selectLine != null && selectLine.FunctionCode != FunctionCode.SELECTCASE); 
  1068. //とりあえず、対応するSELECTCASE跨ぎは閉じる
  1069. SelectcaseStack.Pop();
  1070. //こっちでも抜かないとSELECTCASEが2つのENDSELECTに対応してしまう
  1071. nestStack.Pop();
  1072. break;
  1073. }
  1074. nestStack.Pop();
  1075. SelectcaseStack.Pop();
  1076. selectLine.JumpTo = func;
  1077. if (selectLine.IsError)
  1078. break;
  1079. IOperandTerm term = ((ExpressionArgument)selectLine.Argument).Term;
  1080. if (term == null)
  1081. {
  1082. ParserMediator.Warn("SELECTCASEの引数がありません", selectLine, 2, true, false);
  1083. break;
  1084. }
  1085. foreach (InstructionLine caseLine in selectLine.IfCaseList)
  1086. {
  1087. caseLine.JumpTo = func;
  1088. if (caseLine.IsError)
  1089. continue;
  1090. if (caseLine.FunctionCode == FunctionCode.CASEELSE)
  1091. continue;
  1092. CaseExpression[] caseExps = ((CaseArgument)caseLine.Argument).CaseExps;
  1093. if (caseExps.Length == 0)
  1094. ParserMediator.Warn("CASEの引数がありません", caseLine, 2, true, false);
  1095. foreach (CaseExpression exp in caseExps)
  1096. {
  1097. if (exp.GetOperandType() != term.GetOperandType())
  1098. ParserMediator.Warn("CASEの引数の型がSELECTCASEと一致しません", caseLine, 2, true, false);
  1099. }
  1100. }
  1101. }
  1102. break;
  1103. case FunctionCode.REND:
  1104. case FunctionCode.NEXT:
  1105. case FunctionCode.WEND:
  1106. case FunctionCode.LOOP:
  1107. FunctionCode parentFunc = FunctionIdentifier.getParentFunc(func.FunctionCode);
  1108. //if (parentFunc == FunctionCode.__NULL__)
  1109. // throw new ExeEE("何か変?");
  1110. if ((nestStack.Count == 0)
  1111. || (nestStack.Peek().FunctionCode != parentFunc))
  1112. {
  1113. ParserMediator.Warn("対応する" + parentFunc + "の無い" + func.Function.Name + "文です", func, 2, true, false);
  1114. break;
  1115. }
  1116. pairLine = nestStack.Pop();//REPEAT
  1117. func.JumpTo = pairLine;
  1118. pairLine.JumpTo = func;
  1119. break;
  1120. case FunctionCode.CATCH:
  1121. pairLine = nestStack.Count == 0 ? null : nestStack.Peek();
  1122. if ((pairLine == null)
  1123. || ((pairLine.FunctionCode != FunctionCode.TRYCGOTO)
  1124. && (pairLine.FunctionCode != FunctionCode.TRYCCALL)
  1125. && (pairLine.FunctionCode != FunctionCode.TRYCJUMP)
  1126. && (pairLine.FunctionCode != FunctionCode.TRYCGOTOFORM)
  1127. && (pairLine.FunctionCode != FunctionCode.TRYCCALLFORM)
  1128. && (pairLine.FunctionCode != FunctionCode.TRYCJUMPFORM)))
  1129. {
  1130. ParserMediator.Warn("対応するTRYC系命令がありません", func, 2, true, false);
  1131. break;
  1132. }
  1133. pairLine = nestStack.Pop();//TRYC
  1134. pairLine.JumpToEndCatch = func;//TRYCにCATCHの位置を教える
  1135. nestStack.Push(func);
  1136. break;
  1137. case FunctionCode.ENDCATCH:
  1138. if ((nestStack.Count == 0)
  1139. || (nestStack.Peek().FunctionCode != FunctionCode.CATCH))
  1140. {
  1141. ParserMediator.Warn("対応するCATCHのないENDCATCHです", func, 2, true, false);
  1142. break;
  1143. }
  1144. pairLine = nestStack.Pop();//CATCH
  1145. pairLine.JumpToEndCatch = func;//CATCHにENDCATCHの位置を教える
  1146. break;
  1147. case FunctionCode.PRINTDATA:
  1148. case FunctionCode.PRINTDATAL:
  1149. case FunctionCode.PRINTDATAW:
  1150. case FunctionCode.PRINTDATAD:
  1151. case FunctionCode.PRINTDATADL:
  1152. case FunctionCode.PRINTDATADW:
  1153. case FunctionCode.PRINTDATAK:
  1154. case FunctionCode.PRINTDATAKL:
  1155. case FunctionCode.PRINTDATAKW:
  1156. {
  1157. foreach (InstructionLine iLine in nestStack)
  1158. {
  1159. if (iLine.Function.IsPrintData())
  1160. {
  1161. ParserMediator.Warn("PRINTDATA系命令が入れ子にされています", func, 2, true, false);
  1162. break;
  1163. }
  1164. if (iLine.FunctionCode == FunctionCode.STRDATA)
  1165. {
  1166. ParserMediator.Warn("PRINTDATA系命令の中にSTRDATA系命令が含まれています", func, 2, true, false);
  1167. break;
  1168. }
  1169. }
  1170. if (func.IsError)
  1171. break;
  1172. func.dataList = new List<List<InstructionLine>>();
  1173. nestStack.Push(func);
  1174. break;
  1175. }
  1176. case FunctionCode.STRDATA:
  1177. {
  1178. foreach (InstructionLine iLine in nestStack)
  1179. {
  1180. if (iLine.FunctionCode == FunctionCode.STRDATA)
  1181. {
  1182. ParserMediator.Warn("STRDATA命令が入れ子にされています", func, 2, true, false);
  1183. break;
  1184. }
  1185. if (iLine.Function.IsPrintData())
  1186. {
  1187. ParserMediator.Warn("STRDATA系命令の中にPRINTDATA系命令が含まれています", func, 2, true, false);
  1188. break;
  1189. }
  1190. }
  1191. if (func.IsError)
  1192. break;
  1193. func.dataList = new List<List<InstructionLine>>();
  1194. nestStack.Push(func);
  1195. break;
  1196. }
  1197. case FunctionCode.DATALIST:
  1198. {
  1199. InstructionLine pline = (nestStack.Count == 0) ? null : nestStack.Peek();
  1200. if ((pline == null) || ((!pline.Function.IsPrintData()) && (pline.FunctionCode != FunctionCode.STRDATA)))
  1201. {
  1202. ParserMediator.Warn("対応するPRINTDATA系命令のないDATALISTです", func, 2, true, false);
  1203. break;
  1204. }
  1205. tempLineList = new List<InstructionLine>();
  1206. nestStack.Push(func);
  1207. break;
  1208. }
  1209. case FunctionCode.ENDLIST:
  1210. {
  1211. if ((nestStack.Count == 0) || (nestStack.Peek().FunctionCode != FunctionCode.DATALIST))
  1212. {
  1213. ParserMediator.Warn("対応するDATALISTのないENDLISTです", func, 2, true, false);
  1214. break;
  1215. }
  1216. if (tempLineList.Count == 0)
  1217. ParserMediator.Warn("DATALIST命令に表示データが与えられていません(このDATALISTは空文字列を表示します)", func, 1, false, false);
  1218. nestStack.Pop();
  1219. nestStack.Peek().dataList.Add(tempLineList);
  1220. break;
  1221. }
  1222. case FunctionCode.DATA:
  1223. case FunctionCode.DATAFORM:
  1224. {
  1225. InstructionLine pdata = (nestStack.Count == 0) ? null : nestStack.Peek();
  1226. if ((pdata == null) || (!pdata.Function.IsPrintData() && pdata.FunctionCode != FunctionCode.DATALIST && pdata.FunctionCode != FunctionCode.STRDATA))
  1227. {
  1228. ParserMediator.Warn("対応するPRINTDATA系命令のない" + func.Function.Name + "です", func, 2, true, false);
  1229. break;
  1230. }
  1231. List<InstructionLine> iList = new List<InstructionLine>();
  1232. if (pdata.FunctionCode != FunctionCode.DATALIST)
  1233. {
  1234. iList.Add(func);
  1235. pdata.dataList.Add(iList);
  1236. }
  1237. else
  1238. tempLineList.Add(func);
  1239. break;
  1240. }
  1241. case FunctionCode.ENDDATA:
  1242. {
  1243. InstructionLine pline = (nestStack.Count == 0) ? null : nestStack.Peek();
  1244. if ((pline == null) || ((!pline.Function.IsPrintData()) && (pline.FunctionCode != FunctionCode.STRDATA)))
  1245. {
  1246. ParserMediator.Warn("対応するPRINTDATA系命令もしくはSTRDATAのない" + func.Function.Name + "です", func, 2, true, false);
  1247. break;
  1248. }
  1249. if (pline.FunctionCode == FunctionCode.DATALIST)
  1250. ParserMediator.Warn("DATALISTが閉じられていません", func, 2, true, false);
  1251. if (pline.dataList.Count == 0)
  1252. ParserMediator.Warn(pline.Function.Name + "命令に表示データがありません(この命令は無視されます)", func, 1, false, false);
  1253. pline.JumpTo = func;
  1254. nestStack.Pop();
  1255. break;
  1256. }
  1257. case FunctionCode.TRYCALLLIST:
  1258. case FunctionCode.TRYJUMPLIST:
  1259. case FunctionCode.TRYGOTOLIST:
  1260. foreach (InstructionLine iLine in nestStack)
  1261. {
  1262. if (iLine.FunctionCode == FunctionCode.TRYCALLLIST || iLine.FunctionCode == FunctionCode.TRYJUMPLIST || iLine.FunctionCode == FunctionCode.TRYGOTOLIST)
  1263. {
  1264. ParserMediator.Warn("TRYCALLLIST系命令が入れ子にされています", func, 2, true, false);
  1265. break;
  1266. }
  1267. }
  1268. if (func.IsError)
  1269. break;
  1270. func.callList = new List<InstructionLine>();
  1271. nestStack.Push(func);
  1272. break;
  1273. case FunctionCode.FUNC:
  1274. {
  1275. InstructionLine pFunc = (nestStack.Count == 0) ? null : nestStack.Peek();
  1276. if ((pFunc == null) ||
  1277. (pFunc.FunctionCode != FunctionCode.TRYCALLLIST && pFunc.FunctionCode != FunctionCode.TRYJUMPLIST && pFunc.FunctionCode != FunctionCode.TRYGOTOLIST))
  1278. {
  1279. ParserMediator.Warn("対応するTRYCALLLIST系命令のない" + func.Function.Name + "です", func, 2, true, false);
  1280. break;
  1281. }
  1282. if (func.Argument == null)
  1283. {
  1284. ParserMediator.Warn("TRYCALLLIST系命令中に無効な" + func.Function.Name + "が存在します", pFunc, 2, true, false);
  1285. break;
  1286. }
  1287. if (pFunc.FunctionCode == FunctionCode.TRYGOTOLIST)
  1288. {
  1289. if (((SpCallArgment)func.Argument).SubNames.Length != 0)
  1290. {
  1291. ParserMediator.Warn("TRYGOTOLISTの呼び出し対象に[~~]が設定されています", func, 2, true, false);
  1292. break;
  1293. }
  1294. if (((SpCallArgment)func.Argument).RowArgs.Length != 0)
  1295. {
  1296. ParserMediator.Warn("TRYGOTOLISTの呼び出し対象に引数が設定されています", func, 2, true, false);
  1297. break;
  1298. }
  1299. }
  1300. pFunc.callList.Add(func);
  1301. break;
  1302. }
  1303. case FunctionCode.ENDFUNC:
  1304. InstructionLine pf = (nestStack.Count == 0) ? null : nestStack.Peek();
  1305. if ((pf == null) ||
  1306. (pf.FunctionCode != FunctionCode.TRYCALLLIST && pf.FunctionCode != FunctionCode.TRYJUMPLIST && pf.FunctionCode != FunctionCode.TRYGOTOLIST))
  1307. {
  1308. ParserMediator.Warn("対応するTRYCALLLIST系命令のない" + func.Function.Name + "です", func, 2, true, false);
  1309. break;
  1310. }
  1311. pf.JumpTo = func;
  1312. nestStack.Pop();
  1313. break;
  1314. case FunctionCode.NOSKIP:
  1315. foreach (InstructionLine iLine in nestStack)
  1316. {
  1317. if (iLine.FunctionCode == FunctionCode.NOSKIP)
  1318. {
  1319. ParserMediator.Warn("NOSKIP系命令が入れ子にされています", func, 2, true, false);
  1320. break;
  1321. }
  1322. }
  1323. if (func.IsError)
  1324. break;
  1325. nestStack.Push(func);
  1326. break;
  1327. case FunctionCode.ENDNOSKIP:
  1328. InstructionLine pfunc = (nestStack.Count == 0) ? null : nestStack.Peek();
  1329. if ((pfunc == null) ||
  1330. (pfunc.FunctionCode != FunctionCode.NOSKIP))
  1331. {
  1332. ParserMediator.Warn("対応するNOSKIP系命令のない" + func.Function.Name + "です", func, 2, true, false);
  1333. break;
  1334. }
  1335. //エラーハンドリング用
  1336. pfunc.JumpTo = func;
  1337. func.JumpTo = pfunc;
  1338. nestStack.Pop();
  1339. break;
  1340. }
  1341. }
  1342. while (nestStack.Count != 0)
  1343. {
  1344. InstructionLine func = nestStack.Pop();
  1345. string funcName = func.Function.Name;
  1346. string funcMatch = FunctionIdentifier.getMatchFunction(func.FunctionCode);
  1347. if (func != null)
  1348. ParserMediator.Warn(funcName + " is missing corresponding " + funcMatch, func, 2, true, false);
  1349. else
  1350. ParserMediator.Warn("ディフォルトエラー(Emuera設定漏れ)", func, 2, true, false);
  1351. }
  1352. //使ったスタックをクリア
  1353. SelectcaseStack.Clear();
  1354. }
  1355. private void setJumpTo(FunctionLabelLine label)
  1356. {
  1357. //3周目/3周
  1358. //フロー制御命令のジャンプ先を設定
  1359. LogicalLine nextLine = label;
  1360. int depth = label.Depth;
  1361. if (depth < 0)
  1362. depth = -2;
  1363. while (true)
  1364. {
  1365. nextLine = nextLine.NextLine;
  1366. InstructionLine func = nextLine as InstructionLine;
  1367. if (func == null)
  1368. {
  1369. if ((nextLine is NullLine) || (nextLine is FunctionLabelLine))
  1370. break;
  1371. continue;
  1372. }
  1373. if (func.IsError)
  1374. continue;
  1375. parentProcess.scaningLine = func;
  1376. if (func.Function.Instruction != null)
  1377. {
  1378. string FunctionNotFoundName = null;
  1379. try
  1380. {
  1381. func.Function.Instruction.SetJumpTo(ref useCallForm, func, depth, ref FunctionNotFoundName);
  1382. }
  1383. catch (CodeEE e)
  1384. {
  1385. ParserMediator.Warn(e.Message, func, 2, true, false);
  1386. continue;
  1387. }
  1388. if (FunctionNotFoundName != null)
  1389. {
  1390. if (!Program.AnalysisMode)
  1391. printFunctionNotFoundWarning("指定された関数名\"@" + FunctionNotFoundName + "\"は存在しません", func, 2, true);
  1392. else
  1393. printFunctionNotFoundWarning(FunctionNotFoundName, func, 2, true);
  1394. }
  1395. continue;
  1396. }
  1397. if ((func.FunctionCode == FunctionCode.TRYCALLLIST) || (func.FunctionCode == FunctionCode.TRYJUMPLIST))
  1398. useCallForm = true;
  1399. }
  1400. }
  1401. }
  1402. }