/// <summary> /// 获取后缀分词 - 用于测试分析 /// </summary> public List <string> PostfixWords(TOKENLink startLink, TOKENLink endLink) { CheckParen(startLink, endLink); //先检查再进行后缀表达式转换 TokenEnvirAnalyze(startLink, endLink); TOKENLink link = _toolBox.InfixToPostfix(startLink, endLink); List <string> wordList = new List <string>(); while (link != null) { if (link.Token.Type == ETokenType.token_operand) { wordList.Add(((TOKEN <IOperand>)link.Token).Tag.ToString()); } else { Operator op = ((TOKEN <Operator>)link.Token).Tag; if (op.Value == "+" || op.Value == "-") { wordList.Add(op.Value + " " + op.Type.ToString()); } else { wordList.Add(op.Value); } } link = link.Next; } return(wordList); }
public void Add(TOKENLink token) { if (token != null) { if (Head != null) { Tail.Next = token; token.Prev = Tail; Tail = token; } else { Head = token; Tail = token; } } }
/// <summary> /// 括弧必须成对出现,并且先有“(”才有“)” /// </summary> /// <param name="startLink"></param> /// <param name="endLink"></param> private void CheckParen(TOKENLink startLink, TOKENLink endLink) { TOKENLink curLink = startLink; int cout = 0; while (true) { if (curLink.Token.Type == ETokenType.token_operator) { if (((TOKEN <Operator>)curLink.Token).Tag.Type == EOperatorType.LeftParen) { cout++; } else if (((TOKEN <Operator>)curLink.Token).Tag.Type == EOperatorType.RightParen) { cout--; } if (cout < 0) { throw new Exception(string.Format("Error! 缺少左括弧(索引:{0})", curLink.Token.Index.ToString())); } } if (curLink == endLink) { break; } curLink = curLink.Next; } if (cout > 0) { throw new Exception(string.Format("Error! 缺少“{0}”个右括弧", cout.ToString())); } }
/// <summary> /// 语法分析 /// </summary> /// <param name="startLink"></param> /// <param name="endLink"></param> public IOperand Analyze(TOKENLink startLink, TOKENLink endLink) { //分三步 //1、括弧有效性判断 //2、操作符和操作数应用环境分析 //3、操作符好操作数匹配类型分析 //第一步 CheckParen(startLink, endLink); //第二步 TokenEnvirAnalyze(startLink, endLink); //第三步 TOKENLink postfixLink = _toolBox.InfixToPostfix(startLink, endLink); TOKENLink link_new = null; IToken token = null; while (postfixLink.Next != null) { postfixLink = postfixLink.Next; if (postfixLink.Token.Type == ETokenType.token_operator) { link_new = null; token = null; EOperatorType type = ((TOKEN <Operator>)postfixLink.Token).Tag.Type; switch (type) { case EOperatorType.Positive: //正 case EOperatorType.Negative: //负 IOperand operand = ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag; if (operand.Type == EDataType.Ddouble || operand.Type == EDataType.Dint) { token = postfixLink.Prev.Token; } else { throw new Exception(string.Format("Error! 运算符“{0}”无法应用于“{2}”类型的操作数(索引:{1})", ((TOKEN <Operator>)postfixLink.Token).Tag.Value, postfixLink.Token.Index.ToString(), operand.Type.ToString())); } break; case EOperatorType.Plus: case EOperatorType.Minus: case EOperatorType.Multiply: case EOperatorType.Divide: case EOperatorType.Mod: if ((((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dstring || ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dstring) && (type == EOperatorType.Plus || type == EOperatorType.Minus)) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <string>(EDataType.Dstring, ""), postfixLink.Token.Index); } else if ((((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Ddouble || ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dint) && (((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Ddouble || ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dint)) { if ((((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Ddouble || ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Ddouble) || (type == EOperatorType.Divide || type == EOperatorType.Mod)) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <double>(EDataType.Ddouble, 0), postfixLink.Token.Index); } else { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <int>(EDataType.Dint, 0), postfixLink.Token.Index); } } else { throw new Exception(string.Format("Error! 运算符“{0}”无法应用于“{2}”和“{3}”类型的操作数(索引:{1})", ((TOKEN <Operator>)postfixLink.Token).Tag.Value, postfixLink.Token.Index.ToString(), ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type.ToString(), ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type.ToString())); } break; case EOperatorType.LessThan: case EOperatorType.GreaterThan: case EOperatorType.Equal: case EOperatorType.NotEqual: case EOperatorType.GreaterEqual: case EOperatorType.LessEqual: if (((((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Ddouble || ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dint) && (((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Ddouble || ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dint)) || (((((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dstring && ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dstring) || (((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dbool && ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dbool)) && (type == EOperatorType.Equal || type == EOperatorType.NotEqual))) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <bool>(EDataType.Dbool, true), postfixLink.Token.Index); } else { throw new Exception(string.Format("Error! 运算符“{0}”无法应用于“{2}”和“{3}”类型的操作数(索引:{1})", ((TOKEN <Operator>)postfixLink.Token).Tag.Value, postfixLink.Token.Index.ToString(), ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type.ToString(), ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type.ToString())); } break; default: break; } if (token != null) { link_new = new TOKENLink(token); link_new.Next = postfixLink.Next; if (postfixLink.Next != null) { postfixLink.Next.Prev = link_new; } if (((TOKEN <Operator>)postfixLink.Token).Tag.Dimension == 1) { //一元操作符 if (postfixLink.Prev.Prev != null) { link_new.Prev = postfixLink.Prev.Prev; postfixLink.Prev.Prev.Next = link_new; } } else if (((TOKEN <Operator>)postfixLink.Token).Tag.Dimension == 2) { //二元操作符 if (postfixLink.Prev.Prev.Prev != null) { link_new.Prev = postfixLink.Prev.Prev.Prev; postfixLink.Prev.Prev.Prev.Next = link_new; } } postfixLink = link_new; } } //end if } //end while return(((TOKEN <IOperand>)postfixLink.Token).Tag); }
/// <summary> /// 检查标记应用环境 /// </summary> /// <param name="startLink"></param> /// <param name="endLink"></param> private void TokenEnvirAnalyze(TOKENLink startLink, TOKENLink endLink) { TOKENLink curLink = startLink; while (true) { switch (curLink.Token.Type) { case ETokenType.token_operand: if (curLink.Prev != null && (curLink.Prev.Token.Type == ETokenType.token_operand || (curLink.Prev.Token.Type == ETokenType.token_operator && ((TOKEN <Operator>)curLink.Prev.Token).Tag.Type == EOperatorType.RightParen))) { throw new Exception(string.Format("Error! 操作数“{0}”附近有语法错误(索引:{1})", ((TOKEN <IOperand>)curLink.Token).Tag.ToString(), curLink.Token.Index.ToString())); } break; case ETokenType.token_operator: EOperatorType type = ((TOKEN <Operator>)curLink.Token).Tag.Type; switch (type) { case EOperatorType.Positive: //正 case EOperatorType.Negative: //负 if (!(curLink.Next != null && (curLink.Next.Token.Type == ETokenType.token_operand || (curLink.Next.Token.Type == ETokenType.token_operator && ((TOKEN <Operator>)curLink.Next.Token).Tag.Type == EOperatorType.LeftParen)))) { throw new Exception(string.Format("Error! 一元操作符“{0}”附近有语法错误(索引:{1})", ((TOKEN <Operator>)curLink.Token).Tag.Value, curLink.Token.Index.ToString())); } break; case EOperatorType.LeftParen: if (curLink.Prev != null && (curLink.Prev.Token.Type == ETokenType.token_operand || (curLink.Prev.Token.Type == ETokenType.token_operator && ((TOKEN <Operator>)curLink.Prev.Token).Tag.Type == EOperatorType.RightParen))) { throw new Exception(string.Format("Error! 左括弧“{0}”附近有语法错误(索引:{1})", ((TOKEN <Operator>)curLink.Token).Tag.Value, curLink.Token.Index.ToString())); } break; case EOperatorType.RightParen: if (curLink.Prev == null || (curLink.Prev.Token.Type == ETokenType.token_operator && ((TOKEN <Operator>)curLink.Prev.Token).Tag.Type == EOperatorType.LeftParen)) { throw new Exception(string.Format("Error! 右括弧“{0}”附近有语法错误(索引:{1})", ((TOKEN <Operator>)curLink.Token).Tag.Value, curLink.Token.Index.ToString())); } break; default: if (!((curLink.Prev != null && (curLink.Prev.Token.Type == ETokenType.token_operand || (curLink.Prev.Token.Type == ETokenType.token_operator && ((TOKEN <Operator>)curLink.Prev.Token).Tag.Type == EOperatorType.RightParen))) && (curLink.Next != null && (curLink.Next.Token.Type == ETokenType.token_operand || (curLink.Next.Token.Type == ETokenType.token_operator && (((TOKEN <Operator>)curLink.Next.Token).Tag.Type == EOperatorType.LeftParen || ((TOKEN <Operator>)curLink.Next.Token).Tag.Type == EOperatorType.Negative || ((TOKEN <Operator>)curLink.Next.Token).Tag.Type == EOperatorType.Positive)))))) { throw new Exception(string.Format("Error! 二元操作符“{0}”附近有语法错误(索引:{1})", ((TOKEN <Operator>)curLink.Token).Tag.Value, curLink.Token.Index.ToString())); } break; } break; default: break; } if (curLink == endLink) { break; } else { curLink = curLink.Next; } } }
/// <summary> /// 中缀表达式转后缀表达式 /// -1*6+5*(2+3) 转换成 1 - 6 * 5 2 3 + * + /// </summary> /// <param name="startLink"></param> /// <param name="endLink"></param> /// <returns></returns> public TOKENLink InfixToPostfix(TOKENLink startLink, TOKENLink endLink) { //进入此函数的链表 - 只含操作符和操作数 TOKENLink postfixLinkHead = null; TOKENLink postfixLinkTail = null; TOKENLink tempLink = null; TOKENLink curLink = startLink; KeyValueList <IToken, int> tokenList = new KeyValueList <IToken, int>(); int Deep_PRI = 0; //括弧深度优先级 while (true) { if (curLink.Token.Type == ETokenType.token_operand) { //操作数 直接放入后缀链表 TOKENLink link = new TOKENLink(curLink.Token); if (postfixLinkHead == null) { postfixLinkHead = link; postfixLinkTail = link; } else { postfixLinkTail.Next = link; link.Prev = postfixLinkTail; postfixLinkTail = link; } } else { if (((TOKEN <Operator>)curLink.Token).Tag.Type == EOperatorType.LeftParen) { Deep_PRI++; } else if (((TOKEN <Operator>)curLink.Token).Tag.Type == EOperatorType.RightParen) { Deep_PRI--; } else { //将操作符放入临时链表 TOKENLink link_new = new TOKENLink(curLink.Token); tokenList.Add(link_new.Token, Deep_PRI); if (tempLink == null) { tempLink = link_new; } else { tempLink.Next = link_new; link_new.Prev = tempLink; tempLink = link_new; } //判断需要放入后缀链表的项 while (tempLink.Prev != null) { if ((tokenList[tempLink.Prev.Token] > tokenList[tempLink.Token]) || ((tokenList[tempLink.Prev.Token] == tokenList[tempLink.Token]) && (((TOKEN <Operator>)tempLink.Prev.Token).Tag.PRI >= ((TOKEN <Operator>)tempLink.Token).Tag.PRI))) { TOKENLink link_Operator = tempLink.Prev; if (tempLink.Prev.Prev != null) { tempLink.Prev.Prev.Next = tempLink; tempLink.Prev = tempLink.Prev.Prev; } else { tempLink.Prev = null; } postfixLinkTail.Next = link_Operator; link_Operator.Prev = postfixLinkTail; postfixLinkTail = link_Operator; } else { break; } } }// end if } if (curLink == endLink) { break; } curLink = curLink.Next; }// end while TOKENLink link_p = tempLink; while (link_p != null) { tempLink = tempLink.Prev; postfixLinkTail.Next = link_p; link_p.Prev = postfixLinkTail; postfixLinkTail = link_p; link_p = tempLink; } postfixLinkHead.Prev = null; postfixLinkTail.Next = null; return(postfixLinkHead); }
/// <summary> /// 表达式求值 /// </summary> /// <param name="startLink"></param> /// <param name="endLink"></param> /// <returns></returns> public IOperand ExpressionEvaluate(TOKENLink startLink, TOKENLink endLink) { TOKENLink postfixLink = _toolBox.InfixToPostfix(startLink, endLink); TOKENLink link_new = null; IToken token = null; while (postfixLink.Next != null) { postfixLink = postfixLink.Next; if (postfixLink.Token.Type == ETokenType.token_operator) { link_new = null; token = null; EOperatorType type = ((TOKEN <Operator>)postfixLink.Token).Tag.Type; switch (type) { case EOperatorType.Positive: //正 case EOperatorType.Negative: //负 IOperand operand = ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag; if (type == EOperatorType.Negative) { if (operand.Type == EDataType.Dint) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <int>(EDataType.Dint, -((Operand <int>)operand).TValue), postfixLink.Token.Index); } else if (operand.Type == EDataType.Ddouble) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <double>(EDataType.Ddouble, -((Operand <double>)operand).TValue), postfixLink.Token.Index); } } else { token = postfixLink.Prev.Token; } break; case EOperatorType.Plus: case EOperatorType.Minus: if (((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dstring || ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dstring) { if (type == EOperatorType.Plus) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <string>(EDataType.Dstring, ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.ToString() + ((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.ToString()), postfixLink.Token.Index); } else { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <string>(EDataType.Dstring, ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.ToString().Replace(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.ToString(), "")), postfixLink.Token.Index); } } else if (((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Ddouble || ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Ddouble) { if (type == EOperatorType.Plus) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <double>(EDataType.Ddouble, Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Value) + Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Value)), postfixLink.Token.Index); } else { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <double>(EDataType.Ddouble, Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Value) - Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Value)), postfixLink.Token.Index); } } else { if (type == EOperatorType.Plus) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <int>(EDataType.Dint, ((Operand <int>)((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag).TValue + ((Operand <int>)((TOKEN <IOperand>)postfixLink.Prev.Token).Tag).TValue), postfixLink.Token.Index); } else { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <int>(EDataType.Dint, ((Operand <int>)((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag).TValue - ((Operand <int>)((TOKEN <IOperand>)postfixLink.Prev.Token).Tag).TValue), postfixLink.Token.Index); } } break; case EOperatorType.Multiply: if (((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Ddouble || ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Ddouble) { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <double>(EDataType.Ddouble, Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Value) * Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Value)), postfixLink.Token.Index); } else { token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <int>(EDataType.Dint, ((Operand <int>)((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag).TValue * ((Operand <int>)((TOKEN <IOperand>)postfixLink.Prev.Token).Tag).TValue), postfixLink.Token.Index); } break; case EOperatorType.Divide: token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <double>(EDataType.Ddouble, Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Value) / Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Value)), postfixLink.Token.Index); break; case EOperatorType.Mod: token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <double>(EDataType.Ddouble, Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Value) % Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Value)), postfixLink.Token.Index); break; case EOperatorType.LessThan: case EOperatorType.GreaterThan: case EOperatorType.GreaterEqual: case EOperatorType.LessEqual: bool result = false; double first = Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Value); double second = Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Value); switch (type) { case EOperatorType.LessThan: result = first < second; break; case EOperatorType.GreaterThan: result = first > second; break;; case EOperatorType.GreaterEqual: result = first >= second; break; case EOperatorType.LessEqual: result = first <= second; break; } token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <bool>(EDataType.Dbool, result), postfixLink.Token.Index); break; case EOperatorType.Equal: case EOperatorType.NotEqual: bool r = false; if (((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dstring && ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dstring) { if (type == EOperatorType.Equal) { r = ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.ToString().Equals(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.ToString()); } else { r = !((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.ToString().Equals(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.ToString()); } } else if (((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Type == EDataType.Dbool && ((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Type == EDataType.Dbool) { bool f = ((Operand <bool>)((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag).TValue; bool s = ((Operand <bool>)((TOKEN <IOperand>)postfixLink.Prev.Token).Tag).TValue; if (type == EOperatorType.Equal) { r = f == s; } else { r = f != s; } } else { double f = Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Prev.Token).Tag.Value); double s = Convert.ToDouble(((TOKEN <IOperand>)postfixLink.Prev.Token).Tag.Value); if (type == EOperatorType.Equal) { r = f == s; } else { r = f != s; } } token = new TOKEN <IOperand>(ETokenType.token_operand, new Operand <bool>(EDataType.Dbool, r), postfixLink.Token.Index); break; default: break; } if (token != null) { link_new = new TOKENLink(token); link_new.Next = postfixLink.Next; if (postfixLink.Next != null) { postfixLink.Next.Prev = link_new; } if (((TOKEN <Operator>)postfixLink.Token).Tag.Dimension == 1) { //一元操作符 if (postfixLink.Prev.Prev != null) { link_new.Prev = postfixLink.Prev.Prev; postfixLink.Prev.Prev.Next = link_new; } } else if (((TOKEN <Operator>)postfixLink.Token).Tag.Dimension == 2) { //二元操作符 if (postfixLink.Prev.Prev.Prev != null) { link_new.Prev = postfixLink.Prev.Prev.Prev; postfixLink.Prev.Prev.Prev.Next = link_new; } } postfixLink = link_new; } } //end if } //end while return(((TOKEN <IOperand>)postfixLink.Token).Tag); }