Пример #1
0
 private static void CheckOperandNull(object p1, object p2, int nPos)
 {
     if (p1 == null || p2 == null)
     {
         throw ParsingException.NewParsingException(ParseError.peNeedOperand, nPos);
     }
 }
        /// <summary>
        /// 分析表达式,
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns>分析结果</returns>
        /// <remarks>
        /// 对传入的表达式进行分析
        /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="parse" lang="cs" title="调用分析表达式的函数" />
        /// </remarks>
        public static ParseResult Parse(string expression)
        {
            ParseResult result = null;

            if (string.IsNullOrEmpty(expression) == false)
            {
                ParsingContext context = new ParsingContext(expression);

                context.OutputIdentifiers = true;
                ExpTreeNode tree = ExpressionParser.instance.DoExpression(context);

                if (context.CurrentChar != '\0')
                {
                    throw ParsingException.NewParsingException(ParseError.peInvalidOperator, context.Position, context.CurrentChar.ToString());
                }

                result = new ParseResult(tree, context.Identifiers);
            }
            else
            {
                result = new ParseResult(null, null);
            }

            return(result);
        }
Пример #3
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);
        }
Пример #4
0
        /// <summary>
        /// 处理各种系数、负数、括号等
        /// </summary>
        /// <returns></returns>
        private ExpTreeNode DoFactor(ParsingContext context)
        {
            SkipSpaces(context);

            ExpTreeNode node = null;

            char ch = context.CurrentChar;

            int nPos = context.Position;

            switch (ch)
            {
            case '-':       //处理负号
                OutputID(context, Operation_IDs.OI_NEG, "-", context.Position);

                context.Position++;

                ExpTreeNode node2 = DoExpression(context);

                ExpTreeNode left = NewTreeNode(context);
                left.OperationID = Operation_IDs.OI_NEG;
                left.Value       = (decimal) - 1;
                left.Position    = nPos;

                node = NewTreeNode(context, left, node2, Operation_IDs.OI_MUL, nPos);
                break;

            case '(':
                OutputID(context, Operation_IDs.OI_LBRACKET, "(", context.Position);
                context.Position++;
                node = DoExpression(context);

                SkipSpaces(context);

                if (context.CurrentChar != ')')
                {
                    if (context.ThrowParseException)
                    {
                        throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, ")");
                    }
                }
                else
                {
                    OutputID(context, Operation_IDs.OI_RBRACKET, ")", context.Position);
                }

                context.Position++;
                break;

            default:
                node = DoIdentifier(context);
                break;
            }

            SkipSpaces(context);

            return(node);
        }
Пример #5
0
        private static ExpTreeNode DoString(ParsingContext context)
        {
            int  nPos = context.Position;
            char ch   = context.ExpressionChars[++context.Position];

            StringBuilder strB   = new StringBuilder(256);
            StringBuilder strIDB = new StringBuilder(256);

            strIDB.Append('"');

            while (ch != '\0')
            {
                if (ch != '"')
                {
                    strB.Append(ch);
                    strIDB.Append(ch);
                    context.Position++;
                }
                else
                if (context.ExpressionChars[context.Position + 1] == '"')
                {
                    strB.Append('"');
                    strIDB.Append("\"\"");
                    context.Position += 2;
                }
                else
                {
                    strIDB.Append('"');
                    context.Position++;
                    break;
                }

                ch = context.CurrentChar;
            }

            if (ch == '\0')
            {
                if (context.ThrowParseException)
                {
                    throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, "\"");
                }
            }

            string strID = strIDB.ToString();

            OutputID(context, Operation_IDs.OI_STRING, strID, nPos);
            ExpTreeNode node = NewTreeNode(context);

            node.Position    = nPos;
            node.OperationID = Operation_IDs.OI_STRING;
            node.Value       = strB.ToString();

            return(node);
        }
