/// <summary> /// Parses the expression and builds the token queue for compiling /// </summary> public void Parse() { try { _tokenQueue.Clear(); _ptr = 0; while (IsInBounds()) { string op = ""; int lastptr = _ptr; if (_pstr[_ptr] != ' ') { // Parse enclosed strings if (_pstr[_ptr] == '\'') { bool isStringClosed = false; _ptr++; lastptr = _ptr; StringBuilder tokenbuilder = new StringBuilder(); // check for escaped single-quote and backslash while (IsInBounds()) { if (_pstr[_ptr] == '\\') { tokenbuilder.Append(_pstr.Substring(lastptr, _ptr - lastptr)); char nextchar = _pstr[_ptr + 1]; switch (nextchar) { case '\'': case '\\': tokenbuilder.Append(nextchar); break; default: throw new Exception("Unrecognized escape sequence"); } _ptr++; _ptr++; lastptr = _ptr; } else if ((_pstr[_ptr] == '\'')) { isStringClosed = true; break; } else { _ptr++; } } if (!isStringClosed) { throw new Exception("Unclosed string literal at " + lastptr); } tokenbuilder.Append(_pstr.Substring(lastptr, _ptr - lastptr)); string token = tokenbuilder.ToString(); _tokenQueue.Enqueue(new Token() { Value = token, IsIdent = true, Type = typeof(string) }); _ptr++; } // Parse enclosed dates else if (_pstr[_ptr] == '#') { bool isDateClosed = false; _ptr++; lastptr = _ptr; while (IsInBounds()) { _ptr++; if (_pstr[_ptr] == '#') { isDateClosed = true; break; } } if (!isDateClosed) { throw new Exception("Unclosed date literal at " + lastptr); } string token = _pstr.Substring(lastptr, _ptr - lastptr); DateTime dt = DateTime.Parse(token); _tokenQueue.Enqueue(new Token() { Value = dt, IsIdent = true, Type = typeof(DateTime) }); _ptr++; } else if (_pstr[_ptr] == ',') { bool pe = false; while (_opStack.Count > 0) { if ((string)_opStack.Peek().Value == "(") { OpToken temp = _opStack.Pop(); Token lastToken = _opStack.Peek(); if (lastToken.GetType() == typeof(MemberToken)) { MemberToken lastmember = (MemberToken)lastToken; if (lastmember != null) { lastmember.ArgCount++; } } _opStack.Push(temp); pe = true; break; } else { OpToken popToken = _opStack.Pop(); _tokenQueue.Enqueue(popToken); } } if (!pe) { throw new Exception("Parenthesis mismatch"); } _ptr++; } // Member accessor else if (_pstr[_ptr] == '.') { if (_opStack.Count > 0) { OpToken sc = _opStack.Peek(); // if the last operator was also a Member accessor pop it on the tokenQueue if ((string)sc.Value == ".") { OpToken popToken = _opStack.Pop(); _tokenQueue.Enqueue(popToken); } } _opStack.Push(new MemberToken()); _ptr++; } // Parse hexadecimal literals else if (HelperMethods.IsHexStart(_pstr, _ptr)) { bool isNeg = false; if (_pstr[_ptr] == '-') { isNeg = true; _ptr++; lastptr = _ptr; } //skip 0x _ptr += 2; // Number identifiers start with a number and may contain numbers and decimals while (IsInBounds() && (HelperMethods.IsHex(_pstr, _ptr) || _pstr[_ptr] == 'L')) { _ptr++; } string token = _pstr.Substring(lastptr, _ptr - lastptr); Type ntype = typeof(System.Int32); object val = null; if (token.EndsWith("L")) { ntype = typeof(System.Int64); token = token.Remove(token.Length - 1, 1); } var y = 10; switch (ntype.Name) { case "Int32": val = isNeg ? -Convert.ToInt32(token, 16) : Convert.ToInt32(token, 16); break; case "Int64": val = isNeg ? -Convert.ToInt64(token, 16) : Convert.ToInt64(token, 16); break; } _tokenQueue.Enqueue(new Token() { Value = val, IsIdent = true, Type = ntype }); } // Parse numbers else if (HelperMethods.IsANumber(_pstr, _ptr)) { // Number identifiers start with a number and may contain numbers and decimals while (IsInBounds() && (HelperMethods.IsANumber(_pstr, _ptr) || _pstr[_ptr] == '.' || _pstr[_ptr] == 'd' || _pstr[_ptr] == 'f' || _pstr[_ptr] == 'L')) { _ptr++; } string token = _pstr.Substring(lastptr, _ptr - lastptr); Type ntype = typeof(System.Int32); object val = null; if (token.Contains('.')) { ntype = typeof(System.Double); } if (token.EndsWith("d") || token.EndsWith("f") || token.EndsWith("L")) { if (token.EndsWith("d")) { ntype = typeof(System.Double); } if (token.EndsWith("f")) { ntype = typeof(System.Single); } if (token.EndsWith("L")) { ntype = typeof(System.Int64); } token = token.Remove(token.Length - 1, 1); } switch (ntype.Name) { case "Int32": val = int.Parse(token); break; case "Int64": val = long.Parse(token); break; case "Double": val = double.Parse(token); break; case "Single": val = float.Parse(token); break; } _tokenQueue.Enqueue(new Token() { Value = val, IsIdent = true, Type = ntype }); } // Test for identifier else if (HelperMethods.IsAlpha(_pstr[_ptr]) || (_pstr[_ptr] == '_')) { _ptr++; while (IsInBounds() && (HelperMethods.IsAlpha(_pstr[_ptr]) || HelperMethods.IsNumeric(_pstr, _ptr))) { _ptr++; } string token = _pstr.Substring(lastptr, _ptr - lastptr); MemberToken mToken = null; if (_opStack.Count > 0) { OpToken opToken = _opStack.Peek(); if (opToken.GetType() == typeof(MemberToken)) { mToken = (MemberToken)opToken; } } if ((mToken != null) && (mToken.Name == null)) { mToken.Name = token; } else if (_typeRegistry.ContainsKey(token)) { if (_typeRegistry[token].GetType().Name == "RuntimeType") { _tokenQueue.Enqueue(new Token() { Value = ((Type)_typeRegistry[token]).UnderlyingSystemType, IsType = true }); } else { _tokenQueue.Enqueue(new Token() { Value = _typeRegistry[token], IsType = true }); } } else { if ((token.ToLower() == "null")) { _tokenQueue.Enqueue(new Token() { Value = null, IsIdent = true, Type = typeof(object) }); } else if ((token.ToLower() == "true") || (token.ToLower() == "false")) { _tokenQueue.Enqueue(new Token() { Value = Boolean.Parse(token), IsIdent = true, Type = typeof(Boolean) }); } else { throw new Exception(string.Format("Unknown type or identifier '{0}'", token)); } } } else if (_pstr[_ptr] == '[') { _opStack.Push(new OpToken() { Value = "[", Ptr = _ptr + 1 }); _ptr++; } else if (_pstr[_ptr] == ']') { bool pe = false; // Until the token at the top of the stack is a left bracket, // pop operators off the stack onto the output queue while (_opStack.Count > 0) { OpToken sc = _opStack.Peek(); if ((string)sc.Value == "[") { OpToken temp = _opStack.Pop(); if (_opStack.Count > 0) { Token lastToken = _opStack.Peek(); if (lastToken.GetType() == typeof(MemberToken)) { MemberToken lastmember = (MemberToken)lastToken; // check if there was anything significant between the opening paren and the closing paren // If so, then we have an argument... This isn't the best approach perhaps, but it works... if (_pstr.Substring(sc.Ptr, _ptr - sc.Ptr).Trim().Length > 0) { lastmember.ArgCount++; } } } _opStack.Push(temp); pe = true; break; } else { OpToken popToken = _opStack.Pop(); _tokenQueue.Enqueue(popToken); } } // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. if (!pe) { throw new Exception("Parenthesis mismatch"); } // Pop the left parenthesis from the stack, but not onto the output queue. OpToken lopToken = _opStack.Pop(); //tokenQueue.Enqueue(lopToken); _ptr++; } else if (_pstr[_ptr] == '(') { int curptr = _ptr; while (_pstr[curptr] != ')') { curptr++; } string typeName = _pstr.Substring(lastptr + 1, curptr - lastptr - 1).Trim(); Type t; if (_typeRegistry.ContainsKey(typeName)) { _tokenQueue.Enqueue(new Token() { Value = "(" + typeName + ")", IsCast = true, Type = (Type)_typeRegistry[typeName] }); _ptr = curptr + 1; } else if ((t = Type.GetType(typeName)) != null) { _tokenQueue.Enqueue(new Token() { Value = "(" + t.Name + ")", IsCast = true, Type = t }); _ptr = curptr + 1; } else { _opStack.Push(new OpToken() { Value = "(", Ptr = _ptr + 1 }); _ptr++; } } else if (_pstr[_ptr] == ')') { bool pe = false; //int poppedtokens = 0; // Until the token at the top of the stack is a left parenthesis, // pop operators off the stack onto the output queue while (_opStack.Count > 0) { OpToken sc = _opStack.Peek(); if ((string)sc.Value == "(") { OpToken temp = _opStack.Pop(); if (_opStack.Count > 0) { Token lastToken = _opStack.Peek(); if (lastToken.GetType() == typeof(MemberToken)) { MemberToken lastmember = (MemberToken)lastToken; // check if there was anything significant between the opening paren and the closing paren // If so, then we have an argument... This isn't the best approach perhaps, but it works... if (_pstr.Substring(sc.Ptr, _ptr - sc.Ptr).Trim().Length > 0) { lastmember.ArgCount++; } } } _opStack.Push(temp); pe = true; break; } else { OpToken popToken = _opStack.Pop(); _tokenQueue.Enqueue(popToken); // poppedtokens++; } } // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. if (!pe) { throw new Exception("Parenthesis mismatch"); } // Pop the left parenthesis from the stack, but not onto the output queue. _opStack.Pop(); //If the token at the top of the stack is a function token, pop it onto the output queue. if (_opStack.Count > 0) { OpToken popToken = _opStack.Peek(); if ((string)popToken.Value == ".") { popToken = _opStack.Pop(); _tokenQueue.Enqueue(popToken); } } _ptr++; } else if ((op = _operators.IsOperator(_pstr, ref _ptr)) != null) { while (_opStack.Count > 0) { OpToken sc = _opStack.Peek(); if (_operators.IsOperator((string)sc.Value) && ((_operators[op].LeftAssoc && (_operators[op].Precedence <= _operators[(string)sc.Value].Precedence)) || (_operators[op].Precedence < _operators[(string)sc.Value].Precedence)) ) { OpToken popToken = _opStack.Pop(); _tokenQueue.Enqueue(popToken); } else { break; } } _opStack.Push(new OpToken() { Value = op }); _ptr++; } else { throw new Exception("Unexpected token '" + _pstr[_ptr].ToString() + "'"); } } else { _ptr++; } } while (_opStack.Count > 0) { OpToken sc = _opStack.Peek(); if ((string)sc.Value == "(" || (string)sc.Value == ")") { throw new Exception("Paren mismatch"); } sc = _opStack.Pop(); _tokenQueue.Enqueue(sc); } } catch (Exception ex) { throw new Exception(String.Format("Parser error at position {0}: {1}", _ptr, ex.Message), ex); } }
/// <summary> /// Parses the expression and builds the token queue for compiling /// </summary> public void Parse(bool isScope = false) { try { fTokenQueue.Clear(); fPtr = 0; while (IsInBounds()) { string op = ""; int lastptr = fPtr; if (fPstr[fPtr] != ' ') { // Parse enclosed strings if (fPstr[fPtr] == '\'') { bool isStringClosed = false; fPtr++; lastptr = fPtr; var tokenbuilder = new StringBuilder(); // check for escaped single-quote and backslash while (IsInBounds()) { if (fPstr[fPtr] == '\\') { tokenbuilder.Append(fPstr.Substring(lastptr, fPtr - lastptr)); char nextchar = fPstr[fPtr + 1]; switch (nextchar) { case '\'': case '\\': tokenbuilder.Append(nextchar); break; default: TkDebug.ThrowToolkitException("无法识别的转义字符", this); break; } fPtr++; fPtr++; lastptr = fPtr; } else if ((fPstr[fPtr] == '\'')) { isStringClosed = true; break; } else { fPtr++; } } if (!isStringClosed) { TkDebug.ThrowToolkitException(string.Format(ObjectUtil.SysCulture, "没有关闭的字符串,位置在{0}", lastptr), this); } tokenbuilder.Append(fPstr.Substring(lastptr, fPtr - lastptr)); string token = tokenbuilder.ToString(); fTokenQueue.Enqueue(new Token() { Value = token, IsIdent = true, Type = typeof(string) }); fPtr++; } // Parse enclosed dates else if (fPstr[fPtr] == '#') { bool isDateClosed = false; fPtr++; lastptr = fPtr; while (IsInBounds()) { fPtr++; if (fPstr[fPtr] == '#') { isDateClosed = true; break; } } if (!isDateClosed) { TkDebug.ThrowToolkitException(string.Format(ObjectUtil.SysCulture, "未关闭的日期,位置在{0}", lastptr), this); } string token = fPstr.Substring(lastptr, fPtr - lastptr); DateTime dt; if (token == "Now") { dt = DateTime.Now; } else { dt = DateTime.Parse(token, ObjectUtil.SysCulture); } fTokenQueue.Enqueue(new Token() { Value = dt, IsIdent = true, Type = typeof(DateTime) }); fPtr++; } // ArgSeparator else if (fPstr[fPtr] == ',') { bool pe = false; while (fOpStack.Count > 0) { if ((string)fOpStack.Peek().Value == "(") { OpToken temp = fOpStack.Pop(); Token lastToken = fOpStack.Peek(); if (lastToken.GetType() == typeof(MemberToken)) { MemberToken lastmember = (MemberToken)lastToken; if (lastmember != null) { lastmember.ArgCount++; } } fOpStack.Push(temp); pe = true; break; } else { OpToken popToken = fOpStack.Pop(); fTokenQueue.Enqueue(popToken); } } if (!pe) { TkDebug.ThrowToolkitException("括号不匹配", this); } fPtr++; } // Member accessor else if (fPstr[fPtr] == '.') { if (fOpStack.Count > 0) { OpToken sc = fOpStack.Peek(); // if the last operator was also a Member accessor pop it on the tokenQueue if ((string)sc.Value == ".") { OpToken popToken = fOpStack.Pop(); fTokenQueue.Enqueue(popToken); } } fOpStack.Push(new MemberToken()); fPtr++; } // Parse hexadecimal literals else if (HelperMethods.IsHexStart(fPstr, fPtr)) { bool isNeg = false; if (fPstr[fPtr] == '-') { isNeg = true; fPtr++; lastptr = fPtr; } //skip 0x fPtr += 2; // Number identifiers start with a number and may contain numbers and decimals while (IsInBounds() && (HelperMethods.IsHex(fPstr, fPtr) || fPstr[fPtr] == 'L')) { fPtr++; } string token = fPstr.Substring(lastptr, fPtr - lastptr); Type ntype = typeof(System.Int32); object val = null; if (token.EndsWith("L", StringComparison.CurrentCulture)) { ntype = typeof(System.Int64); token = token.Remove(token.Length - 1, 1); } switch (ntype.Name) { case "Int32": val = isNeg ? -Convert.ToInt32(token, 16) : Convert.ToInt32(token, 16); break; case "Int64": val = isNeg ? -Convert.ToInt64(token, 16) : Convert.ToInt64(token, 16); break; } fTokenQueue.Enqueue(new Token() { Value = val, IsIdent = true, Type = ntype }); } // Parse numbers else if (HelperMethods.IsANumber(fPstr, fPtr)) { bool isDecimal = false; int suffixLength = 0; // Number identifiers start with a number and may contain numbers and decimals while (IsInBounds()) { if (fPstr[fPtr] == 'l' || fPstr[fPtr] == 'L' || fPstr[fPtr] == 'u' || fPstr[fPtr] == 'U') { if (isDecimal) { TkDebug.ThrowToolkitException("不是期望的decimal结束符", this); } //if (suffixLength == 0) suffixStart = _ptr; if (suffixLength == 1) { fPtr++; break; } suffixLength++; } else if (fPstr[fPtr] == '.') { if (isDecimal) { break; } isDecimal = true; } else if (fPstr[fPtr] == 'd' || fPstr[fPtr] == 'D' || fPstr[fPtr] == 'f' || fPstr[fPtr] == 'F' || fPstr[fPtr] == 'm' || fPstr[fPtr] == 'M') { suffixLength++; fPtr++; break; } else if (!HelperMethods.IsANumber(fPstr, fPtr)) { break; } fPtr++; } string token = fPstr.Substring(lastptr, fPtr - lastptr); string suffix = ""; Type ntype = null; object val = null; if (suffixLength > 0) { suffix = token.Substring(token.Length - suffixLength); token = token.Substring(0, token.Length - suffixLength); switch (suffix.ToLower(ObjectUtil.SysCulture)) { case "d": ntype = typeof(Double); val = double.Parse(token, CultureInfo.InvariantCulture); break; case "f": ntype = typeof(Single); val = float.Parse(token, CultureInfo.InvariantCulture); break; case "m": ntype = typeof(Decimal); val = decimal.Parse(token, CultureInfo.InvariantCulture); break; case "l": ntype = typeof(Int64); val = long.Parse(token, CultureInfo.InvariantCulture); break; case "u": ntype = typeof(UInt32); val = uint.Parse(token, CultureInfo.InvariantCulture); break; case "ul": case "lu": ntype = typeof(UInt64); val = ulong.Parse(token, CultureInfo.InvariantCulture); break; } } else { if (isDecimal) { ntype = typeof(Double); val = double.Parse(token, CultureInfo.InvariantCulture); } else { ntype = typeof(Int32); val = int.Parse(token, CultureInfo.InvariantCulture); } } fTokenQueue.Enqueue(new Token() { Value = val, IsIdent = true, Type = ntype }); } // Test for identifier else if (HelperMethods.IsAlpha(fPstr[fPtr]) || (fPstr[fPtr] == '_')) { fPtr++; while (IsInBounds() && (HelperMethods.IsAlpha(fPstr[fPtr]) || (fPstr[fPtr] == '_') || HelperMethods.IsNumeric(fPstr, fPtr))) { fPtr++; } string token = fPstr.Substring(lastptr, fPtr - lastptr); MemberToken mToken = null; if (fOpStack.Count > 0) { OpToken opToken = fOpStack.Peek(); if (opToken.GetType() == typeof(MemberToken)) { mToken = (MemberToken)opToken; } } if ((mToken != null) && (mToken.Name == null)) { mToken.Name = token; } else if (TypeRegistry.ContainsKey(token)) { if (TypeRegistry[token].GetType().Name == "RuntimeType") { fTokenQueue.Enqueue(new Token() { Value = ((Type)TypeRegistry[token]).UnderlyingSystemType, IsType = true }); } else { fTokenQueue.Enqueue(new Token() { Value = TypeRegistry[token], IsType = true }); } } else { if ((token == "null")) { fTokenQueue.Enqueue(new Token() { Value = null, IsIdent = true, Type = typeof(object) }); } else if ((token == "true") || (token == "false")) { fTokenQueue.Enqueue(new Token() { Value = Boolean.Parse(token), IsIdent = true, Type = typeof(Boolean) }); } else { if (Global != null) { fTokenQueue.Enqueue(new Token() { Value = Global, IsType = true }); } else { if (isScope) { fTokenQueue.Enqueue(new Token() { IsScope = true }); } else { //_tokenQueue.Enqueue(new Token() { IsIdent = true, Value = token }); TkDebug.ThrowToolkitException(string.Format(ObjectUtil.SysCulture, "未知的类型或标识符'{0}'", token), this); } } if (fOpStack.Count > 0) { OpToken sc = fOpStack.Peek(); // if the last operator was also a Member accessor pop it on the tokenQueue if ((string)sc.Value == ".") { OpToken popToken = fOpStack.Pop(); fTokenQueue.Enqueue(popToken); } } fOpStack.Push(new MemberToken()); fPtr -= token.Length; } } } else if (fPstr[fPtr] == '[') { fOpStack.Push(new OpToken() { Value = "[", Ptr = fPtr + 1 }); fPtr++; } else if (fPstr[fPtr] == ']') { bool pe = false; // Until the token at the top of the stack is a left bracket, // pop operators off the stack onto the output queue while (fOpStack.Count > 0) { OpToken sc = fOpStack.Peek(); if ((string)sc.Value == "[") { OpToken temp = fOpStack.Pop(); if (fOpStack.Count > 0) { Token lastToken = fOpStack.Peek(); if (lastToken.GetType() == typeof(MemberToken)) { MemberToken lastmember = (MemberToken)lastToken; // check if there was anything significant between the opening paren and the closing paren // If so, then we have an argument... This isn't the best approach perhaps, but it works... if (fPstr.Substring(sc.Ptr, fPtr - sc.Ptr).Trim().Length > 0) { lastmember.ArgCount++; } } } fOpStack.Push(temp); pe = true; break; } else { OpToken popToken = fOpStack.Pop(); fTokenQueue.Enqueue(popToken); } } // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. if (!pe) { TkDebug.ThrowToolkitException("括号不匹配", this); } // Pop the left parenthesis from the stack, but not onto the output queue. fOpStack.Pop(); //tokenQueue.Enqueue(lopToken); fPtr++; } else if (fPstr[fPtr] == '(') { int curptr = fPtr; int depth = 0; var containsComma = false; while (IsInBounds()) { if (fPstr[fPtr] == '(') { depth++; } if (fPstr[fPtr] == ')') { depth--; } if (fPstr[fPtr] == ',') { containsComma = true; } fPtr++; if (depth == 0) { break; } } fPtr--; if (depth != 0) { TkDebug.ThrowToolkitException("括号不匹配", this); } string token = fPstr.Substring(lastptr + 1, fPtr - lastptr - 1).Trim(); Type t; bool isCast = false; if (!containsComma) { if (TypeRegistry.ContainsKey(token)) { fTokenQueue.Enqueue(new Token() { Value = "(" + token + ")", IsCast = true, Type = (Type)TypeRegistry[token] }); //_ptr = curptr + 1; isCast = true; } else if ((t = Type.GetType(token)) != null) { fTokenQueue.Enqueue(new Token() { Value = "(" + t.Name + ")", IsCast = true, Type = t }); // _ptr = curptr + 1; isCast = true; } } if (!isCast) { fOpStack.Push(new OpToken() { Value = "(", Ptr = curptr + 1 }); fPtr = curptr + 1; } } else if (fPstr[fPtr] == ')') { bool pe = false; //int poppedtokens = 0; // Until the token at the top of the stack is a left parenthesis, // pop operators off the stack onto the output queue while (fOpStack.Count > 0) { OpToken sc = fOpStack.Peek(); if ((string)sc.Value == "(") { OpToken temp = fOpStack.Pop(); if (fOpStack.Count > 0) { Token lastToken = fOpStack.Peek(); if (lastToken.GetType() == typeof(MemberToken)) { MemberToken lastmember = (MemberToken)lastToken; // check if there was anything significant between the opening paren and the closing paren // If so, then we have an argument... This isn't the best approach perhaps, but it works... if (fPstr.Substring(sc.Ptr, fPtr - sc.Ptr).Trim().Length > 0) { lastmember.ArgCount++; } } } fOpStack.Push(temp); pe = true; break; } else { OpToken popToken = fOpStack.Pop(); fTokenQueue.Enqueue(popToken); // poppedtokens++; } } // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. if (!pe) { TkDebug.ThrowToolkitException("括号不匹配", this); } // Pop the left parenthesis from the stack, but not onto the output queue. fOpStack.Pop(); //If the token at the top of the stack is a function token, pop it onto the output queue. if (fOpStack.Count > 0) { OpToken popToken = fOpStack.Peek(); if ((string)popToken.Value == ".") { popToken = fOpStack.Pop(); popToken.IsFunction = true; fTokenQueue.Enqueue(popToken); } } fPtr++; } //else if (_pstr[_ptr] == '=' && _pstr[_ptr + 1] == '>') //{ // _ptr++; // _ptr++; //} else if ((op = fOperators.IsOperator(fPstr, ref fPtr)) != null) { while (fOpStack.Count > 0) { OpToken sc = fOpStack.Peek(); if (fOperators.IsOperator((string)sc.Value) && ((fOperators[op].LeftAssoc && (fOperators[op].Precedence <= fOperators[(string)sc.Value].Precedence)) || (fOperators[op].Precedence < fOperators[(string)sc.Value].Precedence)) ) { OpToken popToken = fOpStack.Pop(); fTokenQueue.Enqueue(popToken); } else { break; } } fOpStack.Push(new OpToken() { Value = op }); fPtr++; } else { TkDebug.ThrowToolkitException(string.Format(ObjectUtil.SysCulture, "不是期望的标识符 '{0}'", fPstr[fPtr]), this); } } else { fPtr++; } } while (fOpStack.Count > 0) { OpToken sc = fOpStack.Peek(); if ((string)sc.Value == "(" || (string)sc.Value == ")") { TkDebug.ThrowToolkitException("括号不匹配", this); } sc = fOpStack.Pop(); fTokenQueue.Enqueue(sc); } } catch (Exception ex) { TkDebug.ThrowToolkitException(String.Format(ObjectUtil.SysCulture, "分析错误,位置在{0}: {1}", fPtr, ex.Message), ex, this); } }