StrForm.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using NTERA.EmuEra.Game.EraEmu.GameData.Expression;
  5. using NTERA.EmuEra.Game.EraEmu.GameData.Function;
  6. using NTERA.EmuEra.Game.EraEmu.GameData.Variable;
  7. using NTERA.EmuEra.Game.EraEmu.Sub;
  8. using NTERA.EmuEra.Game.EraEmu._Library;
  9. namespace NTERA.EmuEra.Game.EraEmu.GameData
  10. {
  11. internal sealed class StrForm
  12. {
  13. private StrForm() { }
  14. string[] strs;//terms.Length + 1
  15. IOperandTerm[] terms;
  16. #region static
  17. static FormattedStringMethod formatCurlyBrace;
  18. static FormattedStringMethod formatPercent;
  19. static FormattedStringMethod formatYenAt;
  20. static FunctionMethodTerm NameTarget;// "***"
  21. static FunctionMethodTerm CallnameMaster;// "+++"
  22. static FunctionMethodTerm CallnamePlayer;// "==="
  23. static FunctionMethodTerm NameAssi;// "///"
  24. static FunctionMethodTerm CallnameTarget;// "$$$"
  25. public static void Initialize()
  26. {
  27. formatCurlyBrace = new FormatCurlyBrace();
  28. formatPercent = new FormatPercent();
  29. formatYenAt = new FormatYenAt();
  30. VariableToken nameID = GlobalStatic.VariableData.GetSystemVariableToken("NAME");
  31. VariableToken callnameID = GlobalStatic.VariableData.GetSystemVariableToken("CALLNAME");
  32. IOperandTerm[] zeroArg = { new SingleTerm(0) };
  33. VariableTerm target = new VariableTerm(GlobalStatic.VariableData.GetSystemVariableToken("TARGET"), zeroArg);
  34. VariableTerm master = new VariableTerm(GlobalStatic.VariableData.GetSystemVariableToken("MASTER"), zeroArg);
  35. VariableTerm player = new VariableTerm(GlobalStatic.VariableData.GetSystemVariableToken("PLAYER"), zeroArg);
  36. VariableTerm assi = new VariableTerm(GlobalStatic.VariableData.GetSystemVariableToken("ASSI"), zeroArg);
  37. VariableTerm nametarget = new VariableTerm(nameID, new IOperandTerm[] { target });
  38. VariableTerm callnamemaster = new VariableTerm(callnameID, new IOperandTerm[] { master });
  39. VariableTerm callnameplayer = new VariableTerm(callnameID, new IOperandTerm[] { player });
  40. VariableTerm nameassi = new VariableTerm(nameID, new IOperandTerm[] { assi });
  41. VariableTerm callnametarget = new VariableTerm(callnameID, new IOperandTerm[] { target });
  42. NameTarget = new FunctionMethodTerm(formatPercent, new IOperandTerm[] { nametarget, null, null });
  43. CallnameMaster = new FunctionMethodTerm(formatPercent, new IOperandTerm[] { callnamemaster, null, null });
  44. CallnamePlayer = new FunctionMethodTerm(formatPercent, new IOperandTerm[] { callnameplayer, null, null });
  45. NameAssi = new FunctionMethodTerm(formatPercent, new IOperandTerm[] { nameassi, null, null });
  46. CallnameTarget = new FunctionMethodTerm(formatPercent, new IOperandTerm[] { callnametarget, null, null });
  47. }
  48. public static StrForm FromWordToken(StrFormWord wt)
  49. {
  50. StrForm ret = new StrForm();
  51. ret.strs = wt.Strs;
  52. IOperandTerm[] termArray = new IOperandTerm[wt.SubWords.Length];
  53. for (int i = 0; i < wt.SubWords.Length; i++)
  54. {
  55. SubWord SWT = wt.SubWords[i];
  56. TripleSymbolSubWord tSymbol = SWT as TripleSymbolSubWord;
  57. if (tSymbol != null)
  58. {
  59. switch (tSymbol.Code)
  60. {
  61. case '*':
  62. termArray[i] = NameTarget;
  63. continue;
  64. case '+':
  65. termArray[i] = CallnameMaster;
  66. continue;
  67. case '=':
  68. termArray[i] = CallnamePlayer;
  69. continue;
  70. case '/':
  71. termArray[i] = NameAssi;
  72. continue;
  73. case '$':
  74. termArray[i] = CallnameTarget;
  75. continue;
  76. }
  77. throw new ExeEE("何かおかしい");
  78. }
  79. WordCollection wc = null;
  80. IOperandTerm operand = null;
  81. YenAtSubWord yenat = SWT as YenAtSubWord;
  82. if (yenat != null)
  83. {
  84. wc = yenat.Words;
  85. if (wc != null)
  86. {
  87. operand = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.EoL);
  88. if (!wc.EOL)
  89. throw new CodeEE("三項演算子\\@の第一オペランドが異常です");
  90. }
  91. else
  92. operand = new SingleTerm(0);
  93. IOperandTerm left = new StrFormTerm(FromWordToken(yenat.Left));
  94. IOperandTerm right = null;
  95. if (yenat.Right == null)
  96. right = new SingleTerm("");
  97. else
  98. right = new StrFormTerm(FromWordToken(yenat.Right));
  99. termArray[i] = new FunctionMethodTerm(formatYenAt, new[] { operand, left, right });
  100. continue;
  101. }
  102. wc = SWT.Words;
  103. operand = ExpressionParser.ReduceExpressionTerm(wc, TermEndWith.Comma);
  104. if (operand == null)
  105. {
  106. if (SWT is CurlyBraceSubWord)
  107. throw new CodeEE("{}の中に式が存在しません");
  108. throw new CodeEE("%%の中に式が存在しません");
  109. }
  110. IOperandTerm second = null;
  111. SingleTerm third = null;
  112. wc.ShiftNext();
  113. if (!wc.EOL)
  114. {
  115. second = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.Comma);
  116. wc.ShiftNext();
  117. if (!wc.EOL)
  118. {
  119. IdentifierWord id = wc.Current as IdentifierWord;
  120. if (id == null)
  121. throw new CodeEE("','の後にRIGHT又はLEFTがありません");
  122. if (string.Equals(id.Code, "LEFT", Config.Config.SCVariable))//標準RIGHT
  123. third = new SingleTerm(1);
  124. else if (!string.Equals(id.Code, "RIGHT", Config.Config.SCVariable))
  125. throw new CodeEE("','の後にRIGHT又はLEFT以外の単語があります");
  126. wc.ShiftNext();
  127. }
  128. if (!wc.EOL)
  129. throw new CodeEE("RIGHT又はLEFTの後に余分な文字があります");
  130. }
  131. if (SWT is CurlyBraceSubWord)
  132. {
  133. if (operand.GetOperandType() != typeof(Int64))
  134. throw new CodeEE("{}の中の式が数式ではありません");
  135. termArray[i] = new FunctionMethodTerm(formatCurlyBrace, new[] { operand, second, third });
  136. continue;
  137. }
  138. if (operand.GetOperandType() != typeof(string))
  139. throw new CodeEE("%%の中の式が文字列式ではありません");
  140. termArray[i] = new FunctionMethodTerm(formatPercent, new[] { operand, second, third });
  141. }
  142. ret.terms = termArray;
  143. return ret;
  144. }
  145. #endregion
  146. public bool IsConst => (strs.Length == 1);
  147. public IOperandTerm GetIOperandTerm()
  148. {
  149. if((strs.Length == 2) && (strs[0].Length == 0) && (strs[1].Length == 0))
  150. return terms[0];
  151. return null;
  152. }
  153. public void Restructure(ExpressionMediator exm, bool tryTranslate=false)
  154. {
  155. if (strs.Length == 1)
  156. return;
  157. bool canRestructure = false;
  158. for (int i = 0; i < terms.Length; i++)
  159. {
  160. terms[i] = terms[i].Restructure(exm);
  161. if (terms[i] is SingleTerm)
  162. {
  163. canRestructure = true;
  164. }
  165. }
  166. if (!canRestructure)
  167. return;
  168. List<string> strList = new List<string>();
  169. List<IOperandTerm> termList = new List<IOperandTerm>();
  170. strList.AddRange(strs);
  171. termList.AddRange(terms);
  172. for (int i = 0; i < termList.Count; i++)
  173. {
  174. if (termList[i] is SingleTerm)
  175. {
  176. string str = termList[i].GetStrValue(exm, tryTranslate);
  177. strList[i] = strList[i] + str + strList[i + 1];
  178. termList.RemoveAt(i);
  179. strList.RemoveAt(i + 1);
  180. i--;
  181. }
  182. }
  183. strs = new string[strList.Count];
  184. terms = new IOperandTerm[termList.Count];
  185. strList.CopyTo(strs);
  186. termList.CopyTo(terms);
  187. }
  188. public string GetString(ExpressionMediator exm, bool tryTranslate = false)
  189. {
  190. if (strs.Length == 1)
  191. return strs[0];
  192. StringBuilder builder = new StringBuilder(100);
  193. for (int i = 0; i < strs.Length - 1; i++)
  194. {
  195. builder.Append(strs[i]);
  196. //builder.Append(Translation.translate(terms[i].GetStrValue(exm)));
  197. //If the tryTranslate is true we'll try to translate it
  198. //HERE
  199. builder.Append(terms[i].GetStrValue(exm, tryTranslate));
  200. }
  201. builder.Append(strs[strs.Length - 1]);
  202. return builder.ToString();
  203. }
  204. #region FormattedStringMethod 書式付文字列の内部
  205. private abstract class FormattedStringMethod : FunctionMethod
  206. {
  207. public FormattedStringMethod()
  208. {
  209. CanRestructure = true;
  210. ReturnType = typeof(string);
  211. argumentTypeArray = null;
  212. }
  213. public override string CheckArgumentType(string name, IOperandTerm[] arguments) { throw new ExeEE("型チェックは呼び出し元が行うこと"); }
  214. public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments) { throw new ExeEE("戻り値の型が違う"); }
  215. public override SingleTerm GetReturnValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate) { return new SingleTerm(GetStrValue(exm, arguments, tryTranslate)); }
  216. }
  217. private sealed class FormatCurlyBrace : FormattedStringMethod
  218. {
  219. public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
  220. {
  221. int nbrPad = 0;
  222. string ret = arguments[0].GetIntValue(exm).ToString();
  223. if (arguments[1] == null)
  224. return ret;
  225. //Bartoum: Engine bug fix, a negative value will make PadRight && PadLeft left.
  226. nbrPad = (int)arguments[1].GetIntValue(exm);
  227. if(nbrPad < 0)
  228. nbrPad = 0;
  229. if (arguments[2] != null)
  230. ret = ret.PadRight(nbrPad, ' ');//LEFT
  231. else
  232. ret = ret.PadLeft(nbrPad, ' ');//RIGHT
  233. return ret;
  234. }
  235. }
  236. private sealed class FormatPercent : FormattedStringMethod
  237. {
  238. public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
  239. {
  240. if (arguments[1] != null)
  241. tryTranslate = true;
  242. //Changes by Bartoum
  243. string ret = arguments[0].GetStrValue(exm, tryTranslate);
  244. string original = ret;
  245. //We try to translate the entire string. If the name of a csv variable was put alone in a variable like ARGS this will work.
  246. //At this point we can't know where the name came from so we need to use ALL.
  247. if(exm.Process.getCurrentLine != null && exm.Process.getCurrentLine.ToString().Contains("RETURNF"))
  248. tryTranslate = false;
  249. if (tryTranslate){
  250. ret = Translation.translate(ret, "ALL", tryTranslate);
  251. //If it didn't work we strip everything after a number and all those characters - [ ] 【 】and ( if ) is not present.
  252. if(original == ret){
  253. ret = Translation.translateALL(ret, "ALL");
  254. }
  255. }
  256. if (arguments[1] == null)
  257. return ret;
  258. int totalLength = (int)arguments[1].GetIntValue(exm);
  259. int currentLength = LangManager.GetStrlenLang(ret);
  260. totalLength -= currentLength - ret.Length;//全角文字の数だけマイナス。タブ文字?ゼロ幅文字?知るか!
  261. if (totalLength < ret.Length)
  262. return ret;//PadLeftは0未満を送ると例外を投げる
  263. if (arguments[2] != null)
  264. ret = ret.PadRight(totalLength, ' ');//LEFT
  265. else
  266. ret = ret.PadLeft(totalLength, ' ');//RIGHT
  267. return ret;
  268. }
  269. }
  270. private sealed class FormatYenAt : FormattedStringMethod
  271. {//Operator のTernaryIntStrStrとやってることは同じ
  272. public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
  273. {
  274. return (arguments[0].GetIntValue(exm) != 0) ? arguments[1].GetStrValue(exm) : arguments[2].GetStrValue(exm);
  275. }
  276. }
  277. #endregion
  278. }
  279. }