コード例 #1
0
        //执行函数校验
        private ExpressionToken VerifyFunction(ExpressionToken funtionToken, Stack <ExpressionToken> verifyStack)
        {
            if (!(verifyStack.Count == 0))
            {
                bool            doPop     = true;
                var             args      = new List <BaseMetadata>();
                ExpressionToken parameter = null;
                //弹出函数的参数,直到遇到"("时终止
                while (doPop && !(verifyStack.Count == 0))
                {
                    parameter = verifyStack.Pop();

                    if (ExpressionToken.ETokenType.ETOKEN_TYPE_CONSTANT == parameter.TokenType)
                    {
                        //常量
                        args.Add(parameter.Constant);
                    }
                    else if (ExpressionToken.ETokenType.ETOKEN_TYPE_VARIABLE == parameter.TokenType)
                    {
                        args.Add(parameter.Variable);
                    }
                    else if ("(".Equals(parameter.GetSplitor()))
                    {
                        doPop = false;
                    }
                    else
                    {
                        //没有找到应该存在的右括号
                        throw new IllegalExpressionException("表达式不合法,函数\"" + funtionToken.TokenText + "\"遇到非法参数" + parameter.ToString() + ";位置:" + parameter.StartPosition
                                                             , funtionToken.ToString()
                                                             , funtionToken.StartPosition);
                    }
                }

                if (doPop && (verifyStack.Count == 0))
                {
                    //操作栈以空,没有找到函数的左括号(
                    throw new IllegalExpressionException("表达式不合法,函数\"" + funtionToken.TokenText + "\"缺少\"(\";位置:" + (funtionToken.StartPosition + funtionToken.ToString().Length)
                                                         , funtionToken.ToString()
                                                         , funtionToken.StartPosition);
                }

                //校验函数
                var arguments = new BaseMetadata[args.Count];
                arguments = args.ToArray();
                Constant result = FunctionExecution.Verify(funtionToken.TokenText, funtionToken.StartPosition, arguments);
                return(ExpressionToken.CreateConstantToken(result));
            }
            else
            {
                //没有找到应该存在的右括号
                throw new IllegalExpressionException("表达式不合法,函数\"" + funtionToken.TokenText + "\"不完整"
                                                     , funtionToken.ToString()
                                                     , funtionToken.StartPosition);
            }
        }
