/// <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); } }
/// <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); }