private void CheckOperand(object p1, object p2, int nPos)
 {
     if (p1 == null || p2 == null)
     {
         throw ParsingException.NewParsingException(Parse_Error.peNeedOperand, nPos);
     }
 }
        /// <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;
                }
            }
        }
        /// <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);
        }
        private EXP_TreeNode DoVariable()
        {
            int  nPos = _Position;
            char ch   = _ExpressionChars[++_Position];

            //OutputID(Operation_IDs.OI_Variable, "$", nPos);
            //EXP_TreeNode node = NewTreeNode();

            //node._Position = nPos;
            //node._OperationID = Operation_IDs.OI_Variable;
            //node._Params = new ArrayList();
            //node._Params.Add(DoString());

            //return node;
            StringBuilder strB = new StringBuilder(256);

            if (Char.IsLetter(ch))
            {
                strB.Append(ch);
                ch = _ExpressionChars[++_Position];

                while (Char.IsLetter(ch) || Char.IsDigit(ch) || ch == '_')
                {
                    strB.Append(ch);
                    ch = _ExpressionChars[++_Position];
                }
                //if (ch == '\0')
                //    throw ParsingException.NewParsingException(Parse_Error.peCharExpected, _Position, "\"");

                string strID = strB.ToString();

                OutputID(Operation_IDs.OI_Variable, "$", nPos);
                EXP_TreeNode node = NewTreeNode();

                node._Position    = nPos;
                node._OperationID = Operation_IDs.OI_Variable;
                node._Params      = new ArrayList();

                EXP_TreeNode param = NewTreeNode();
                param._Value       = strID;
                param._OperationID = Operation_IDs.OI_STRING;
                node._Params.Add(param);
                OutputID(Operation_IDs.OI_STRING, strID, _Position);


                this.Variables.Add("$" + strID);

                return(node);
            }
            else
            {
                throw ParsingException.NewParsingException(Parse_Error.peInvalidChar, _Position, "");
            }
        }
        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 (ch == '$')
                {
                    result = DoVariable();
                }
                else if (Char.IsLetter(ch) || ch == '_')
                {
                    result = DoFunctionID();
                }
                else
                {
                    throw ParsingException.NewParsingException(Parse_Error.peInvalidOperator, _Position, ch.ToString());
                }

                SkipSpaces();
            }

            return(result);
        }
        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_Variable:
                    {
                        ParamObject[] po = GetParamArray(node._Params);
                        oValue = CalculateFunction("getValue", po, this);
                    }
                    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);
        }