using FormulaEnginePoC.FormulaEngine.Mapping; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FormulaEnginePoC.FormulaEngine { internal static class FormulaConverter { private class ExpressTokenExtractor : ExpressionTokenSplitter { private readonly Token[] _tokens; public Token[] Tokens => _tokens.ToArray(); public ExpressTokenExtractor(string expression) : base(expression) { var lst = new List(); do { NextToken(); lst.Add(CurrentToken); } while (CurrentToken.Id != TokenId.End); _tokens = lst.ToArray(); } } private static readonly Dictionary Operators; private static readonly Dictionary Functions; public static string[] GetOperators() => Operators.Keys.ToArray(); public static string[] GetFunctions() => Functions.Keys.ToArray(); static FormulaConverter() { Operators = new Dictionary { {"+", "+"} , {"-", "-"} , {"*", "*"} , {"/", "/"} , {"(", "("} , {")", ")"} , {"<", "<"} , {">", ">"} , {"<=", "<="} , {">=", ">="} , {"%", "%"} , {"如果", ""} , {"那么", "?"} , {"否则", ":"} , {"否则如果", ":"} , {"或者", "||"} , {"并且", "&&"} , {"取反", "!"} }; Functions = new Dictionary { {"ABS", $"{nameof(Math)}.{nameof(Math.Abs)}"} , {"CEIL", $"{nameof(Math)}.{nameof(Math.Ceiling)}"} , {"FLOOR", $"{nameof(Math)}.{nameof(Math.Floor)}"} , {"ROUND", $"{nameof(Math)}.{nameof(Math.Round)}"} , {"MOD", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Mod)}"} , {"STR", $"{nameof(MoreFunction)}.{nameof(MoreFunction.ToString)}"} , {"NUM", $"{nameof(MoreFunction)}.{nameof(MoreFunction.ToDouble)}"} , {"AVG", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Avg)}"} , {"SUM", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Sum)}"} , {"MAX", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Max)}"} , {"MIN", $"{nameof(MoreFunction)}.{nameof(MoreFunction.Min)}"} , {"文本开头为", ".StartsWith"} , {"文本结束为", ".EndsWith"} , {"文本包含", ".Contains"} , {"文本截取", ".SubString"} }; } public static string Convert(string friendInput, TypeMapping mapping, FormulaValueTypeConversion valueConversion = FormulaValueTypeConversion.ConvertToDouble) { var functions = new Dictionary(Functions); if (valueConversion == FormulaValueTypeConversion.ConvertToDecimal) { functions["NUM"] = $"{nameof(MoreFunction)}.{nameof(MoreFunction.ToDecimal)}"; } var numFunction = functions["NUM"]; var code = new StringBuilder(); var parser = new ExpressTokenExtractor(friendInput); foreach (var token in parser.Tokens) { code.Append(" "); if (token.Id == ExpressionTokenSplitter.TokenId.Identifier) { if (Operators.TryGetValue(token.Text, out var op)) { code.Append(op); } else if (functions.TryGetValue(token.Text, out var func)) { code.Append(func); } else if (mapping.TryGetProperty(token.Text, out var property)) { if (valueConversion == FormulaValueTypeConversion.ConvertToDouble && property.DataType == typeof(decimal)) { code.Append($"{numFunction} ( p.{property.Name} )"); } else if (valueConversion == FormulaValueTypeConversion.ConvertToDecimal && (property.DataType == typeof(float) || property.DataType == typeof(double))) { code.Append($"{numFunction} ( p.{property.Name} )"); } else { code.Append($"p.{property.Name}"); } } else { code.Append(token.Text); } } else { //值类型转换 if (token.Id == ExpressionTokenSplitter.TokenId.RealLiteral) { code.Append($"{numFunction} ( {token.Text} )"); } else { code.Append(token.Text); } } } return code.ToString(); } } }