internal GenericUnaryMathFunctionOperator(string functionName, ExpTreeNode parent) : base(parent) { functionName = $"{functionName.Substring(0, 1).ToUpper()}{functionName.Substring(1).ToLower()}"; FunctionName = functionName; var method = typeof(Math).GetMethod(functionName, BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(double) }, null); if (method == null) { throw new InvalidOperationException($"Invalid function name '{functionName}'"); } MathFunc = (Func <double, double>)method.CreateDelegate(typeof(Func <double, double>)); }
/// <summary> /// 获取树结点值 /// </summary> /// <param name="tree">二叉树节点</param> /// <param name="builtInFunctionsWrapper">包含内置函数的实现类</param> /// <param name="callerContext">调用者上下文</param> /// <param name="optimize">最优化选项</param> /// <returns>树结点值</returns> public object GetValue(ExpTreeNode tree, object builtInFunctionsWrapper, object callerContext, bool optimize) { object result = null; if (tree != null) { CalculateContext calcContext = new CalculateContext(); calcContext.Optimize = optimize; calcContext.CallerContxt = callerContext; calcContext.BuiltInFunctionsWrapper = builtInFunctionsWrapper; result = VExp(tree, calcContext); } return result; }
/// <summary> /// 获取树结点值 /// </summary> /// <param name="tree">二叉树节点</param> /// <param name="calcUDF">用户自定义函数的委托</param> /// <param name="callerContext">调用者上下文</param> /// <param name="optimize">最优化选项</param> /// <returns>树结点值</returns> public object GetValue(ExpTreeNode tree, CalculateUserFunction calcUDF, object callerContext, bool optimize) { object result = null; if (tree != null) { CalculateContext calcContext = new CalculateContext(); calcContext.Optimize = optimize; calcContext.CallerContxt = callerContext; calcContext.CalculateUserFunction = calcUDF; result = VExp(tree, calcContext); } return result; }
private object DoIIFFunction(ExpTreeNode funcNode, IReadOnlyList<ExpTreeNode> arrParams, CalculateContext calcContext) { if (arrParams.Count != 3) throw ParsingException.NewParsingException(ParseError.peInvalidParam, funcNode.Position, funcNode.FunctionName, "3"); object result = false; if (arrParams.Count > 0) { object sourceData = this.VExp(arrParams[0], calcContext); if (sourceData != null) { bool sourceCondition = (bool)DataConverter.ChangeType(sourceData, typeof(bool)); if (sourceCondition) result = this.VExp(arrParams[1], calcContext); else result = this.VExp(arrParams[2], calcContext); } } return result; }
private object CalculateFunction(ExpTreeNode funcNode, List<ExpTreeNode> arrParams, CalculateContext calcContext) { object oValue = null; switch (funcNode.FunctionName.ToLower()) { case "in": oValue = this.DoInFunction(funcNode, arrParams, calcContext); break; case "iif": oValue = this.DoIIFFunction(funcNode, arrParams, calcContext); break; } return oValue; }
internal TypeConversionOperator(TypeCode tCode, ExpTreeNode parent) : base(parent) { TargetType = tCode; }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree"></param> /// <param name="builtInFunctionsWrapper">包含内置函数的实现类</param> /// <param name="callerContext">调用者上下文</param> /// <param name="optimize">最优化选项</param> /// <returns>树结点值</returns> public static object GetTreeValue(ExpTreeNode tree, object builtInFunctionsWrapper, object callerContext, bool optimize) { return ExpTreeExecutor.Instance.GetValue(tree, builtInFunctionsWrapper, callerContext, optimize); }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree">解析生成的二叉树</param> /// <param name="calculateUserFunction">用户自定义函数的实现</param> /// <param name="callerContext">自定义函数上下文</param> /// <returns>运算结果</returns> /// <remarks> /// 对含自定义函数的表达式进行解析后生成的二叉树,调用该函数进行运算得出结果值 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="parse" lang="cs" title="对解析生成的二叉树进行计算" /> /// </remarks> public static object GetTreeValue(ExpTreeNode tree, CalculateUserFunction calculateUserFunction, object callerContext) { return GetTreeValue(tree, calculateUserFunction, callerContext, true); }
private static ExpTreeNode NewTreeNode(ParsingContext context, ExpTreeNode left, ExpTreeNode right, Operation_IDs oID, int nPosition) { ExpTreeNode node = NewTreeNode(context, left, right, oID); node.Position = nPosition; return node; }
/// <summary> /// 生成一个新的二叉树节点 /// </summary> /// <param name="context">运行上下文</param> /// <param name="left">左子树</param> /// <param name="right">右子树</param> /// <param name="oID">操作类型</param> /// <returns></returns> private static ExpTreeNode NewTreeNode(ParsingContext context, ExpTreeNode left, ExpTreeNode right, Operation_IDs oID) { ExpTreeNode node = NewTreeNode(context); node.Left = left; node.Right = right; node.OperationID = oID; return node; }
/// <summary> /// 生成一个新的二叉树节点 /// </summary> private static ExpTreeNode NewTreeNode(ParsingContext context) { ExpTreeNode node = new ExpTreeNode(); node.Position = context.Position; return node; }
internal MatchOperator(ExpTreeNode parent) : base(parent) { // }
internal LooseNotEqualsOperator(ExpTreeNode parent) : base(parent) { // }
internal NotEqualsOperator(ExpTreeNode parent) : base(parent) // != { // }
internal GreaterThanOrEqualOperator(ExpTreeNode parent) : base(parent) { // }
internal OperatorBase(ExpTreeNode parent) : base(parent) { }
internal LessThanOrEqualOperator(ExpTreeNode parent) : base(parent) { // }
internal TplEval(ExpTreeNode expression) { _evaluation = expression; }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree"></param> /// <param name="calculateUserFunction">用户自定义函数的实现</param> /// <param name="callerContext"></param> /// <param name="optimize">是否进行bool运算优化,缺省为true</param> /// <returns></returns> /// <remarks> /// 对含自定义函数的表达式进行解析后生成的二叉树,调用该函数进行运算得出结果值 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="parse" lang="cs" title="对解析生成的二叉树进行计算" /> /// </remarks> public static object GetTreeValue(ExpTreeNode tree, CalculateUserFunction calculateUserFunction, object callerContext, bool optimize) { return ExpTreeExecutor.Instance.GetValue(tree, calculateUserFunction, callerContext, optimize); }
internal AdditionOperator(ExpTreeNode parent) : base(parent) { // }
internal TypeOperator(ExpTreeNode parent) : base(parent) { // }
internal DivisionOperator(ExpTreeNode parent) : base(parent) { // }
internal NotOperator(ExpTreeNode parent) : base(parent) { // }
internal ModulusOperator(ExpTreeNode parent) : base(parent) { // }
internal LengthOperator(ExpTreeNode parent) : base(parent) { // }
internal PowerOperator(ExpTreeNode parent) : base(parent) { // }
private object DoInFunction(ExpTreeNode funcNode, IReadOnlyList<ExpTreeNode> arrParams, CalculateContext calcContext) { bool result = false; if (arrParams.Count > 0) { object sourceData = this.VExp(arrParams[0], calcContext); if (sourceData != null) { for (int i = 1; i < arrParams.Count; i++) { object itemValue = this.VExp(arrParams[i], calcContext); if (itemValue != null) { if ((bool)CompareEqualOP(sourceData, itemValue, 0)) { result = true; break; } } } } } return result; }
internal SubtractionOperator(ExpTreeNode parent) : base(parent) { // }
internal MultiplacationOperator(ExpTreeNode parent) : base(parent) { // }
internal TplWhere(ExpTreeNode condition) { _condition = condition; }
private object VExp(ExpTreeNode node, CalculateContext calcContext) { object oValue = null; if (node != null) { try { switch (node.OperationID) { case Operation_IDs.OI_NUMBER: case Operation_IDs.OI_STRING: case Operation_IDs.OI_NEG: case Operation_IDs.OI_BOOLEAN: case Operation_IDs.OI_DATETIME: oValue = node.Value; break; case Operation_IDs.OI_ADD: oValue = AddOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_MINUS: { object p1 = VExp(node.Left, calcContext); object p2 = VExp(node.Right, calcContext); CheckOperandNull(p1, p2, node.Position); oValue = NToD(p1) - NToD(p2); } break; case Operation_IDs.OI_MUL: { object p1 = VExp(node.Left, calcContext); object p2 = VExp(node.Right, calcContext); CheckOperandNull(p1, p2, node.Position); oValue = NToD(p1) * NToD(p2); } break; case Operation_IDs.OI_DIV: { object p1 = VExp(node.Left, calcContext); object p2 = VExp(node.Right, calcContext); CheckOperandNull(p1, p2, node.Position); if (NToD(p2) == 0.0M) { throw ParsingException.NewParsingException(ParseError.peFloatOverflow, node.Position); } oValue = NToD(p1) / NToD(p2); } break; case Operation_IDs.OI_LOGICAL_OR: { oValue = (bool)VExp(node.Left, calcContext); object oRight = (bool)false; if ((bool)oValue == false) oRight = VExp(node.Right, calcContext); CheckOperandNull(oValue, oRight, node.Position); oValue = (bool)oValue || (bool)oRight; } break; case Operation_IDs.OI_LOGICAL_AND: { oValue = (bool)VExp(node.Left, calcContext); object oRight = (bool)true; if ((bool)oValue == true) oRight = VExp(node.Right, calcContext); CheckOperandNull(oValue, oRight, node.Position); oValue = (bool)oValue && (bool)oRight; } break; case Operation_IDs.OI_NOT: oValue = VExp(node.Right, calcContext); CheckOperandNull(oValue, node.Position); oValue = !(bool)oValue; break; case Operation_IDs.OI_GREAT: oValue = CompareGreatOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_GREATEQUAL: oValue = CompareGreatEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_LESS: oValue = CompareLessOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_LESSEQUAL: oValue = CompareLessEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_NOT_EQUAL: oValue = CompareNotEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_EQUAL: oValue = CompareEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position); break; case Operation_IDs.OI_USERDEFINE: { oValue = CalculateFunction(node, node.Params, calcContext); if (oValue == null) { ParamObjectCollection funcParams = GetParams(node.Params, calcContext); oValue = CalculateFunctionWithParameters(node.FunctionName, funcParams, calcContext); if (oValue == null) oValue = calcContext.GetUserFunctionValue(node.FunctionName, funcParams); if (oValue == null) oValue = CalculateExpressionDictionary(node.FunctionName, funcParams, calcContext); } } break; default: throw ParsingException.NewParsingException( ParseError.peInvalidOperator, node.Position, EnumItemDescriptionAttribute.GetAttribute(node.OperationID).ShortName); } } catch (System.InvalidCastException) { throw ParsingException.NewParsingException(ParseError.peTypeMismatch, node.Position); } } return oValue; }
/// <summary> /// 根据语法解析完的Tree,计算出结果 /// </summary> /// <param name="tree">语法解析树</param> /// <returns>结果返回值</returns> /// <remarks> /// 计算解析出的二叉树,得到运算结果 /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="getreevalue" lang="cs" title="对解析生成的二叉树进行计算" /> /// </remarks> public static object GetTreeValue(ExpTreeNode tree) { return GetTreeValue(tree, null, null, true); }
private static ExpTreeNode GetAsExpressionTree(this ParseTreeNode parsedNode, ExpTreeNode parentExpNode) { //The current node is a variable / value token. Create a value node and return it back if (!parsedNode.ChildNodes.Any()) { switch (parsedNode.Term.Name) { case "variable": { var varName = parsedNode.FindTokenAndGetValue <string>(); return(new VariableValue(varName, parentExpNode)); } case "boolean": return(new LiteralValue(parsedNode.FindTokenAndGetValue <bool>(), parentExpNode)); case "integer": case "decimal": return(new LiteralValue(parsedNode.FindTokenAndGetValue <double>(), parentExpNode)); case "SingleQuoteString": case "DoubleQuoteString": return(new LiteralValue(parsedNode.FindTokenAndGetValue <string>(), parentExpNode)); default: throw parsedNode.GetException($"Invalid token type '{parsedNode.Term.Name}' in expression"); } } // Look on the next node down else if (parsedNode.ChildNodes.Count == 1) { return(GetAsExpressionTree(parsedNode.ChildNodes[0], parentExpNode)); } //Ignore parenthesis, the middle non-terminal is what we want // Look on the next node down else if (parsedNode.ChildNodes.Count == 3 && parsedNode.ChildNodes[0]?.Token?.Text == "(") { return(GetAsExpressionTree(parsedNode.ChildNodes[1], parentExpNode)); } //Binary operator else if (parsedNode.ChildNodes.Count == 3) { BinaryOperatorBase binaryOp; var opStr = parsedNode.ChildNodes[1].FindToken().ValueString; switch (opStr) { // Math case "+": binaryOp = new AdditionOperator(parentExpNode); break; case "-": binaryOp = new SubtractionOperator(parentExpNode); break; case "*": binaryOp = new MultiplacationOperator(parentExpNode); break; case "/": binaryOp = new DivisionOperator(parentExpNode); break; case "%": binaryOp = new ModulusOperator(parentExpNode); break; case "^": binaryOp = new PowerOperator(parentExpNode); break; // Bool case "~==": binaryOp = new LooseEqualsOperator(parentExpNode); break; case "~!=": binaryOp = new LooseNotEqualsOperator(parentExpNode); break; case "==": binaryOp = new EqualsOperator(parentExpNode); break; case "!=": binaryOp = new NotEqualsOperator(parentExpNode); break; case "like": binaryOp = new LikeOperator(parentExpNode); break; case "match": binaryOp = new MatchOperator(parentExpNode); break; case ">": binaryOp = new GreaterThanOperator(parentExpNode); break; case ">=": binaryOp = new GreaterThanOrEqualOperator(parentExpNode); break; case "<": binaryOp = new LessThanOperator(parentExpNode); break; case "<=": binaryOp = new LessThanOrEqualOperator(parentExpNode); break; case "&&": binaryOp = new AndOperator(parentExpNode); break; case "||": binaryOp = new OrOperator(parentExpNode); break; default: throw parsedNode.ChildNodes[1].GetException($"Unrecognized operator '{opStr}'"); } binaryOp.LeftOperand = GetAsExpressionTree(parsedNode.ChildNodes[0], binaryOp); binaryOp.RightOperand = GetAsExpressionTree(parsedNode.ChildNodes[2], binaryOp); //Optimize if (binaryOp.LeftOperand is LiteralValue && binaryOp.RightOperand is LiteralValue) { return(new LiteralValue(binaryOp.Eval(), parentExpNode)); } return(binaryOp); } // Unary operator else if (parsedNode.ChildNodes.Count == 2) { var opVal = parsedNode.ChildNodes[0].FindToken().Value; UnaryOperatorBase unaryOp; if (parsedNode.ChildNodes[0].FindToken().Value is TypeCode convertType) { unaryOp = new TypeConversionOperator(convertType, parentExpNode); } else { var opStr = opVal.ToString(); switch (opStr) { case "!": unaryOp = new NotOperator(parentExpNode); break; //Property Checking case "lengthof": unaryOp = new LengthOperator(parentExpNode); break; case "typeof": unaryOp = new TypeOperator(parentExpNode); break; default: unaryOp = new GenericUnaryMathFunctionOperator(opStr, parentExpNode); break; } } unaryOp.Operand = GetAsExpressionTree(parsedNode.ChildNodes[1], unaryOp); //Optimize if (unaryOp.Operand is LiteralValue) { return(new LiteralValue(unaryOp.Eval(), parentExpNode)); } return(unaryOp); } else { throw parsedNode.GetException($"Invalid number of tokens ({parsedNode.ChildNodes.Count})"); } }
internal EqualsOperator(ExpTreeNode parent) : base(parent) // == { // }