Пример #6
0
        private static ExpTreeNode DoDatetime(ParsingContext context)
        {
            int  nPos = context.Position;
            char ch   = context.ExpressionChars[++context.Position];

            StringBuilder strB = new StringBuilder(256);

            strB.Append("#");

            while (ch != '\0')
            {
                strB.Append(ch);

                if (ch == '#')
                {
                    context.Position++;
                    break;
                }

                ch = context.ExpressionChars[++context.Position];
            }

            if (ch == '\0')
            {
                if (context.ThrowParseException)
                {
                    throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, "#");
                }
            }

            ExpTreeNode node = NewTreeNode(context);

            node.Position    = nPos;
            node.OperationID = Operation_IDs.OI_DATETIME;

            try
            {
                string strID = strB.ToString();
                node.Value = DateTime.Parse(strID);

                OutputID(context, Operation_IDs.OI_DATETIME, strID, nPos);

                return(node);
            }
            catch (System.FormatException)
            {
                if (context.ThrowParseException)
                {
                    throw ParsingException.NewParsingException(ParseError.peFormatError, nPos);
                }

                return(null);
            }
        }
Пример #7
0
        /// <summary>
        /// 检查参数的类型
        /// </summary>
        /// <typeparam name="T">参数是否是指定类型,或者是它的派生类</typeparam>
        /// <remarks>
        /// 检查参数类型是否为指定类型
        /// <code source="..\Framework\TestProjects\DeluxeWorks.Library.Test\Expression\ExpressionParserTest.cs" region="UserDefinedFucntions" lang="cs" />
        /// </remarks>
        public void CheckParameterType <T>()
        {
            if (this.Value != null)
            {
                System.Type expectedType = typeof(T);

                //bool temp = !(this.Value.GetType().IsSubclassOf(expectedType) || this.Value.GetType() == expectedType);

                if (false == (this.Value.GetType().IsSubclassOf(expectedType) || this.Value.GetType() == expectedType))
                {
                    throw ParsingException.NewParsingException(ParseError.InvalidParameterType, 0, expectedType.Name, this.Value.GetType().Name);
                }
            }
        }
Пример #8
0
        /// <summary>
        /// 处理各种数字、标识符、自定义函数、字符串等
        /// </summary>
        /// <returns></returns>
        private ExpTreeNode DoIdentifier(ParsingContext context)
        {
            ExpTreeNode result = null;

            SkipSpaces(context);

            char ch = context.CurrentChar;

            if (ch != '\0')
            {
                switch (ch)
                {
                case '#':       //datetime
                    result = DoDatetime(context);
                    break;

                case '"':       //string
                    result = DoString(context);
                    break;

                default:
                    if (Char.IsDigit(ch) || ch == '.')
                    {
                        result = DoNumber(context);
                    }
                    else
                    if (Char.IsLetter(ch) || ch == '_')
                    {
                        result = DoFunctionID(context);
                    }
                    else
                    {
                        if (context.ThrowParseException)
                        {
                            throw ParsingException.NewParsingException(ParseError.peInvalidOperator, context.Position, ch.ToString());
                        }
                    }
                    break;
                }

                SkipSpaces(context);
            }

            return(result);
        }
Пример #9
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);
        }
