EvalExpr.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. using System;
  2. using System.Collections;
  3. using System.Text.RegularExpressions;
  4. using IwbZero.ExprFunctions;
  5. using IwbZero.IwbBase;
  6. using IwbZero.ToolCommon.StringModel;
  7. namespace IwbZero.Expr
  8. {
  9. public class EvalExpr
  10. {
  11. // Fields
  12. private static IdCollection _functions;
  13. private static IdCollection _operators;
  14. private static Regex _RegexDate = new Regex("[0-9]{1,2}/[0-9]{1,2}/[0-9]{2,4}( [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}[ ]*(AM|PM)?)?", RegexOptions.IgnoreCase);
  15. private static Regex _RegexDateAdd = new Regex("[0-9]+(d|m|y)", RegexOptions.IgnoreCase);
  16. private static Regex _RegexDecimal = new Regex(@"-?[0-9]*\.[0-9]*", RegexOptions.IgnoreCase);
  17. private static Regex _RegexInt = new Regex("-?[0-9]+", RegexOptions.IgnoreCase);
  18. private static Regex _RegexVariable = new Regex("[_@a-zA-Z][_@a-zA-Z0-9.$]*", RegexOptions.IgnoreCase);
  19. // Methods
  20. public static string Evaluate(ExprObject exprObj)
  21. {
  22. string str = "";
  23. if (exprObj.ChildCount == 0)
  24. {
  25. return exprObj.Expr;
  26. }
  27. EvaluateAllChildren(exprObj);
  28. ExprObject expr = null;
  29. for (int i = 0; i < exprObj.ChildCount; i++)
  30. {
  31. ExprObject child = exprObj.GetChild(i);
  32. if (child.IsOperator)
  33. {
  34. var @operator = child.GetOperator();
  35. ExprObject expr3 = exprObj.GetChild(i + 1);
  36. if (expr3 != null)
  37. {
  38. expr = @operator.Calculate(expr, expr3);
  39. i++;
  40. }
  41. }
  42. else if (expr == null)
  43. {
  44. expr = child;
  45. }
  46. }
  47. if (expr != null) str = expr.Expr;
  48. return str;
  49. }
  50. public static string Evaluate(string exprStr)
  51. {
  52. string str = exprStr;
  53. try
  54. {
  55. ExprObject exprObj = new ExprObject(exprStr, ExprElements.Expression);
  56. if (Parse(exprObj, true))
  57. {
  58. str = Evaluate(exprObj);
  59. }
  60. }
  61. catch (Exception)
  62. {
  63. // ignored
  64. }
  65. return str;
  66. }
  67. public static string Evaluate(string exprStr, Hashtable variableValueDic)
  68. {
  69. var exprStr2 = TransVariable(exprStr, variableValueDic);
  70. var str = Evaluate(exprStr2);
  71. return str;
  72. }
  73. #region Methods
  74. public static ExprElements GetElementType(string expression)
  75. {
  76. ExprElements variable = ExprElements.Value;
  77. expression = expression.Trim();
  78. Match match = _RegexVariable.Match(expression);
  79. if (((match.Index == 0)) && (match.Length == expression.Length))
  80. {
  81. variable = ExprElements.Variable;
  82. }
  83. return variable;
  84. }
  85. public static ExprTypes GetExprTypes(string expression)
  86. {
  87. ExprTypes date = ExprTypes.String;
  88. expression = expression.Trim();
  89. if ((expression.UAndT() == "TRUE") || (expression.UAndT() == "FALSE"))
  90. {
  91. return ExprTypes.Bool;
  92. }
  93. Match match = _RegexVariable.Match(expression);
  94. if (((match.Index == 0)) && (match.Length == expression.Length))
  95. {
  96. return ExprTypes.Variable;
  97. }
  98. match = _RegexDecimal.Match(expression);
  99. if (((match.Index == 0)) && (match.Length == expression.Length))
  100. {
  101. return ExprTypes.Decimal;
  102. }
  103. match = _RegexInt.Match(expression);
  104. if (((match.Index == 0)) && (match.Length == expression.Length))
  105. {
  106. return ExprTypes.Integer;
  107. }
  108. match = _RegexDateAdd.Match(expression);
  109. if (((match.Index == 0)) && (match.Length == expression.Length))
  110. {
  111. return ExprTypes.DateAdd;
  112. }
  113. match = _RegexDate.Match(expression);
  114. if (((match.Index == 0)) && (match.Length == expression.Length))
  115. {
  116. date = ExprTypes.Date;
  117. }
  118. return date;
  119. }
  120. public static ExprTypes GetExprTypes(ExprObject exprObj)
  121. {
  122. ExprTypes @bool = ExprTypes.String;
  123. if (exprObj.ElementType != ExprElements.String)
  124. {
  125. string str = exprObj.Expr.Trim();
  126. if ((str.UAndT() == "TRUE") || (str.UAndT() == "FALSE"))
  127. {
  128. @bool = ExprTypes.Bool;
  129. str = "";
  130. }
  131. if (str == "")
  132. {
  133. return @bool;
  134. }
  135. Match match = _RegexDecimal.Match(str);
  136. if (((match.Index == 0)) && (match.Length == str.Length))
  137. {
  138. return ExprTypes.Decimal;
  139. }
  140. match = _RegexInt.Match(str);
  141. if (((match.Index == 0)) && (match.Length == str.Length))
  142. {
  143. return ExprTypes.Integer;
  144. }
  145. match = _RegexDateAdd.Match(str);
  146. if (((match.Index == 0)) && (match.Length == str.Length))
  147. {
  148. return ExprTypes.DateAdd;
  149. }
  150. match = _RegexDate.Match(str);
  151. if (((match.Index == 0)) && (match.Length == str.Length))
  152. {
  153. @bool = ExprTypes.Date;
  154. }
  155. }
  156. return @bool;
  157. }
  158. public static DateTime GetLastDayOfMonth(DateTime datetime)
  159. {
  160. int year = datetime.Year;
  161. int month = datetime.Month + 1;
  162. if (month > 12)
  163. {
  164. year++;
  165. month = 1;
  166. }
  167. int day = 1;
  168. return (new DateTime(year, month, day) - new TimeSpan(1, 0, 0, 0));
  169. }
  170. public static DateTime AddDays(DateTime datetime, string toAdd)
  171. {
  172. DateTime time = datetime;
  173. toAdd = toAdd.UAndT();
  174. int days = toAdd.ValI();
  175. if (toAdd.IndexOf("D", StringComparison.Ordinal) >= 0)
  176. {
  177. return (time + new TimeSpan(days, 0, 0, 0));
  178. }
  179. int year;
  180. int month = datetime.Month;
  181. int day = datetime.Day;
  182. if (toAdd.IndexOf("M", StringComparison.Ordinal) >= 0)
  183. {
  184. int num5 = ((datetime.Year * 12) + datetime.Month) + days;
  185. year = num5 / 12;
  186. month = num5 - (year * 12);
  187. }
  188. else
  189. {
  190. year = datetime.Year + days;
  191. }
  192. DateTime lastDayOfMonth = GetLastDayOfMonth(new DateTime(year, month, 1));
  193. if (lastDayOfMonth.Day < day)
  194. {
  195. day = lastDayOfMonth.Day;
  196. }
  197. return new DateTime(year, month, day, datetime.Hour, datetime.Minute, datetime.Second, datetime.Millisecond);
  198. }
  199. public static string TransVariable(string exprStr, Hashtable variableValueDic)
  200. {
  201. string str = exprStr;
  202. var variables = GetVariablesInString(exprStr);
  203. if (variables != null)
  204. {
  205. foreach (string v in variables)
  206. {
  207. var value = GetVariableValue(v, variableValueDic);
  208. if (value != null)
  209. {
  210. str = str.Replace(v, value);
  211. }
  212. }
  213. }
  214. return str;
  215. }
  216. public static string TransGlobalVariable(string exprStr, Hashtable variableValueDic)
  217. {
  218. string str = exprStr;
  219. var variables = GetVariablesInString(exprStr);
  220. if (variables != null)
  221. {
  222. foreach (string v in variables)
  223. {
  224. var value = GetVariableValue(v, variableValueDic);
  225. str = str.Replace(v, value);
  226. }
  227. }
  228. return str;
  229. }
  230. private static void EvaluateAllChildren(ExprObject exprObj)
  231. {
  232. if (exprObj != null)
  233. {
  234. for (int i = 0; i < exprObj.ChildCount; i++)
  235. {
  236. ExprObject child = exprObj.GetChild(i);
  237. EvaluateAllChildren(child);
  238. if (child != null)
  239. {
  240. string str = null;
  241. switch (child.ElementType)
  242. {
  243. case ExprElements.Function:
  244. str = EvaluateFunction(child);
  245. break;
  246. case ExprElements.Variable:
  247. //str = TransSessionVariables(child.Expr);
  248. break;
  249. case ExprElements.Expression:
  250. str = Evaluate(child);
  251. break;
  252. }
  253. if (str != null)
  254. {
  255. child.Expr = str;
  256. child.ElementType = ExprElements.Value;
  257. }
  258. }
  259. }
  260. }
  261. }
  262. public static string EvaluateFunction(ExprObject exprObj)
  263. {
  264. string str = "";
  265. string functionId = exprObj.Expr.UAndT();
  266. if (_functions == null)
  267. {
  268. _functions = new IdCollection();
  269. }
  270. IwbFunction function = (IwbFunction)_functions[functionId];
  271. if (function == null)
  272. {
  273. function = IwbFunction.LoadById(functionId);
  274. if (function != null)
  275. {
  276. _functions.Add(function);
  277. }
  278. }
  279. if (function != null)
  280. {
  281. str = function.InvokeFunction(exprObj);
  282. }
  283. return str;
  284. }
  285. private static bool IsStartingParent(char pcChar)
  286. {
  287. return (pcChar == '(');
  288. }
  289. private static bool IsStartingQuote(char pcChar)
  290. {
  291. if (pcChar != '"')
  292. {
  293. return (pcChar == '\'');
  294. }
  295. return true;
  296. }
  297. private static int GetStaticString(string pcString, char pcQuote)
  298. {
  299. int length = pcString.Length;
  300. for (int i = 0; i < length; i++)
  301. {
  302. char ch = pcString[i];
  303. if (ch == pcQuote)
  304. {
  305. return i;
  306. }
  307. if ((ch == '\\') && (i < (length - 1)))
  308. {
  309. switch (pcString[i + 1])
  310. {
  311. case '"':
  312. case '\'':
  313. i++;
  314. break;
  315. }
  316. }
  317. }
  318. return -1;
  319. }
  320. private static int GetClosingParenthesis(string pcString)
  321. {
  322. int num = -1;
  323. int length = pcString.Length;
  324. int num3 = 0;
  325. for (int i = 0; i < length; i++)
  326. {
  327. char pcQuote = pcString[i];
  328. if (((pcQuote == '"') || (pcQuote == '\'')) && (i < (length - 1)))
  329. {
  330. int staticString = GetStaticString(pcString.Substring(i + 1), pcQuote);
  331. if (staticString >= 0)
  332. {
  333. i += staticString + 1;
  334. }
  335. }
  336. if (pcQuote == '(')
  337. {
  338. num3++;
  339. }
  340. else if (pcQuote == ')')
  341. {
  342. if (num3 == 0)
  343. {
  344. num = i;
  345. }
  346. else
  347. {
  348. num3--;
  349. }
  350. }
  351. }
  352. return num;
  353. }
  354. #endregion
  355. #region 变量赋值
  356. public static ArrayList GetVariablesInString(string pcString)
  357. {
  358. var arr1 = GetStringVariables(pcString) ?? new ArrayList();
  359. var arr2 = GetStringVariables(pcString, IwbVariableType.Global) ?? new ArrayList();
  360. arr1.AddRange(arr2);
  361. return arr1;
  362. }
  363. public static ArrayList GetStringVariables(string pcString, string variableHeader = IwbVariableType.Local)
  364. {
  365. int index;
  366. ArrayList poArrayList = new ArrayList();
  367. for (int i = pcString.IndexOf(variableHeader, StringComparison.Ordinal); i >= 0; i = pcString.IndexOf(variableHeader, index, StringComparison.Ordinal))
  368. {
  369. string pcName = variableHeader;
  370. for (index = i + variableHeader.Length; index < pcString.Length; index++)
  371. {
  372. char ch = pcString[index];
  373. if ((((ch < 'a') || (ch > 'z')) && ((ch < 'A') || (ch > 'Z'))) && (((ch < '0') || (ch > '9')) && (ch != '_')))
  374. {
  375. break;
  376. }
  377. pcName = pcName + ch;
  378. }
  379. poArrayList.InsertIdentifier(pcName);
  380. }
  381. return poArrayList;
  382. }
  383. public static string GetVariableValue(string pcVariable, Hashtable variableValueDic)
  384. {
  385. var key = pcVariable.UAndT();
  386. foreach (DictionaryEntry dic in variableValueDic)
  387. {
  388. if (dic.Key.UAndT() == key)
  389. {
  390. return ((IwbRtVariable)dic.Value).GetStringValue();
  391. }
  392. }
  393. return null;
  394. }
  395. #endregion 变量赋值
  396. #region 表达式转换为ExprObject
  397. public static bool Parse(ExprObject exprObj, bool plThrowException)
  398. {
  399. bool flag = true;
  400. try
  401. {
  402. Parse(exprObj);
  403. }
  404. catch (Exception)
  405. {
  406. if (plThrowException)
  407. {
  408. throw;
  409. }
  410. flag = false;
  411. }
  412. return flag;
  413. }
  414. private static void Parse(ExprObject exprObj, string pcExpression = null)
  415. {
  416. pcExpression = (pcExpression ?? exprObj.Expr)?.Trim() ?? "";
  417. switch (GetExprTypes(pcExpression))
  418. {
  419. case ExprTypes.Integer:
  420. case ExprTypes.Decimal:
  421. case ExprTypes.Date:
  422. case ExprTypes.Bool:
  423. exprObj.AddChild(new ExprObject(pcExpression, ExprElements.Value));
  424. return;
  425. case ExprTypes.Variable:
  426. exprObj.AddChild(new ExprObject(pcExpression, ExprElements.Variable));
  427. return;
  428. }
  429. ExprObject exprObject = null;
  430. string str = "";
  431. while (pcExpression != "")
  432. {
  433. var poNode = GetNextElement(ref pcExpression);
  434. if (poNode != null)
  435. {
  436. if (((poNode.ElementType != ExprElements.String) && (poNode.Expr == "-")) && ((exprObject == null) || exprObject.IsOperator))
  437. {
  438. str = "-";
  439. }
  440. else
  441. {
  442. poNode.Expr = str + poNode.Expr;
  443. exprObj.AddChild(poNode);
  444. str = "";
  445. }
  446. exprObject = poNode;
  447. }
  448. }
  449. CollapseSyntaxTree(exprObj);
  450. }
  451. private static ExprObject GetNextElement(ref string pcString)
  452. {
  453. ExprObject exprObj = null;
  454. string pcExpr = "";
  455. bool flag = false;
  456. int length = pcString.Length;
  457. for (int i = 0; i < length; i++)
  458. {
  459. char pcChar = pcString[i];
  460. string str2 = "";
  461. if (i < (length - 1))
  462. {
  463. str2 = pcString.Substring(i + 1);
  464. }
  465. int closingParenthesis;
  466. if (IsStartingParent(pcChar))
  467. {
  468. closingParenthesis = GetClosingParenthesis(str2);
  469. if (closingParenthesis < 0)
  470. {
  471. throw new Exception("No ending parenthesis.");
  472. }
  473. if (pcExpr != "")
  474. {
  475. string pcExpression = pcString.Substring(i + 1, closingParenthesis);
  476. exprObj = new ExprObject(pcExpr, ExprElements.Function);
  477. if (pcExpression != "")
  478. {
  479. Parse(exprObj, pcExpression);
  480. CollapseFunctionCall(exprObj);
  481. }
  482. }
  483. else
  484. {
  485. exprObj = new ExprObject(pcString.Substring(i + 1, closingParenthesis), ExprElements.Expression);
  486. Parse(exprObj, exprObj.Expr);
  487. }
  488. i = (i + closingParenthesis) + 2;
  489. flag = true;
  490. }
  491. else if (IsStartingQuote(pcChar))
  492. {
  493. if (pcExpr != "")
  494. {
  495. throw new Exception("Operand required.");
  496. }
  497. closingParenthesis = GetStaticString(str2, pcChar);
  498. if (closingParenthesis < 0)
  499. {
  500. throw new Exception("No ending quote.");
  501. }
  502. exprObj = new ExprObject(pcString.Substring(i + 1, closingParenthesis), ExprElements.String);
  503. i = (i + closingParenthesis) + 2;
  504. flag = true;
  505. }
  506. else
  507. {
  508. ExprOperator @operator = GetOperator(pcString.Substring(i));
  509. bool flag2 = true;
  510. if (i == (length - 1))
  511. {
  512. pcString = "";
  513. }
  514. if (((@operator != null) && (pcExpr != "")) && (GetExprTypes(pcExpr) == ExprTypes.String))
  515. {
  516. @operator = null;
  517. }
  518. if (@operator != null)
  519. {
  520. if (pcExpr == "")
  521. {
  522. exprObj = new ExprObject(@operator.Id, ExprElements.Operator);
  523. i += @operator.Symbol.Length;
  524. }
  525. flag = true;
  526. flag2 = false;
  527. }
  528. else if ((pcExpr == "") && (pcChar == ' '))
  529. {
  530. flag2 = false;
  531. }
  532. if (flag2)
  533. {
  534. pcExpr = pcExpr + pcChar.ToString();
  535. }
  536. if ((pcExpr != "") && ((@operator != null) || (i == (length - 1))))
  537. {
  538. ExprElements elementType = GetElementType(pcExpr);
  539. exprObj = new ExprObject(pcExpr, elementType);
  540. flag = true;
  541. }
  542. }
  543. if (flag)
  544. {
  545. if (i < pcString.Length)
  546. {
  547. pcString = pcString.Substring(i);
  548. return exprObj;
  549. }
  550. pcString = "";
  551. return exprObj;
  552. }
  553. }
  554. return null;
  555. }
  556. private static ExprOperator GetOperator(string pcString)
  557. {
  558. foreach (ExprOperator operator2 in Operators)
  559. {
  560. if (operator2.IsSymbolMatched(pcString))
  561. {
  562. return operator2;
  563. }
  564. }
  565. return null;
  566. }
  567. /// <summary>
  568. /// 构建表达式树
  569. /// </summary>
  570. /// <param name="poExprObject"></param>
  571. private static void CollapseSyntaxTree(ExprObject poExprObject)
  572. {
  573. int level = -1;
  574. int piStart = -1;
  575. int piLevel = 100;
  576. for (int i = 0; i < poExprObject.ChildCount; i++)
  577. {
  578. ExprOperator @operator = poExprObject.GetChild(i).GetOperator();
  579. if (i == (poExprObject.ChildCount - 1))
  580. {
  581. @operator = new ExprOperator("", "", piLevel, 0);
  582. i++;
  583. }
  584. if (@operator != null)
  585. {
  586. if (piLevel > @operator.Level)
  587. {
  588. piLevel = @operator.Level;
  589. }
  590. if (@operator.Level > level)
  591. {
  592. piStart = i - @operator.LeftOperands;
  593. }
  594. else if (@operator.Level < level)
  595. {
  596. CollapseSyntaxTree(poExprObject, piStart, i - 1);
  597. CollapseSyntaxTree(poExprObject);
  598. }
  599. level = @operator.Level;
  600. }
  601. }
  602. }
  603. /// <summary>
  604. /// 构建表达式树
  605. /// </summary>
  606. /// <param name="poExprObject"></param>
  607. /// <param name="piStart"></param>
  608. /// <param name="piEnd"></param>
  609. private static void CollapseSyntaxTree(ExprObject poExprObject, int piStart, int piEnd)
  610. {
  611. if (piEnd > piStart)
  612. {
  613. ExprObject poNode = new ExprObject("", ExprElements.Expression);
  614. for (int i = piStart; i <= piEnd; i++)
  615. {
  616. ExprObject child = poExprObject.GetChild(piStart);
  617. poExprObject.RemoveChildAt(piStart);
  618. poNode.AddChild(child);
  619. poNode.Expr = poNode.Expr + " " + child.Expr;
  620. }
  621. poExprObject.InsertChildAt(poNode, piStart);
  622. }
  623. }
  624. private static void CollapseFunctionCall(ExprObject poExprObject)
  625. {
  626. if (poExprObject.ChildCount > 1)
  627. {
  628. bool flag = false;
  629. foreach (ExprObject expr in poExprObject.ChildNodes)
  630. {
  631. if (expr.IsOperator && (expr.Expr.Trim() == ","))
  632. {
  633. flag = true;
  634. break;
  635. }
  636. }
  637. if (!flag)
  638. {
  639. ExprObject poNode = new ExprObject(poExprObject.Expr, ExprElements.Expression);
  640. foreach (ExprObject expr3 in poExprObject.ChildNodes)
  641. {
  642. poNode.AddChild(expr3);
  643. }
  644. poExprObject.ChildNodes.Clear();
  645. poExprObject.AddChild(poNode);
  646. }
  647. }
  648. }
  649. public static IdCollection Operators =>
  650. _operators ?? (_operators = new IdCollection
  651. {
  652. new ExprOperator("+", "+", 4, 1),
  653. new ExprOperator("-", "-", 4, 1),
  654. new ExprOperator(",", ",", 0, 0),
  655. new ExprOperator("and", " and ", 1, 1),
  656. new ExprOperator("&&", " && ", 1, 1),
  657. new ExprOperator("or", " or ", 1, 1),
  658. new ExprOperator("||", " || ", 1, 1),
  659. new ExprOperator("not", "not ", 2, 0),
  660. new ExprOperator("!", "! ", 2, 0),
  661. new ExprOperator("!=", "!=", 3, 1),
  662. new ExprOperator("=", "=", 3, 1),
  663. new ExprOperator(">=", ">=", 3, 1),
  664. new ExprOperator(">", ">", 3, 1),
  665. new ExprOperator("<=", "<=", 3, 1),
  666. new ExprOperator("<", "<", 3, 1),
  667. new ExprOperator("like", " like ", 3, 1),
  668. new ExprOperator("*", "*", 5, 1),
  669. new ExprOperator("/", "/", 5, 1),
  670. new ExprOperator("%", "%", 5, 1)
  671. });
  672. #endregion 表达式转换为ExprObject
  673. }
  674. }