Пример #1
0
        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>));
        }
Пример #2
0
        /// <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;
        }
Пример #3
0
        /// <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;
        }
Пример #4
0
        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;
        }
Пример #5
0
        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;
        }
Пример #6
0
 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);
 }
Пример #9
0
        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;
        }
Пример #10
0
        /// <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;
        }
Пример #11
0
        /// <summary>
        /// 生成一个新的二叉树节点
        /// </summary>
        private static ExpTreeNode NewTreeNode(ParsingContext context)
        {
            ExpTreeNode node = new ExpTreeNode();

            node.Position = context.Position;

            return node;
        }
Пример #12
0
 internal MatchOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #13
0
 internal LooseNotEqualsOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #14
0
 internal NotEqualsOperator(ExpTreeNode parent) : base(parent) // !=
 {
     //
 }
Пример #15
0
 internal GreaterThanOrEqualOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #16
0
 internal OperatorBase(ExpTreeNode parent) : base(parent)
 {
 }
Пример #17
0
 internal LessThanOrEqualOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #18
0
 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);
 }
Пример #20
0
 internal AdditionOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #21
0
 internal TypeOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #22
0
 internal DivisionOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #23
0
 internal NotOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #24
0
 internal ModulusOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #25
0
 internal LengthOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #26
0
 internal PowerOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #27
0
        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;
        }
Пример #28
0
 internal SubtractionOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #29
0
 internal MultiplacationOperator(ExpTreeNode parent) : base(parent)
 {
     //
 }
Пример #30
0
 internal TplWhere(ExpTreeNode condition)
 {
     _condition = condition;
 }
Пример #31
0
        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);
 }
Пример #33
0
        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})");
            }
        }
Пример #34
0
 internal EqualsOperator(ExpTreeNode parent) : base(parent) // ==
 {
     //
 }