Пример #10
0
        private ExpTreeNode GetFunctionNode(ParsingContext context, Operation_IDs funcID, string strID)
        {
            ExpTreeNode        node      = null;
            ExpTreeNode        nodeTemp  = null;
            List <ExpTreeNode> paramBase = new List <ExpTreeNode>(4);

            int nStartFunction = context.Position - strID.Length;

            OutputID(context, Operation_IDs.OI_USERDEFINE, strID, nStartFunction);

            if (context.CurrentChar == '(')     //有参数
            {
                OutputIDToSubLevel(context);
                OutputID(context, Operation_IDs.OI_LBRACKET, "(", context.Position);

                do
                {
                    context.Position++;
                    SkipSpaces(context);

                    nodeTemp = DoExpression(context);

                    if (nodeTemp != null)
                    {
                        paramBase.Add(nodeTemp);

                        SkipSpaces(context);
                    }
                    else
                    {
                        break;
                    }

                    if (context.CurrentChar == ',')
                    {
                        OutputID(context, Operation_IDs.OI_COMMA, ",", context.Position);
                    }
                }while (context.CurrentChar == ',');

                if (context.CurrentChar == ')')
                {
                    OutputID(context, Operation_IDs.OI_RBRACKET, ")", context.Position);
                    OutputIDToParentLevel(context);

                    context.Position++;
                    node             = NewTreeNode(context);
                    node.Position    = nStartFunction;
                    node.Params      = paramBase;
                    node.OperationID = funcID;

                    if (funcID == Operation_IDs.OI_USERDEFINE)
                    {
                        node.FunctionName = strID;
                    }
                }
                else
                {
                    if (context.ThrowParseException)
                    {
                        throw ParsingException.NewParsingException(ParseError.peCharExpected, context.Position, ")");
                    }
                }

                SkipSpaces(context);
            }
            else        //没有参数
            {
                node             = NewTreeNode(context);
                node.Position    = nStartFunction;
                node.Params      = paramBase;
                node.OperationID = funcID;

                if (funcID == Operation_IDs.OI_USERDEFINE)
                {
                    node.FunctionName = strID;
                }
            }

            return(node);
        }
Пример #11
0
        /// <summary>
        /// 逻辑比较运算
        /// </summary>
        /// <returns></returns>
        private ExpTreeNode DoLogicalOP(ParsingContext context)
        {
            ExpTreeNode node  = null;
            ExpTreeNode node1 = DoAddSub(context);
            ExpTreeNode node2 = null;

            char op = context.CurrentChar;

            string strID = string.Empty;

            while (op == '>' || op == '<' || op == '=')
            {
                int nPos = context.Position;

                Operation_IDs oID = Operation_IDs.OI_NONE;

                if (context.ExpressionChars[++context.Position] == '=')
                {
                    switch (op)
                    {
                    case '>':           //>=
                        oID   = Operation_IDs.OI_GREATEQUAL;
                        strID = ">=";
                        break;

                    case '<':           //<=
                        oID   = Operation_IDs.OI_LESSEQUAL;
                        strID = "<=";
                        break;

                    case '=':           //==
                        oID   = Operation_IDs.OI_EQUAL;
                        strID = "==";
                        break;

                    default:
                    {
                        if (context.ThrowParseException)
                        {
                            throw ParsingException.NewParsingException(ParseError.peInvalidOperator,
                                                                       context.Position, op.ToString());
                        }
                        break;
                    }
                    }

                    context.Position++;
                }
                else
                {
                    if (context.CurrentChar == '>')
                    {
                        if (op == '<')  //<>
                        {
                            strID = "<>";
                            oID   = Operation_IDs.OI_NOT_EQUAL;
                            context.Position++;
                        }
                        else
                        {
                            if (context.ThrowParseException)
                            {
                                throw ParsingException.NewParsingException(ParseError.peInvalidOperator,
                                                                           context.Position, op.ToString());
                            }
                        }
                    }
                    else
                    {
                        switch (op)
                        {
                        case '>':
                            oID   = Operation_IDs.OI_GREAT;
                            strID = ">";
                            break;

                        case '<':
                            oID   = Operation_IDs.OI_LESS;
                            strID = "<";
                            break;

                        default:
                        {
                            if (context.ThrowParseException)
                            {
                                throw ParsingException.NewParsingException(ParseError.peInvalidOperator,
                                                                           context.Position, op.ToString());
                            }

                            break;
                        }
                        }
                    }
                }

                OutputID(context, oID, strID, nPos);

                node2 = DoAddSub(context);

                node = NewTreeNode(context, node1, node2, oID, nPos);

                node1 = node;

                op = context.CurrentChar;
            }

            return(node1);
        }