Ejemplo n.º 1
0
        /// <summary>
        /// 将子窜转化成Token并加入列表
        /// </summary>
        /// <param name="tokenString"></param>
        /// <param name="tokens"></param>
        private void AddToken(string tokenString, List <ExpressionToken> tokens)
        {
            ExpressionToken token = null;

            //null
            if (ExpressionTokenHelper.IsNull(tokenString))
            {
                token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_NULL, null);
                tokens.Add(token);
            }
            else
            //boolean
            if (ExpressionTokenHelper.IsBoolean(tokenString))
            {
                token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_BOOLEAN, Convert.ToBoolean(tokenString));
                tokens.Add(token);
            }
            else
            //integer
            if (ExpressionTokenHelper.IsInteger(tokenString))
            {
                token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_INT, Convert.ToInt32(tokenString));
                tokens.Add(token);
            }
            else
            //long
            if (ExpressionTokenHelper.IsLong(tokenString))
            {
                token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_LONG, Convert.ToInt64(tokenString.Substring(0, tokenString.Length - 1)));
                tokens.Add(token);
            }
            else
            //float
            if (ExpressionTokenHelper.IsFloat(tokenString))
            {
                token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_FLOAT, Convert.ToSingle(tokenString.Substring(0, tokenString.Length - 1)));
                tokens.Add(token);
            }
            else
            //double
            if (ExpressionTokenHelper.IsDouble(tokenString))
            {
                token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_DOUBLE, Convert.ToDouble(tokenString));
                tokens.Add(token);
            }
            else
            //Date
            if (ExpressionTokenHelper.IsDateTime(tokenString))
            {
                try
                {
                    token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_DATE, Convert.ToDateTime(tokenString.Substring(1, tokenString.Length - 1)));
                }
                catch (Exception e)
                {
                    throw new IllegalExpressionException("日期参数格式错误");
                }
                tokens.Add(token);
            }
            else
            //String
            if (ExpressionTokenHelper.IsString(tokenString))
            {
                token = ExpressionToken.CreateConstantToken(DataType.DATATYPE_STRING, tokenString.Substring(1, tokenString.Length - 1));
                tokens.Add(token);
            }
            else
            //分割符
            if (ExpressionTokenHelper.IsSplitor(tokenString))
            {
                token = ExpressionToken.CreateSplitorToken(tokenString);
                tokens.Add(token);
            }
            else
            //函数
            if (ExpressionTokenHelper.IsFunction(tokenString))
            {
                token = ExpressionToken.CreateFunctionToken(tokenString.Substring(1, tokenString.Length));
                tokens.Add(token);
            }
            else
            //操作符
            if (ExpressionTokenHelper.IsOperator(tokenString))
            {
                Operator op = ExpressionParser.GetOperator(tokenString);
                token = ExpressionToken.CreateOperatorToken(op);
                tokens.Add(token);
            }
            else
            {
                //剩下的都应该是变量,这个判断依赖于生成的RPN是正确的前提
                //变量,在boolean型和null型判别后,只要是字母打头的,不是$的就是变量
                token = ExpressionToken.CreateVariableToken(tokenString);
                tokens.Add(token);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 将正常表达式词元序列,转换成逆波兰式序列  同时检查表达式语法
        /// </summary>
        /// <param name="expTokens"></param>
        /// <returns></returns>
        public List <ExpressionToken> Compile(List <ExpressionToken> expTokens)
        {
            if (expTokens == null || expTokens.Count == 0)
            {
                throw new ArgumentException("无法转化空的表达式");
            }

            //1.初始化逆波兰式队列和操作符栈
            var _RPNExpList = new List <ExpressionToken>();
            Stack <ExpressionToken> opStack = new Stack <ExpressionToken>();
            //初始化检查栈
            Stack <ExpressionToken> verifyStack = new Stack <ExpressionToken>();

            //2.出队列中从左向右依次遍历token
            //2-1. 声明一个存储函数词元的临时变量
            ExpressionToken _function = null;

            foreach (ExpressionToken expToken in expTokens)
            {
                if (ExpressionToken.ETokenType.ETOKEN_TYPE_CONSTANT == expToken.TokenType)
                {
                    //读入一个常量,压入逆波兰式队列
                    _RPNExpList.Add(expToken);
                    //同时压入校验栈
                    verifyStack.Push(expToken);
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_VARIABLE == expToken.TokenType)
                {
                    //验证变量声明
                    Variable var = VariableContainer.GetVariable(expToken.Variable.VariableName);
                    if (var == null)
                    {
                        //当变量没有定义时,视为null型
                        expToken.Variable.SetDataType(DataType.DATATYPE_NULL);
                    }
                    //else if (var.GetDataType() == null)
                    //{
                    //    throw new IllegalExpressionException("表达式不合法,变量\"" + expToken.ToString() + "\"缺少定义;位置:" + expToken.StartPosition
                    //                , expToken.ToString()
                    //                , expToken.StartPosition);
                    //}
                    else
                    {
                        //设置Token中的变量类型定义
                        expToken.Variable.SetDataType(var.GetDataType());
                    }

                    //读入一个变量,压入逆波兰式队列
                    _RPNExpList.Add(expToken);
                    //同时压入校验栈
                    verifyStack.Push(expToken);
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_OPERATOR == expToken.TokenType)
                {
                    //读入一个操作符
                    if (opStack.Count == 0)
                    {//如果操作栈为空
                        if (Operator.COLON == expToken.Op)
                        {
                            //:操作符不可能单独出现,前面必须有对应的?
                            throw new IllegalExpressionException("在读入\":\"时,操作栈中找不到对应的\"?\" "

                                                                 , expToken.ToString()
                                                                 , expToken.StartPosition);
                        }
                        else
                        {
                            //一般操作符,则压入栈内;
                            opStack.Push(expToken);
                        }
                    }
                    else
                    {
                        bool doPeek = true;
                        while (!(opStack.Count == 0) && doPeek)
                        {
                            //如果栈不为空,则比较栈顶的操作符的优先级
                            ExpressionToken onTopOp = opStack.Peek();

                            //如果栈顶元素是函数,直接将操作符压入栈
                            if (ExpressionToken.ETokenType.ETOKEN_TYPE_FUNCTION == onTopOp.TokenType)
                            {
                                if (Operator.COLON == expToken.Op)
                                {
                                    //:操作符不可能直接遇见函数,前面必须有对应的?
                                    throw new IllegalExpressionException("在读入\":\"时,操作栈中找不到对应的\"?\""

                                                                         , expToken.ToString()
                                                                         , expToken.StartPosition);
                                }
                                else
                                {
                                    opStack.Push(expToken);
                                    doPeek = false;
                                }
                            }
                            else if (ExpressionToken.ETokenType.ETOKEN_TYPE_SPLITOR == onTopOp.TokenType &&
                                     "(".Equals(onTopOp.GetSplitor()))
                            {//如果栈顶元素是(,直接将操作符压入栈
                                if (Operator.COLON == expToken.Op)
                                {
                                    //:操作符不可能直接遇见(,前面必须有对应的?
                                    throw new IllegalExpressionException("在读入\":\"时,操作栈中找不到对应的\"?\""

                                                                         , expToken.ToString()
                                                                         , expToken.StartPosition);
                                }
                                else
                                {
                                    opStack.Push(expToken);
                                    doPeek = false;
                                }
                            }
                            else if (ExpressionToken.ETokenType.ETOKEN_TYPE_OPERATOR == onTopOp.TokenType)
                            {
                                //如果栈顶元素是操作符
                                if (expToken.Op.Priority > onTopOp.Op.Priority)
                                {
                                    if (Operator.COLON == expToken.Op)
                                    {
                                        //注意:如果在后期的功能扩展中,存在有比:优先级更低的操作符
                                        //则必须在此处做出栈处理
                                    }
                                    else
                                    {
                                        //当前操作符的优先级 > 栈顶操作符的优先级 ,则将当前操作符入站
                                        opStack.Push(expToken);
                                        doPeek = false;
                                    }
                                }
                                else if (expToken.Op.Priority == onTopOp.Op.Priority)
                                {
                                    if (Operator.QUES == expToken.Op)
                                    {
                                        //? , ?  -- >不弹出
                                        //?: , ? -- >不弹出
                                        opStack.Push(expToken);
                                        doPeek = false;
                                    }
                                    else if (Operator.COLON == expToken.Op)
                                    {
                                        //? , : -- > 弹出? ,将操作符转变成?: , 再压入栈
                                        if (Operator.QUES == onTopOp.Op)
                                        {
                                            //弹出?
                                            opStack.Pop();
                                            //将操作符转变成?:
                                            ExpressionToken opSelectToken = ExpressionToken.CreateOperatorToken(Operator.SELECT);
                                            opSelectToken.StartPosition = onTopOp.StartPosition;
                                            //再压入栈
                                            opStack.Push(opSelectToken);
                                            doPeek = false;
                                        }
                                        else if (Operator.SELECT == onTopOp.Op)
                                        { // ?: , : -->弹出?: ,执行校验
                                          //执行操作符校验
                                            ExpressionToken result = VerifyOperator(onTopOp, verifyStack);
                                            //把校验结果压入检验栈
                                            verifyStack.Push(result);
                                            //校验通过,弹出栈顶操作符,加入到逆波兰式队列
                                            opStack.Pop();
                                            _RPNExpList.Add(onTopOp);
                                        }
                                    }
                                    else
                                    {
                                        //当前操作符的优先级 = 栈顶操作符的优先级,且执行顺序是从左到右的,则将栈顶的操作符弹出
                                        //执行操作符校验
                                        ExpressionToken result = VerifyOperator(onTopOp, verifyStack);
                                        //把校验结果压入检验栈
                                        verifyStack.Push(result);
                                        //校验通过,弹出栈顶操作符,加入到逆波兰式队列
                                        opStack.Pop();
                                        _RPNExpList.Add(onTopOp);
                                    }
                                }
                                else
                                {
                                    //当前操作符的优先级 < 栈顶操作符的优先级,则将栈顶的操作符弹出
                                    //执行操作符校验
                                    ExpressionToken result = VerifyOperator(onTopOp, verifyStack);
                                    //把校验结果压入检验栈
                                    verifyStack.Push(result);
                                    //校验通过,弹出栈顶操作符,加入到逆波兰式队列
                                    opStack.Pop();
                                    _RPNExpList.Add(onTopOp);
                                }
                            }
                        }
                        //当前操作符的优先级 <= 栈内所有的操作符优先级
                        if (doPeek && opStack.Count == 0)
                        {
                            if (Operator.COLON == expToken.Op)
                            {
                                //:操作符不可能直接入栈,前面必须有对应的?
                                throw new IllegalExpressionException("在读入\":\"时,操作栈中找不到对应的\"?\""

                                                                     , expToken.ToString()
                                                                     , expToken.StartPosition);
                            }
                            else
                            {
                                opStack.Push(expToken);
                            }
                        }
                    }
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_FUNCTION == expToken.TokenType)
                {
                    //遇到函数名称,则使用临时变量暂存下来,等待(的来临
                    _function = expToken;
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_SPLITOR == expToken.TokenType)
                {
                    //处理读入的“(”
                    if ("(".Equals(expToken.GetSplitor()))
                    {
                        //如果此时_function != null,说明是函数的左括号
                        if (_function != null)
                        {
                            //向逆波兰式队列压入"("
                            _RPNExpList.Add(expToken);
                            //向校验栈压入
                            verifyStack.Push(expToken);

                            //将"("及临时缓存的函数压入操作符栈,括号在前
                            opStack.Push(expToken);
                            opStack.Push(_function);

                            //清空临时变量
                            _function = null;
                        }
                        else
                        {
                            //说明是普通的表达式左括号
                            //将"("压入操作符栈
                            opStack.Push(expToken);
                        }

                        //处理读入的“)”
                    }
                    else if (")".Equals(expToken.GetSplitor()))
                    {
                        bool doPop = true;

                        while (doPop && !(opStack.Count == 0))
                        {
                            // 从操作符栈顶弹出操作符或者函数,
                            ExpressionToken onTopOp = opStack.Pop();
                            if (ExpressionToken.ETokenType.ETOKEN_TYPE_OPERATOR == onTopOp.TokenType)
                            {
                                if (Operator.QUES == onTopOp.Op)
                                {
                                    //)分割符不可能遇到?,这说明缺少:号
                                    throw new IllegalExpressionException("在读入\")\"时,操作栈中遇到\"?\" ,缺少\":\"号"

                                                                         , onTopOp.ToString()
                                                                         , onTopOp.StartPosition);
                                }
                                else
                                {
                                    //如果栈顶元素是普通操作符,执行操作符校验
                                    ExpressionToken result = VerifyOperator(onTopOp, verifyStack);
                                    //把校验结果压入检验栈
                                    verifyStack.Push(result);

                                    // 校验通过,则添加到逆波兰式对列
                                    _RPNExpList.Add(onTopOp);
                                }
                            }
                            else if (ExpressionToken.ETokenType.ETOKEN_TYPE_FUNCTION == onTopOp.TokenType)
                            {
                                // 如果遇到函数,则说明")"是函数的右括号
                                //执行函数校验
                                ExpressionToken result = VerifyFunction(onTopOp, verifyStack);
                                //把校验结果压入检验栈
                                verifyStack.Push(result);

                                //校验通过,添加")"到逆波兰式中
                                _RPNExpList.Add(expToken);
                                //将函数加入逆波兰式
                                _RPNExpList.Add(onTopOp);
                            }
                            else if ("(".Equals(onTopOp.GetSplitor()))
                            {
                                // 如果遇到"(", 则操作结束
                                doPop = false;
                            }
                        }

                        if (doPop && opStack.Count == 0)
                        {
                            throw new IllegalExpressionException("在读入\")\"时,操作栈中找不到对应的\"(\" "

                                                                 , expToken.GetSplitor()
                                                                 , expToken.StartPosition);
                        }

                        //处理读入的“,”
                    }
                    else if (",".Equals(expToken.GetSplitor()))
                    {
                        //依次弹出操作符栈中的所有操作符,压入逆波兰式队列,直到遇见函数词元
                        bool doPeek = true;

                        while (!(opStack.Count == 0) && doPeek)
                        {
                            ExpressionToken onTopOp = opStack.Peek();

                            if (ExpressionToken.ETokenType.ETOKEN_TYPE_OPERATOR == onTopOp.TokenType)
                            {
                                if (Operator.QUES == onTopOp.Op)
                                {
                                    //,分割符不可能遇到?,这说明缺少:号
                                    throw new IllegalExpressionException("在读入\",\"时,操作栈中遇到\"?\" ,缺少\":\"号"

                                                                         , onTopOp.ToString()
                                                                         , onTopOp.StartPosition);
                                }
                                else
                                {
                                    //弹出操作符栈顶的操作符
                                    opStack.Pop();
                                    //执行操作符校验
                                    ExpressionToken result = VerifyOperator(onTopOp, verifyStack);
                                    //把校验结果压入检验栈
                                    verifyStack.Push(result);
                                    //校验通过,,压入逆波兰式队列
                                    _RPNExpList.Add(onTopOp);
                                }
                            }
                            else if (ExpressionToken.ETokenType.ETOKEN_TYPE_FUNCTION == onTopOp.TokenType)
                            {
                                //遇见函数词元,结束弹出
                                doPeek = false;
                            }
                            else if (ExpressionToken.ETokenType.ETOKEN_TYPE_SPLITOR == onTopOp.TokenType &&
                                     "(".Equals(onTopOp.GetSplitor()))
                            {
                                //在读入","时,操作符栈顶为"(",则报错
                                throw new IllegalExpressionException("在读入\",\"时,操作符栈顶为\"(\",,(函数丢失) 位置:" + onTopOp.StartPosition
                                                                     , expToken.GetSplitor()
                                                                     , expToken.StartPosition);
                            }
                        }
                        //栈全部弹出,但没有遇见函数词元
                        if (doPeek && opStack.Count == 0)
                        {
                            throw new IllegalExpressionException("在读入\",\"时,操作符栈弹空,没有找到相应的函数词元 "

                                                                 , expToken.GetSplitor()
                                                                 , expToken.StartPosition);
                        }
                    }
                }
            }

            //将操作栈内剩余的操作符逐一弹出,并压入逆波兰式队列
            while (!(opStack.Count == 0))
            {
                ExpressionToken onTopOp = opStack.Pop();

                if (ExpressionToken.ETokenType.ETOKEN_TYPE_OPERATOR == onTopOp.TokenType)
                {
                    if (Operator.QUES == onTopOp.Op)
                    {
                        //遇到单一的剩下的?,这说明缺少:号
                        throw new IllegalExpressionException("操作栈中遇到剩余的\"?\" ,缺少\":\"号"

                                                             , onTopOp.ToString()
                                                             , onTopOp.StartPosition);
                    }
                    else
                    {
                        //执行操作符校验
                        ExpressionToken result = VerifyOperator(onTopOp, verifyStack);
                        //把校验结果压入检验栈
                        verifyStack.Push(result);

                        //校验成功,将操作符加入逆波兰式
                        _RPNExpList.Add(onTopOp);
                    }
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_FUNCTION == onTopOp.TokenType)
                {
                    //如果剩余是函数,则函数缺少右括号")"
                    throw new IllegalExpressionException("函数" + onTopOp.TokenText + "缺少\")\""
                                                         , onTopOp.TokenText
                                                         , onTopOp.StartPosition);
                }
                else if ("(".Equals(onTopOp.GetSplitor()))
                {
                    //剩下的就只有“(”了,则说明表达式的算式缺少右括号")"
                    throw new IllegalExpressionException("左括号\"(\"缺少配套的右括号\")\""

                                                         , onTopOp.TokenText
                                                         , onTopOp.StartPosition);
                }
            }

            //表达式校验完成,这是校验栈内应该只有一个结果,否则视为表达式不完成
            if (verifyStack.Count != 1)
            {
                var errorBuffer = new StringBuilder("\r\n");
                while (!(verifyStack.Count == 0))
                {
                    ExpressionToken onTop = verifyStack.Pop();
                    errorBuffer.Append("\t").Append(onTop.ToString()).Append("\r\n");
                }
                throw new IllegalExpressionException("表达式不完整.\r\n 校验栈状态异常:" + errorBuffer);
            }

            return(_RPNExpList);
        }