コード例 #2
0
        /**
         * 执行逆波兰式
         * @return
         */
        public Constant Execute(List <ExpressionToken> _RPNExpList)
        {
            if (_RPNExpList == null || _RPNExpList.Count == 0)
            {
                throw new ArgumentException("无法执行空的逆波兰式队列");
            }

            //初始化编译栈
            Stack <ExpressionToken> compileStack = new Stack <ExpressionToken>();

            foreach (ExpressionToken expToken in _RPNExpList)
            {
                if (ExpressionToken.ETokenType.ETOKEN_TYPE_CONSTANT == expToken.TokenType)
                {
                    //读取一个常量,压入栈
                    compileStack.Push(expToken);
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_VARIABLE == expToken.TokenType)
                {
                    //读取一个变量
                    //从上下文获取变量的实际值,将其转化成常量Token,压入栈
                    Variable varWithValue = VariableContainer.GetVariable(expToken.Variable.VariableName);
                    if (varWithValue != null)
                    {
                        //生成一个有值常量,varWithValue.getDataValue有可能是空值
                        ExpressionToken constantToken = ExpressionToken.CreateConstantToken(
                            varWithValue.GetDataType()
                            , varWithValue.DataValue);
                        compileStack.Push(constantToken);
                    }
                    else
                    {
                        //throw new IllegalStateException("变量\"" +expToken.getVariable().getVariableName() + "\"不是上下文合法变量" );
                        //当变量没有定义时,视为null型
                        ExpressionToken constantToken = ExpressionToken.CreateConstantToken(
                            DataType.DATATYPE_NULL
                            , null);
                        compileStack.Push(constantToken);
                    }
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_OPERATOR == expToken.TokenType)
                {
                    Operator op = expToken.Op;
                    //判定几元操作符
                    int opType = op.OpType;
                    //取得相应的参数个数
                    Constant[]      args     = new Constant[opType];
                    ExpressionToken argToken = null;
                    for (int i = 0; i < opType; i++)
                    {
                        if (!(compileStack.Count == 0))
                        {
                            argToken = compileStack.Pop();
                            if (ExpressionToken.ETokenType.ETOKEN_TYPE_CONSTANT == argToken.TokenType)
                            {
                                args[i] = argToken.Constant;
                            }
                            else
                            {
                                //如果取出的Token不是常量,则抛出错误
                                throw new Exception("操作符" + op.Token + "找不到相应的参数,或参数个数不足;位置:" + expToken.StartPosition);
                            }
                        }
                        else
                        {
                            //栈已经弹空,没有取道操作符对应的操作数
                            throw new Exception("操作符" + op.Token + "找不到相应的参数,或参数个数不足;位置:" + expToken.StartPosition);
                        }
                    }
                    //构造引用常量对象
                    Reference       reference   = new Reference(expToken, args);
                    ExpressionToken resultToken = ExpressionToken.CreateReference(reference);
                    //将引用对象压入栈
                    compileStack.Push(resultToken);
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_FUNCTION == expToken.TokenType)
                {
                    if (!(compileStack.Count == 0))
                    {
                        ExpressionToken onTop = compileStack.Pop();
                        //检查在遇到函数词元后,执行栈中弹出的第一个词元是否为“)”
                        if (")".Equals(onTop.GetSplitor()))
                        {
                            bool            doPop     = true;
                            List <Constant> argsList  = new List <Constant>();
                            ExpressionToken parameter = null;
                            //弹出函数的参数,直到遇到"("时终止
                            while (doPop && !(compileStack.Count == 0))
                            {
                                parameter = compileStack.Pop();

                                if (ExpressionToken.ETokenType.ETOKEN_TYPE_CONSTANT == parameter.TokenType)
                                {
                                    argsList.Add(parameter.Constant);
                                }
                                else if ("(".Equals(parameter.GetSplitor()))
                                {
                                    doPop = false;
                                }
                                else
                                {
                                    //在函数中遇到的既不是常量,也不是"(",则报错
                                    throw new Exception("函数" + expToken.TokenText + "执行时遇到非法参数" + parameter.ToString());
                                }
                            }

                            if (doPop && (compileStack.Count == 0))
                            {
                                //操作栈以空,没有找到函数的左括号(
                                throw new Exception("函数" + expToken.TokenText + "执行时没有找到应有的\"(\"");
                            }

                            //执行函数
                            Constant[] arguments = new Constant[argsList.Count];
                            arguments = argsList.ToArray();
                            //构造引用常量对象
                            Reference       reference   = new Reference(expToken, arguments);
                            ExpressionToken resultToken = ExpressionToken.CreateReference(reference);
                            //将引用对象压入栈
                            compileStack.Push(resultToken);
                        }
                        else
                        {
                            //没有找到应该存在的右括号
                            throw new Exception("函数" + expToken.TokenText + "执行时没有找到应有的\")\"");
                        }
                    }
                    else
                    {
                        //没有找到应该存在的右括号
                        throw new Exception("函数" + expToken.TokenText + "执行时没有找到应有的\")\"");
                    }
                }
                else if (ExpressionToken.ETokenType.ETOKEN_TYPE_SPLITOR == expToken.TokenType)
                {
                    //读取一个分割符,压入栈,通常是"("和")"
                    compileStack.Push(expToken);
                }
            }

            //表达式编译完成,这是编译栈内应该只有一个编译结果
            if (compileStack.Count == 1)
            {
                ExpressionToken token  = compileStack.Pop();
                Constant        result = token.Constant;
                //执行Reference常量
                if (result.IsReference)
                {
                    Reference resultRef = (Reference)result.DataValue;
                    return(resultRef.Execute());
                }
                else
                {
                    //返回普通的常量
                    return(result);
                }
            }
            else
            {
                var errorBuffer = new StringBuilder("\r\n");
                while (!(compileStack.Count == 0))
                {
                    ExpressionToken onTop = compileStack.Pop();
                    errorBuffer.Append("\t").Append(onTop.ToString()).Append("\r\n");
                }
                throw new Exception("表达式不完整.\r\n 结果状态异常:" + errorBuffer.ToString());
            }
        }
コード例 #3
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);
        }