CodeGenerator.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. using GDNXFD.Data;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using System.Threading.Tasks;
  8. namespace GDNXFD.Alert.Interpreter
  9. {
  10. public class CodeGenerator
  11. {
  12. private string className;
  13. private string expression;
  14. private List<string> varList;
  15. private Stack<SustainModel> sustainStack;
  16. private List<SustainModel> sustainList;
  17. private Stack<char> barcketStack;
  18. private int sustainSeq = 1;
  19. public CodeGenerator(string clsName, string exps)
  20. {
  21. if (string.IsNullOrWhiteSpace(clsName))
  22. {
  23. className = GenerateRandomString(10);
  24. }
  25. else
  26. {
  27. className = clsName.Trim();
  28. }
  29. varList = new List<string>();
  30. if (string.IsNullOrWhiteSpace(exps))
  31. {
  32. varList.Add("true");
  33. return;
  34. }
  35. try
  36. {
  37. expression = exps.Trim().TrimEnd(';');
  38. expression = ReplaceStatusContinued(expression);
  39. expression = ReplaceSuddenChange(expression);
  40. expression = ReplaceLastUpdateTime(expression);
  41. expression = ReplaceDiffMinutes(expression);
  42. expression = ReplaceDiffSeconds(expression);
  43. PhrasingExpression(expression);
  44. if (varList != null && varList.Count > 0)
  45. {
  46. foreach (string strVar in varList)
  47. {
  48. if (DataCache.Instance.RelateUniformCodes == null)
  49. DataCache.Instance.RelateUniformCodes = new List<string>();
  50. if (!DataCache.Instance.RelateUniformCodes.Contains(strVar))
  51. DataCache.Instance.RelateUniformCodes.Add(strVar);
  52. }
  53. }
  54. if (sustainList != null && sustainList.Count > 0)
  55. {
  56. foreach (SustainModel sm in sustainList)
  57. {
  58. if (string.IsNullOrEmpty(sm.Expression) || sm.EndIndex == 0 || sm.Duration==0)
  59. throw new ExpressionException("Sustain方法不完整!");
  60. if (sm.VarList != null)
  61. {
  62. foreach (string strVar in sm.VarList)
  63. {
  64. if (DataCache.Instance.RelateUniformCodes == null)
  65. DataCache.Instance.RelateUniformCodes = new List<string>();
  66. if (!DataCache.Instance.RelateUniformCodes.Contains(strVar))
  67. DataCache.Instance.RelateUniformCodes.Add(strVar);
  68. }
  69. }
  70. }
  71. }
  72. }
  73. catch(ExpressionException)
  74. {
  75. throw;
  76. }
  77. catch (Exception ex)
  78. {
  79. throw new ExpressionException(ex);
  80. }
  81. }
  82. public void PhrasingExpression(string exps)
  83. {
  84. char[] arr = exps.ToCharArray();
  85. for (int i = 0; i < arr.Length; i++)
  86. {
  87. #region Sustain函数开始匹配
  88. if (arr[i] == 'S' && i + 7 < arr.Length &&
  89. arr[i + 1] == 'u' &&
  90. arr[i + 2] == 's' &&
  91. arr[i + 3] == 't' &&
  92. arr[i + 4] == 'a' &&
  93. arr[i + 5] == 'i' &&
  94. arr[i + 6] == 'n')
  95. {
  96. int offset = i;
  97. i += 7;
  98. while (IsWhite(arr[i]) && i < arr.Length - 1) i++; //去除空白
  99. if (arr[i] == '(')
  100. {
  101. SustainModel sModel = new SustainModel();
  102. sModel.Sequence = sustainSeq++;
  103. sModel.StartIndex = offset;
  104. if (sustainStack == null)
  105. sustainStack = new Stack<SustainModel>();
  106. if (sustainStack.Count > 0)
  107. {
  108. SustainModel sm = sustainStack.Peek();
  109. if (sm.SustainList == null)
  110. sm.SustainList = new List<SustainModel>();
  111. sm.SustainList.Add(sModel);
  112. }
  113. sustainStack.Push(sModel);
  114. if (sustainStack.Count == 1)
  115. {
  116. if (sustainList == null)
  117. sustainList = new List<SustainModel>();
  118. sustainList.Add(sModel);
  119. }
  120. i++;
  121. }
  122. }
  123. #endregion
  124. #region AI、DI变量匹配
  125. //AI, DI变量提取
  126. if ((arr[i] == 'A' || arr[i] == 'D') && i + 1 < arr.Length && arr[i + 1] == 'I')
  127. {
  128. if (i == 0 || !IsLetterOrNumber(arr[i-1]))
  129. {
  130. int offset = i;
  131. i += 2;
  132. while ((IsLetterOrNumber(arr[i]) || arr[i] == '_') && i < arr.Length - 1) i++; //提取以AI或DI开头的单词
  133. string expVar = new string(arr, offset, i == arr.Length - 1 ? i - offset + 1 : i - offset);
  134. if (sustainStack != null && sustainStack.Count > 0)
  135. {
  136. SustainModel sm = sustainStack.Peek();
  137. if (sm.VarList == null)
  138. sm.VarList = new List<string>();
  139. if (!sm.VarList.Contains(expVar))
  140. sm.VarList.Add(expVar);
  141. }
  142. else
  143. {
  144. if (varList == null)
  145. varList = new List<string>();
  146. if (!varList.Contains(expVar))
  147. varList.Add(expVar);
  148. }
  149. }
  150. }
  151. #endregion
  152. #region Sustain函数结尾匹配
  153. if (sustainStack != null && sustainStack.Count > 0)
  154. {
  155. SustainModel sm = sustainStack.Peek();
  156. if (arr[i] == '(')
  157. {
  158. if (barcketStack == null)
  159. barcketStack = new Stack<char>();
  160. barcketStack.Push('(');
  161. }
  162. else if (arr[i] == ')')
  163. {
  164. if (barcketStack != null && barcketStack.Count > 0)
  165. {
  166. barcketStack.Pop();
  167. }
  168. else
  169. {
  170. sm.EndIndex = i;
  171. sm.Expression = new string(arr, sm.StartIndex, sm.EndIndex-sm.StartIndex+1);
  172. if (sm.Duration == 0 && sm.DurationIndex !=0)
  173. {
  174. string strDuration = new string(arr, sm.DurationIndex, sm.EndIndex-sm.DurationIndex);
  175. int duration = 0;
  176. if (int.TryParse(strDuration.Trim(), out duration))
  177. {
  178. sm.Duration = duration;
  179. }
  180. else
  181. {
  182. throw new ExpressionException("表达式格式错误!位置:" + i);
  183. }
  184. }
  185. if (sm.Interval == 0 && sm.IntervalIndex != 0)
  186. {
  187. string str = new string(arr, sm.IntervalIndex, sm.EndIndex-sm.IntervalIndex);
  188. int interval = 0;
  189. if (int.TryParse(str.Trim(), out interval))
  190. {
  191. sm.Interval = interval;
  192. }
  193. else
  194. {
  195. throw new ExpressionException("表达式格式错误!位置:" + i);
  196. }
  197. }
  198. sustainStack.Pop();
  199. }
  200. }
  201. else if (arr[i] == ',')
  202. {
  203. if (barcketStack == null || barcketStack.Count == 0)
  204. {
  205. if (sm.DurationIndex == 0)
  206. sm.DurationIndex = i+1;
  207. else
  208. {
  209. sm.IntervalIndex = i+1;
  210. string strDuration = new string(arr, sm.DurationIndex, i-sm.DurationIndex);
  211. int duration = 0;
  212. if (int.TryParse(strDuration.Trim(), out duration))
  213. {
  214. sm.Duration = duration;
  215. }
  216. else
  217. {
  218. throw new ExpressionException("表达式格式错误!位置:" + i);
  219. }
  220. }
  221. }
  222. }
  223. }
  224. #endregion
  225. }
  226. }
  227. private bool IsLetterOrNumber(char c)
  228. {
  229. if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
  230. return true;
  231. return false;
  232. }
  233. private bool IsWhite(char c)
  234. {
  235. if (c == ' ' || c == '\n' || c == '\r' || c == '\t')
  236. return true;
  237. return false;
  238. }
  239. public string ToClassString()
  240. {
  241. StringBuilder sbMembers = null;
  242. if (varList != null && varList.Count > 0)
  243. {
  244. sbMembers = new StringBuilder();
  245. foreach (string member in varList)
  246. {
  247. if (member.StartsWith("AI"))
  248. sbMembers.AppendLine(string.Format(CodeTemplate.AIDeclare, member));
  249. else if (member.StartsWith("DI"))
  250. sbMembers.AppendLine(string.Format(CodeTemplate.DIDeclare, member));
  251. }
  252. }
  253. string exps = expression;
  254. StringBuilder sbSustainMethod = null;
  255. if (sustainList != null && sustainList.Count > 0)
  256. {
  257. sbSustainMethod = new StringBuilder();
  258. foreach (SustainModel sm in sustainList)
  259. {
  260. exps = exps.Replace(sm.Expression, sm.GetCallString());
  261. GenerateSustainMethod(sm, ref sbSustainMethod);
  262. }
  263. }
  264. string retStatement = string.Format(CodeTemplate.ReturnStatement, exps);
  265. return string.Format(CodeTemplate.Outline, className,
  266. sbMembers == null ? "" : sbMembers.ToString(),
  267. retStatement,
  268. sbSustainMethod == null ? "" : sbSustainMethod.ToString());
  269. }
  270. public void GenerateSustainMethod(SustainModel sm, ref StringBuilder sbSustainMethod)
  271. {
  272. sbSustainMethod.Append(sm.ToMethodString());
  273. if (sm.SustainList != null)
  274. {
  275. foreach (SustainModel ssm in sm.SustainList)
  276. GenerateSustainMethod(ssm, ref sbSustainMethod);
  277. }
  278. }
  279. private string GenerateRandomString(int codeCount)
  280. {
  281. string str = string.Empty;
  282. int seed = new Random().Next();
  283. Random random = new Random(seed);
  284. for (int i = 0; i < codeCount; i++)
  285. {
  286. int num = random.Next();
  287. str = str + ((char)(65 + ((ushort)(num % 26)))).ToString();
  288. }
  289. return str;
  290. }
  291. private string ReplaceDiffMinutes(string exp)
  292. {
  293. if (!exp.Contains("DiffMinutes"))
  294. return exp;
  295. string regex = @"DiffMinutes\(\w+,\s*\d+\)";
  296. MatchCollection coll = Regex.Matches(exp, regex);
  297. foreach (Match item in coll)
  298. {
  299. string rplStr = ConvertDiffMinutes(item.Value);
  300. exp = exp.Replace(item.Value, rplStr);
  301. }
  302. return exp;
  303. }
  304. private string ConvertDiffMinutes(string sc)
  305. {
  306. string template = "DiffMinutes(\"STR{0}\",{1},objectId,objectType)";
  307. string tmp = sc.Trim();
  308. tmp = tmp.TrimStart('D', 'i', 'f', 'f', 'M', 'i', 'n', 'u', 't', 'e', 's');
  309. tmp = tmp.Trim();
  310. tmp = tmp.TrimStart('(');
  311. tmp = tmp.TrimEnd(')');
  312. string[] arr = tmp.Split(',');
  313. return string.Format(template, arr[0].Trim(), arr[1].Trim());
  314. }
  315. private string ReplaceDiffSeconds(string exp)
  316. {
  317. if (!exp.Contains("DiffSeconds"))
  318. return exp;
  319. string regex = @"DiffSeconds\(\w+,\s*\d+\)";
  320. MatchCollection coll = Regex.Matches(exp, regex);
  321. foreach (Match item in coll)
  322. {
  323. string rplStr = ConvertDiffSeconds(item.Value);
  324. exp = exp.Replace(item.Value, rplStr);
  325. }
  326. return exp;
  327. }
  328. private string ConvertDiffSeconds(string sc)
  329. {
  330. string template = "DiffSeconds(\"STR{0}\",{1},objectId,objectType)";
  331. string tmp = sc.Trim();
  332. tmp = tmp.TrimStart('D', 'i', 'f', 'f', 'S', 'e', 'c', 'o', 'n', 'd', 's');
  333. tmp = tmp.Trim();
  334. tmp = tmp.TrimStart('(');
  335. tmp = tmp.TrimEnd(')');
  336. string[] arr = tmp.Split(',');
  337. return string.Format(template, arr[0].Trim(), arr[1].Trim());
  338. }
  339. private string ReplaceStatusContinued(string exp)
  340. {
  341. if (!exp.Contains("StatusContinued"))
  342. return exp;
  343. string regex = @"StatusContinued\(\w+,\s*\d+\)";
  344. MatchCollection coll = Regex.Matches(exp, regex);
  345. foreach (Match item in coll)
  346. {
  347. string rplStr = ConvertStatusContinued(item.Value);
  348. exp = exp.Replace(item.Value, rplStr);
  349. }
  350. return exp;
  351. }
  352. private string ConvertStatusContinued(string sc)
  353. {
  354. string template = "StatusContinued(\"STR{0}\",{1},objectId,objectType)";
  355. string tmp = sc.Trim();
  356. tmp = tmp.TrimStart('S', 't', 'a', 't', 'u', 's', 'C', 'o', 'n', 't', 'i', 'n', 'u', 'e', 'd');
  357. tmp = tmp.Trim();
  358. tmp = tmp.TrimStart('(');
  359. tmp = tmp.TrimEnd(')');
  360. string[] arr = tmp.Split(',');
  361. return string.Format(template, arr[0].Trim(), arr[1].Trim());
  362. }
  363. private string ReplaceSuddenChange(string exp)
  364. {
  365. if (!exp.Contains("SuddenChange"))
  366. return exp;
  367. string regex = @"SuddenChange\(\w+,\s*\d+,\s*\d+(\.\d+)?\)";
  368. MatchCollection coll = Regex.Matches(exp, regex);
  369. foreach (Match item in coll)
  370. {
  371. string rplStr = ConvertSuddenChange(item.Value);
  372. exp = exp.Replace(item.Value, rplStr);
  373. }
  374. return exp;
  375. }
  376. private string ConvertSuddenChange(string sc)
  377. {
  378. string template = "SuddenChange(\"STR{0}\",{1},{2},objectId,objectType)";
  379. string tmp = sc.Trim();
  380. tmp = tmp.TrimStart('S', 'u', 'd', 'd', 'e', 'n', 'C', 'h', 'a', 'n', 'g','e');
  381. tmp = tmp.Trim();
  382. tmp = tmp.TrimStart('(');
  383. tmp = tmp.TrimEnd(')');
  384. string[] arr = tmp.Split(',');
  385. return string.Format(template, arr[0].Trim(), arr[1].Trim(), arr[2].Trim());
  386. }
  387. private string ReplaceLastUpdateTime(string exp)
  388. {
  389. if (!exp.Contains("LastUpdateTime"))
  390. return exp;
  391. string regex = @"LastUpdateTime\(\w+\)";
  392. MatchCollection coll = Regex.Matches(exp, regex);
  393. foreach (Match item in coll)
  394. {
  395. string rplStr = ConvertLastUpdateTime(item.Value);
  396. exp = exp.Replace(item.Value, rplStr);
  397. }
  398. return exp;
  399. }
  400. private string ConvertLastUpdateTime(string sc)
  401. {
  402. string template = "LastUpdateTime(\"STR{0}\",objectId,objectType)";
  403. string tmp = sc.Trim();
  404. tmp = tmp.TrimStart('L', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'T', 'i', 'm', 'e');
  405. tmp = tmp.Trim();
  406. tmp = tmp.TrimStart('(');
  407. tmp = tmp.TrimEnd(')');
  408. return string.Format(template, tmp.Trim());
  409. }
  410. }
  411. }