/// <summary>
        /// 处理逻辑非"!"运算符
        /// </summary>
        /// <returns></returns>
        private EXP_TreeNode DoSgOP()
        {
            EXP_TreeNode node  = null;
            EXP_TreeNode node2 = null;

            SkipSpaces();

            char ch = _ExpressionChars[_Position];

            if (ch == '!')
            {
                OutputID(Operation_IDs.OI_NOT, "!", _Position);

                int nPos = _Position;

                _Position++;

                node2 = DoSgOP();
                node  = NewTreeNode(null, node2, Operation_IDs.OI_NOT, nPos);
            }
            else
            {
                node = DoFactor();
            }

            return(node);
        }
        private EXP_TreeNode DoLogical_AND_OR(char chSensitive, Operation_IDs oID, DoNextOP nextOP)
        {
            EXP_TreeNode node  = null;
            EXP_TreeNode node1 = nextOP();
            EXP_TreeNode node2 = null;

            while (_ExpressionChars[_Position] == chSensitive)
            {
                int  nPos = _Position;
                char op   = _ExpressionChars[_Position++];

                if (op == chSensitive)
                {
                    OutputID(oID, chSensitive.ToString() + chSensitive.ToString(), nPos);
                    _Position++;
                }

                node2 = nextOP();

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

                node1 = node;
            }

            return(node1);
        }
        /// <summary>
        /// 处理乘除运算
        /// </summary>
        /// <returns></returns>
        private EXP_TreeNode DoMulDiv()
        {
            EXP_TreeNode node  = null;
            EXP_TreeNode node1 = DoSgOP();
            EXP_TreeNode node2 = null;

            char ch = _ExpressionChars[_Position];

            while (ch == '*' || ch == '/')
            {
                Operation_IDs oID = Operation_IDs.OI_NONE;

                oID = (ch == '*') ? Operation_IDs.OI_MUL : Operation_IDs.OI_DIV;

                OutputID(oID, ch.ToString(), _Position);

                int nPos = _Position;

                _Position++;
                node2 = DoSgOP();

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

                ch = _ExpressionChars[_Position];
            }

            return(node1);
        }
        /// <summary>
        /// 重新构造二叉树
        /// </summary>
        /// <param name="strExpression">表达式</param>
        public void ChangeExpression(string strExpression)
        {
            _Expression = strExpression;

            _Tree              = null;
            _Position          = 0;
            _Identifiers       = null;
            _CurrentIdentifier = null;
            _ParentIdentifier  = null;

            if (strExpression != string.Empty)
            {
                try
                {
                    _ExpressionChars = new Char[strExpression.Length + 1];

                    strExpression.CopyTo(0, _ExpressionChars, 0, strExpression.Length);
                    _ExpressionChars[strExpression.Length] = '\0';

                    _Tree = DoExpression();

                    if (_ExpressionChars[_Position] != '\0')
                    {
                        throw ParsingException.NewParsingException(Parse_Error.peSyntaxError, _Position);
                    }
                }
                finally
                {
                    _CurrentIdentifier = null;
                    _ParentIdentifier  = null;
                }
            }
        }
        private EXP_TreeNode NewTreeNode(EXP_TreeNode left, EXP_TreeNode right, Operation_IDs oID, int nPosition)
        {
            EXP_TreeNode node = NewTreeNode(left, right, oID);

            node._Position = nPosition;

            return(node);
        }
        /// <summary>
        /// 生成一个新的二叉树节点
        /// </summary>
        private EXP_TreeNode NewTreeNode()
        {
            EXP_TreeNode node = new EXP_TreeNode();

            node._Position = _Position;

            return(node);
        }
        /// <summary>
        /// 处理各种系数、负数、括号等
        /// </summary>
        /// <returns></returns>
        private EXP_TreeNode DoFactor()
        {
            EXP_TreeNode node  = null;
            EXP_TreeNode left  = null;
            EXP_TreeNode node2 = null;

            SkipSpaces();

            char ch = _ExpressionChars[_Position];

            int nPos = _Position;

            if (ch == '-')              //处理负号
            {
                OutputID(Operation_IDs.OI_NEG, "-", _Position);

                _Position++;

                node2 = DoExpression();

                left = NewTreeNode();
                left._OperationID = Operation_IDs.OI_NEG;
                left._Value       = (double)-1;
                left._Position    = nPos;

                node = NewTreeNode(left, node2, Operation_IDs.OI_MUL, nPos);
            }
            else
            if (ch == '(')
            {
                OutputID(Operation_IDs.OI_LBRACKET, "(", _Position);
                _Position++;
                node = DoExpression();

                SkipSpaces();

                if (_ExpressionChars[_Position] != ')')
                {
                    throw ParsingException.NewParsingException(Parse_Error.peCharExpected, _Position, ")");
                }
                else
                {
                    OutputID(Operation_IDs.OI_RBRACKET, ")", _Position);
                }

                _Position++;
            }
            else
            {
                node = DoIdentifier();
            }

            SkipSpaces();

            return(node);
        }
        /// <summary>
        /// 生成一个新的二叉树节点
        /// </summary>
        /// <param name="left">左子树</param>
        /// <param name="right">右子树</param>
        /// <param name="oID">操作类型</param>
        /// <returns></returns>
        private EXP_TreeNode NewTreeNode(EXP_TreeNode left, EXP_TreeNode right, Operation_IDs oID)
        {
            EXP_TreeNode node = NewTreeNode();

            node._Left        = left;
            node._Right       = right;
            node._OperationID = oID;

            return(node);
        }
        private ParamObject[] GetParamArray(ArrayList arrParams)
        {
            ParamObject[] result = new ParamObject[arrParams.Count];

            for (int i = 0; i < arrParams.Count; i++)
            {
                EXP_TreeNode node = (EXP_TreeNode)arrParams[i];

                result[i] = new ParamObject(VExp(node), node._Position);
            }

            return(result);
        }
        private EXP_TreeNode DoString()
        {
            int  nPos = _Position;
            char ch   = _ExpressionChars[++_Position];

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

            strIDB.Append('"');

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

                ch = _ExpressionChars[_Position];
            }

            if (ch == '\0')
            {
                throw ParsingException.NewParsingException(Parse_Error.peCharExpected, _Position, "\"");
            }

            string strID = strIDB.ToString();

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

            node._Position    = nPos;
            node._OperationID = Operation_IDs.OI_STRING;
            node._Value       = strB.ToString();

            return(node);
        }
        private EXP_TreeNode DoDatetime()
        {
            int  nPos = _Position;
            char ch   = _ExpressionChars[++_Position];

            StringBuilder strB = new StringBuilder(256);

            strB.Append("#");

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

                if (ch == '#')
                {
                    _Position++;
                    break;
                }

                ch = _ExpressionChars[++_Position];
            }

            if (ch == '\0')
            {
                throw ParsingException.NewParsingException(Parse_Error.peCharExpected, _Position, "#");
            }

            EXP_TreeNode node = NewTreeNode();

            node._Position    = nPos;
            node._OperationID = Operation_IDs.OI_DATETIME;

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

                OutputID(Operation_IDs.OI_DATETIME, strID, nPos);

                return(node);
            }
            catch (System.FormatException)
            {
                throw ParsingException.NewParsingException(Parse_Error.peFormatError, nPos);
            }
        }
        /// <summary>
        /// 处理各种数字、标识符、自定义函数、字符串等
        /// </summary>
        /// <returns></returns>
        private EXP_TreeNode DoIdentifier()
        {
            EXP_TreeNode result = null;

            SkipSpaces();

            char ch = _ExpressionChars[_Position];

            if (ch != '\0')
            {
                if (ch == '#')                  //string
                {
                    result = DoDatetime();
                }
                else
                if (ch == '"')                  //string
                {
                    result = DoString();
                }
                else
                if (Char.IsDigit(ch) || ch == '.')
                {
                    result = DoNumber();
                }
                else
                if (Char.IsLetter(ch) || ch == '_')
                {
                    result = DoFunctionID();
                }
                else
                {
                    throw ParsingException.NewParsingException(Parse_Error.peInvalidOperator, _Position, ch.ToString());
                }

                SkipSpaces();
            }

            return(result);
        }
        private EXP_TreeNode DoNumber()
        {
            int  nPos = _Position;
            char ch   = _ExpressionChars[_Position];

            while (Char.IsDigit(ch) || (ch == '.'))
            {
                ch = _ExpressionChars[++_Position];
            }

            EXP_TreeNode node = NewTreeNode();

            node._Position    = nPos;
            node._OperationID = Operation_IDs.OI_NUMBER;

            string ns = new String(_ExpressionChars, nPos, _Position - nPos);

            node._Value = double.Parse(ns);

            OutputID(Operation_IDs.OI_NUMBER, ns, nPos);

            return(node);
        }
        private EXP_TreeNode DoFunction(string strID)
        {
            Operation_IDs oID = Operation_IDs.OI_USERDEFINE;

            EXP_TreeNode node = null;

            string strLower = strID.ToLower();

            if (strLower == "true" || strLower == "false")
            {
                node              = NewTreeNode();
                node._Position    = _Position - strID.Length;
                node._OperationID = Operation_IDs.OI_BOOLEAN;
                node._Value       = bool.Parse(strLower);

                OutputID(Operation_IDs.OI_BOOLEAN, strID, node._Position);
            }
            else
            {
                node = GetFunctionNode(oID, strID);
            }

            return(node);
        }
        private object VExp(EXP_TreeNode node)
        {
            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), VExp(node._Right), node._Position);
                        break;

                    case Operation_IDs.OI_MINUS:
                    {
                        object p1 = VExp(node._Left);
                        object p2 = VExp(node._Right);

                        CheckOperand(p1, p2, node._Position);
                        oValue = (double)p1 - (double)p2;
                    }
                    break;

                    case Operation_IDs.OI_MUL:
                    {
                        object p1 = VExp(node._Left);
                        object p2 = VExp(node._Right);

                        CheckOperand(p1, p2, node._Position);
                        oValue = (double)p1 * (double)p2;
                    }
                    break;

                    case Operation_IDs.OI_DIV:
                    {
                        object p1 = VExp(node._Left);
                        object p2 = VExp(node._Right);

                        CheckOperand(p1, p2, node._Position);
                        oValue = (double)p1 / (double)p2;
                    }
                    break;

                    case Operation_IDs.OI_LOGICAL_OR:
                    {
                        oValue = (bool)VExp(node._Left);
                        object oRight = (bool)false;

                        if (Optimize == false || (bool)oValue == false)
                        {
                            oRight = VExp(node._Right);
                        }

                        CheckOperand(oValue, oRight, node._Position);
                        oValue = (bool)oValue || (bool)oRight;
                    }
                    break;

                    case Operation_IDs.OI_LOGICAL_AND:
                    {
                        oValue = (bool)VExp(node._Left);
                        object oRight = (bool)true;

                        if (Optimize == false || (bool)oValue == true)
                        {
                            oRight = VExp(node._Right);
                        }

                        CheckOperand(oValue, oRight, node._Position);
                        oValue = (bool)oValue && (bool)oRight;
                    }
                    break;

                    case Operation_IDs.OI_NOT:
                        oValue = VExp(node._Right);
                        CheckOperand(oValue, node._Position);
                        oValue = !(bool)oValue;
                        break;

                    case Operation_IDs.OI_GREAT:
                        oValue = CompareGreatOP(VExp(node._Left), VExp(node._Right), node._Position);
                        break;

                    case Operation_IDs.OI_GREATEQUAL:
                        oValue = CompareGreatEqualOP(VExp(node._Left), VExp(node._Right), node._Position);
                        break;

                    case Operation_IDs.OI_LESS:
                        oValue = CompareLessOP(VExp(node._Left), VExp(node._Right), node._Position);
                        break;

                    case Operation_IDs.OI_LESSEQUAL:
                        oValue = CompareLessEqualOP(VExp(node._Left), VExp(node._Right), node._Position);
                        break;

                    case Operation_IDs.OI_NOT_EQUAL:
                        oValue = CompareNotEqualOP(VExp(node._Left), VExp(node._Right), node._Position);
                        break;

                    case Operation_IDs.OI_EQUAL:
                        oValue = CompareEqualOP(VExp(node._Left), VExp(node._Right), node._Position);
                        break;

                    case Operation_IDs.OI_USERDEFINE:
                    {
                        ParamObject[] po = GetParamArray(node._Params);
                        oValue = CalculateFunction(node._FunctionName, po, this);
                    }
                    break;

                    default:
                        throw ParsingException.NewParsingException(Parse_Error.peInvalidOperator, node._Position);
                    }
                }
                catch                //(System.InvalidCastException ex)
                {
                    throw ParsingException.NewParsingException(Parse_Error.peTypeMismatch, node._Position);
                }
            }

            return(oValue);
        }
        EXP_TreeNode GetFunctionNode(Operation_IDs funcID, string strID)
        {
            EXP_TreeNode node      = null;
            EXP_TreeNode nodeTemp  = null;
            ArrayList    paramBase = new ArrayList(4);

            int nStartFunction = _Position - strID.Length;

            OutputID(Operation_IDs.OI_USERDEFINE, strID, nStartFunction);

            if (_ExpressionChars[_Position] == '(')             //有参数
            {
                OutputIDToSubLevel();
                OutputID(Operation_IDs.OI_LBRACKET, "(", _Position);

                do
                {
                    _Position++;
                    SkipSpaces();

                    nodeTemp = DoExpression();

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

                        SkipSpaces();
                    }
                    else
                    {
                        break;
                    }

                    if (_ExpressionChars[_Position] == ',')
                    {
                        OutputID(Operation_IDs.OI_COMMA, ",", _Position);
                    }
                }while(_ExpressionChars[_Position] == ',');

                if (_ExpressionChars[_Position] == ')')
                {
                    OutputID(Operation_IDs.OI_RBRACKET, ")", _Position);
                    OutputIDToParentLevel();

                    _Position++;
                    node              = NewTreeNode();
                    node._Position    = nStartFunction;
                    node._Params      = paramBase;
                    node._OperationID = funcID;

                    if (funcID == Operation_IDs.OI_USERDEFINE)
                    {
                        node._FunctionName = strID;
                    }
                }
                else
                {
                    throw ParsingException.NewParsingException(Parse_Error.peCharExpected, _Position, ")");
                }

                SkipSpaces();
            }
            else                //没有参数
            {
                node              = NewTreeNode();
                node._Position    = nStartFunction;
                node._Params      = paramBase;
                node._OperationID = funcID;

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

            return(node);
        }
        /// <summary>
        /// 逻辑比较运算
        /// </summary>
        /// <returns></returns>
        private EXP_TreeNode DoLogicalOP()
        {
            EXP_TreeNode node  = null;
            EXP_TreeNode node1 = DoAddSub();
            EXP_TreeNode node2 = null;

            char op = _ExpressionChars[_Position];

            string strID = "";

            while (op == '>' || op == '<' || op == '=')
            {
                int nPos = _Position;

                Operation_IDs oID = Operation_IDs.OI_NONE;

                if (_ExpressionChars[++_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: throw ParsingException.NewParsingException(Parse_Error.peInvalidOperator,
                                                                        _Position, op.ToString());
                    }

                    _Position++;
                }
                else
                {
                    if (_ExpressionChars[_Position] == '>')
                    {
                        if (op == '<')                          //<>
                        {
                            strID = "<>";
                            oID   = Operation_IDs.OI_NOT_EQUAL;
                            _Position++;
                        }
                        else
                        {
                            throw ParsingException.NewParsingException(Parse_Error.peInvalidOperator,
                                                                       _Position, op.ToString());
                        }
                    }
                    else
                    {
                        switch (op)
                        {
                        case '>':
                            oID   = Operation_IDs.OI_GREAT;
                            strID = ">";
                            break;

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

                        default:
                            throw ParsingException.NewParsingException(Parse_Error.peInvalidOperator,
                                                                       _Position, op.ToString());
                        }
                    }
                }

                OutputID(oID, strID, nPos);

                node2 = DoAddSub();

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

                node1 = node;

                op = _ExpressionChars[_Position];
            }

            return(node1);
        }