FormulaConverter.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using FormulaEnginePoC.FormulaEngine.Mapping;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. namespace FormulaEnginePoC.FormulaEngine
  7. {
  8. internal static class FormulaConverter
  9. {
  10. private class ExpressTokenExtractor : ExpressionTokenSplitter
  11. {
  12. private readonly Token[] _tokens;
  13. public Token[] Tokens => _tokens.ToArray();
  14. public ExpressTokenExtractor(string expression) : base(expression)
  15. {
  16. var lst = new List<Token>();
  17. do
  18. {
  19. NextToken();
  20. lst.Add(CurrentToken);
  21. } while (CurrentToken.Id != TokenId.End);
  22. _tokens = lst.ToArray();
  23. }
  24. }
  25. private static readonly Dictionary<string, string> Operators;
  26. private static readonly Dictionary<string, string> Functions;
  27. public static string[] GetOperators() => Operators.Keys.ToArray();
  28. public static string[] GetFunctions() => Functions.Keys.ToArray();
  29. static FormulaConverter()
  30. {
  31. Operators = new Dictionary<string, string>
  32. {
  33. {"+", "+"}
  34. , {"-", "-"}
  35. , {"*", "*"}
  36. , {"/", "/"}
  37. , {"(", "("}
  38. , {")", ")"}
  39. , {"<", "<"}
  40. , {">", ">"}
  41. , {"<=", "<="}
  42. , {">=", ">="}
  43. , {"%", "%"}
  44. , {"如果", ""}
  45. , {"那么", "?"}
  46. , {"否则", ":"}
  47. , {"否则如果", ":"}
  48. , {"或者", "||"}
  49. , {"并且", "&&"}
  50. , {"取反", "!"}
  51. };
  52. Functions = new Dictionary<string, string>
  53. {
  54. {"ABS", $"{nameof(Math)}.{nameof(Math.Abs)}"}
  55. , {"CEIL", $"{nameof(Math)}.{nameof(Math.Ceiling)}"}
  56. , {"FLOOR", $"{nameof(Math)}.{nameof(Math.Floor)}"}
  57. , {"ROUND", $"{nameof(Math)}.{nameof(Math.Round)}"}
  58. , {"MOD", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Mod)}"}
  59. , {"STR", $"{nameof(MoreFunction)}.{nameof(MoreFunction.ToString)}"}
  60. , {"NUM", $"{nameof(MoreFunction)}.{nameof(MoreFunction.ToDouble)}"}
  61. , {"AVG", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Avg)}"}
  62. , {"SUM", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Sum)}"}
  63. , {"MAX", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Max)}"}
  64. , {"MIN", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Min)}"}
  65. , {"文本开头为", ".StartsWith"}
  66. , {"文本结束为", ".EndsWith"}
  67. , {"文本包含", ".Contains"}
  68. , {"文本截取", ".SubString"}
  69. };
  70. }
  71. public static string Convert(string friendInput, TypeMapping mapping, FormulaValueTypeConversion valueConversion = FormulaValueTypeConversion.ConvertToDouble)
  72. {
  73. var functions = new Dictionary<string, string>(Functions);
  74. if (valueConversion == FormulaValueTypeConversion.ConvertToDecimal)
  75. {
  76. functions["NUM"] = $"{nameof(MoreFunction)}.{nameof(MoreFunction.ToDecimal)}";
  77. }
  78. var numFunction = functions["NUM"];
  79. var code = new StringBuilder();
  80. var parser = new ExpressTokenExtractor(friendInput);
  81. foreach (var token in parser.Tokens)
  82. {
  83. code.Append(" ");
  84. if (token.Id == ExpressionTokenSplitter.TokenId.Identifier)
  85. {
  86. if (Operators.TryGetValue(token.Text, out var op))
  87. {
  88. code.Append(op);
  89. }
  90. else if (functions.TryGetValue(token.Text, out var func))
  91. {
  92. code.Append(func);
  93. }
  94. else if (mapping.TryGetProperty(token.Text, out var property))
  95. {
  96. if (valueConversion == FormulaValueTypeConversion.ConvertToDouble && property.DataType == typeof(decimal))
  97. {
  98. code.Append($"{numFunction} ( p.{property.Name} )");
  99. }
  100. else if (valueConversion == FormulaValueTypeConversion.ConvertToDecimal && (property.DataType == typeof(float) || property.DataType == typeof(double)))
  101. {
  102. code.Append($"{numFunction} ( p.{property.Name} )");
  103. }
  104. else
  105. {
  106. code.Append($"p.{property.Name}");
  107. }
  108. }
  109. else
  110. {
  111. code.Append(token.Text);
  112. }
  113. }
  114. else
  115. {
  116. //值类型转换
  117. if (token.Id == ExpressionTokenSplitter.TokenId.RealLiteral)
  118. {
  119. code.Append($"{numFunction} ( {token.Text} )");
  120. }
  121. else
  122. {
  123. code.Append(token.Text);
  124. }
  125. }
  126. }
  127. return code.ToString();
  128. }
  129. }
  130. }