internal static void NormalizeSpace(ProcessingContext context) { StackFrame topArg = context.TopArg; StringBuilder builder = new StringBuilder(); while (topArg.basePtr <= topArg.endPtr) { char[] trimChars = new char[] { ' ', '\t', '\r', '\n' }; string str = context.PeekString(topArg.basePtr).Trim(trimChars); bool flag = false; builder.Length = 0; for (int i = 0; i < str.Length; i++) { char c = str[i]; if (XPathCharTypes.IsWhitespace(c)) { if (!flag) { builder.Append(' '); flag = true; } } else { builder.Append(c); flag = false; } } context.SetValue(context, topArg.basePtr, builder.ToString()); topArg.basePtr++; } }
private void TokenizeNumber() { XPathTokenID id = XPathTokenID.Integer; // Read all the digits for (; XPathCharTypes.IsDigit(this.ch); AdvanceChar()) { ; } if (this.ch == '.') { AdvanceChar(); if (XPathCharTypes.IsDigit(this.ch)) { id = XPathTokenID.Decimal; // Read all the digits after the decimal point for (; XPathCharTypes.IsDigit(this.ch); AdvanceChar()) { ; } } } PutbackChar(); // The converted double double d = QueryValueModel.Double(CurrentSubstring()); // flip the sign if we're negative token.Set(id, d); }
private void TokenizeNumber() { XPathTokenID integer = XPathTokenID.Integer; while (XPathCharTypes.IsDigit(this.ch)) { this.AdvanceChar(); } if (this.ch == '.') { this.AdvanceChar(); if (XPathCharTypes.IsDigit(this.ch)) { integer = XPathTokenID.Decimal; while (XPathCharTypes.IsDigit(this.ch)) { this.AdvanceChar(); } } } this.PutbackChar(); double number = QueryValueModel.Double(this.CurrentSubstring()); this.token.Set(integer, number); }
internal static void NormalizeSpace(ProcessingContext context) { StackFrame argStr = context.TopArg; StringBuilder builder = new StringBuilder(); while (argStr.basePtr <= argStr.endPtr) { char[] whitespace = new char[] { ' ', '\t', '\r', '\n' }; string str = context.PeekString(argStr.basePtr).Trim(whitespace); bool eatingWhitespace = false; builder.Length = 0; for (int i = 0; i < str.Length; ++i) { char c = str[i]; if (XPathCharTypes.IsWhitespace(c)) { if (!eatingWhitespace) { builder.Append(' '); eatingWhitespace = true; } } else { builder.Append(c); eatingWhitespace = false; } } context.SetValue(context, argStr.basePtr, builder.ToString()); argStr.basePtr++; } }
private XPathParser.QName GetQName() { string name1 = GetNCName(); // Return an empty QName if we can't read one if (name1 == null) { return(new XPathParser.QName(string.Empty, string.Empty)); } // Pull the '$' off a variable if (name1[0] == '$') { name1 = name1.Substring(1); } // See if there's a second part to the QName if (PeekChar() == ':' && XPathCharTypes.IsNCNameStart(PeekChar(2))) { AdvanceChar(); ConsumeToken(); return(new XPathParser.QName(name1, GetNCName())); } else { return(new XPathParser.QName(string.Empty, name1)); } }
private void ConsumeWhitespace() { while (XPathCharTypes.IsWhitespace(this.PeekChar())) { this.AdvanceChar(); } this.ConsumeToken(); }
private void ConsumeWhitespace() { // Advance over all whitespace characters and consume the all recently read characters for (; XPathCharTypes.IsWhitespace(PeekChar()); AdvanceChar()) { ; } ConsumeToken(); }
private string GetNCName() { if (!XPathCharTypes.IsNCNameStart(this.PeekChar())) { return(null); } this.AdvanceChar(); while (XPathCharTypes.IsNCName(this.PeekChar())) { this.AdvanceChar(); } string str = this.CurrentSubstring(); this.ConsumeToken(); return(str); }
private XPathParser.QName GetQName() { string nCName = this.GetNCName(); if (nCName == null) { return(new XPathParser.QName(string.Empty, string.Empty)); } if (nCName[0] == '$') { nCName = nCName.Substring(1); } if ((this.PeekChar() == ':') && XPathCharTypes.IsNCNameStart(this.PeekChar(2))) { this.AdvanceChar(); this.ConsumeToken(); return(new XPathParser.QName(nCName, this.GetNCName())); } return(new XPathParser.QName(string.Empty, nCName)); }
private string GetNCName() { // Make sure we're starting an NCName if (XPathCharTypes.IsNCNameStart(PeekChar())) { AdvanceChar(); // Read all the NCName characters for (; XPathCharTypes.IsNCName(PeekChar()); AdvanceChar()) { ; } // Extract, consume, and return the NCName string name = CurrentSubstring(); ConsumeToken(); return(name); } else { return(null); } }
private void TokenizeQName() { while (XPathCharTypes.IsNCName(this.PeekChar())) { this.AdvanceChar(); } string prefix = this.CurrentSubstring(); XPathTokenID unknown = XPathTokenID.Unknown; XPathParser.QName qname = new XPathParser.QName("", ""); if ((this.PeekChar() == ':') && (this.PeekChar(2) != ':')) { this.AdvanceChar(); this.ConsumeToken(); this.AdvanceChar(); if (XPathCharTypes.IsNCNameStart(this.ch)) { while (XPathCharTypes.IsNCName(this.PeekChar())) { this.AdvanceChar(); } unknown = XPathTokenID.NameTest; qname = new XPathParser.QName(prefix, this.CurrentSubstring()); } else if (this.ch == '*') { unknown = XPathTokenID.NameWildcard; qname = new XPathParser.QName(prefix, QueryDataModel.Wildcard); } else { this.ThrowError(QueryCompileError.InvalidNCName, (this.ch == '\0') ? "" : this.CurrentSubstring()); } } else { unknown = XPathTokenID.NameTest; qname = new XPathParser.QName(string.Empty, prefix); } this.ConsumeWhitespace(); if (this.IsSpecialPrev()) { this.token.Set(this.GetNamedOperator(qname)); } else if (qname.Prefix.Length == 0) { if (this.PeekChar() == '(') { unknown = this.GetNodeTypeOrFunction(qname); if (unknown != XPathTokenID.Function) { this.token.Set(unknown); } else { this.token.Set(unknown, qname); } } else if ((this.PeekChar() == ':') && (this.PeekChar(2) == ':')) { this.token.Set(this.GetAxisName(qname)); } else { this.token.Set(unknown, qname); } } else { if (this.PeekChar() == '(') { unknown = XPathTokenID.Function; } this.token.Set(unknown, qname); } }
internal bool MoveNext() { this.previousID = this.token.TokenID; if (!this.AdvanceChar()) { return(false); } if (XPathCharTypes.IsNCNameStart(this.ch)) { this.TokenizeQName(); } else if (XPathCharTypes.IsDigit(this.ch)) { this.TokenizeNumber(); } else { switch (this.ch) { case '!': if (this.PeekChar() != '=') { this.ThrowError(QueryCompileError.UnsupportedOperator, this.CurrentSubstring()); } else { this.AdvanceChar(); this.token.Set(XPathTokenID.Neq); } goto Label_03FB; case '"': this.TokenizeLiteral('"'); goto Label_03FB; case '$': { XPathParser.QName qName = this.GetQName(); if ((qName.Prefix.Length == 0) && (qName.Name.Length == 0)) { this.AdvanceChar(); this.ThrowError(QueryCompileError.InvalidVariable, (this.ch == '\0') ? string.Empty : this.CurrentSubstring()); } this.token.Set(XPathTokenID.Variable, qName); goto Label_03FB; } case '\'': this.TokenizeLiteral('\''); goto Label_03FB; case '(': this.token.Set(XPathTokenID.LParen); goto Label_03FB; case ')': this.token.Set(XPathTokenID.RParen); goto Label_03FB; case '*': if (!this.IsSpecialPrev()) { this.token.Set(XPathTokenID.Wildcard, new XPathParser.QName(string.Empty, QueryDataModel.Wildcard)); } else { this.token.Set(XPathTokenID.Multiply); } goto Label_03FB; case '+': this.token.Set(XPathTokenID.Plus); goto Label_03FB; case ',': this.token.Set(XPathTokenID.Comma); goto Label_03FB; case '-': this.token.Set(XPathTokenID.Minus); goto Label_03FB; case '.': if (this.PeekChar() != '.') { if (XPathCharTypes.IsDigit(this.PeekChar())) { this.TokenizeNumber(); } else { this.token.Set(XPathTokenID.Period); } } else { this.AdvanceChar(); this.token.Set(XPathTokenID.DblPeriod); } goto Label_03FB; case '/': if (this.PeekChar() != '/') { this.token.Set(XPathTokenID.Slash); } else { this.AdvanceChar(); this.token.Set(XPathTokenID.DblSlash); } goto Label_03FB; case ':': if (this.PeekChar() != ':') { this.ThrowError(QueryCompileError.UnexpectedToken, this.CurrentSubstring()); } else { this.AdvanceChar(); this.token.Set(XPathTokenID.DblColon); } goto Label_03FB; case '<': if (this.PeekChar() != '=') { this.token.Set(XPathTokenID.Lt); } else { this.AdvanceChar(); this.token.Set(XPathTokenID.Lte); } goto Label_03FB; case '=': this.token.Set(XPathTokenID.Eq); goto Label_03FB; case '>': if (this.PeekChar() != '=') { this.token.Set(XPathTokenID.Gt); } else { this.AdvanceChar(); this.token.Set(XPathTokenID.Gte); } goto Label_03FB; case '@': this.token.Set(XPathTokenID.AtSign); goto Label_03FB; case '[': this.token.Set(XPathTokenID.LBracket); goto Label_03FB; case ']': this.token.Set(XPathTokenID.RBracket); goto Label_03FB; case '|': this.token.Set(XPathTokenID.Pipe); goto Label_03FB; } this.token.Set(XPathTokenID.Unknown); } Label_03FB: this.ConsumeWhitespace(); return(true); }
private void TokenizeQName() { for (; XPathCharTypes.IsNCName(PeekChar()); AdvanceChar()) { ; } string name1 = this.CurrentSubstring(); XPathTokenID id = XPathTokenID.Unknown; XPathParser.QName qname = new XPathParser.QName("", ""); if (PeekChar() == ':' && PeekChar(2) != ':') { AdvanceChar(); ConsumeToken(); AdvanceChar(); if (XPathCharTypes.IsNCNameStart(this.ch)) { // It's a full QName for (; XPathCharTypes.IsNCName(PeekChar()); AdvanceChar()) { ; } id = XPathTokenID.NameTest; qname = new XPathParser.QName(name1, this.CurrentSubstring()); } else if (this.ch == '*') { // We've got a wildcard id = XPathTokenID.NameWildcard; qname = new XPathParser.QName(name1, QueryDataModel.Wildcard); } else { ThrowError(QueryCompileError.InvalidNCName, this.ch == char.MinValue ? "" : CurrentSubstring()); } } else { // It's a name test without a prefix id = XPathTokenID.NameTest; qname = new XPathParser.QName(string.Empty, name1); } // Handle special cases ConsumeWhitespace(); if (IsSpecialPrev()) { // If we're in the the first special case of the lexer, a qname MUST // be a NamedOperator token.Set(GetNamedOperator(qname)); return; } else if (qname.Prefix.Length == 0) { if (this.PeekChar() == '(') { // An NCName followed by a '(' MUST be eiter a node type or function name id = GetNodeTypeOrFunction(qname); if (id != XPathTokenID.Function) { token.Set(id); } else { token.Set(id, qname); } } else if (this.PeekChar() == ':' && this.PeekChar(2) == ':') { // An NCName followed by a '::' MUST be an axis token.Set(GetAxisName(qname)); } else { token.Set(id, qname); } } else { if (this.PeekChar() == '(') { id = XPathTokenID.Function; } token.Set(id, qname); } }
// Move to the next token // This updates the values in the token instance and returns true if successful. internal bool MoveNext() { // Hold onto the ID of the last token. // It will be needed by some of the special cases. this.previousID = this.token.TokenID; // If there are no more characters, we can't get another token. if (!AdvanceChar()) { return(false); } if (XPathCharTypes.IsNCNameStart(this.ch)) { // Extract a QName if we've got the start of an NCName TokenizeQName(); } else if (XPathCharTypes.IsDigit(this.ch)) { // Extract a number TokenizeNumber(); } else { // Everything else is a single/double character token, or a variable. switch (this.ch) { case '(': token.Set(XPathTokenID.LParen); break; case ')': token.Set(XPathTokenID.RParen); break; case '[': token.Set(XPathTokenID.LBracket); break; case ']': token.Set(XPathTokenID.RBracket); break; case '.': // Watch for a double period if (PeekChar() == '.') { AdvanceChar(); token.Set(XPathTokenID.DblPeriod); } else { // Check if the period is the start of a number if (XPathCharTypes.IsDigit(PeekChar())) { TokenizeNumber(); } else { token.Set(XPathTokenID.Period); } } break; case '@': token.Set(XPathTokenID.AtSign); break; case ',': token.Set(XPathTokenID.Comma); break; case ':': // Only a double colon is permitted. // The single colon part of the QName is consumed in TokenizeQName if it is valid if (PeekChar() == ':') { AdvanceChar(); token.Set(XPathTokenID.DblColon); } else { ThrowError(QueryCompileError.UnexpectedToken, CurrentSubstring()); } break; case '/': // Check for a double slash if (PeekChar() == '/') { AdvanceChar(); token.Set(XPathTokenID.DblSlash); } else { token.Set(XPathTokenID.Slash); } break; case '|': token.Set(XPathTokenID.Pipe); break; case '+': token.Set(XPathTokenID.Plus); break; case '-': token.Set(XPathTokenID.Minus); break; case '=': token.Set(XPathTokenID.Eq); break; case '!': // This can only be the start of a '!=' // 'not' is a negation in XPath if (PeekChar() == '=') { AdvanceChar(); token.Set(XPathTokenID.Neq); } else { ThrowError(QueryCompileError.UnsupportedOperator, CurrentSubstring()); } break; case '<': // Watch for '<=' if (PeekChar() == '=') { AdvanceChar(); token.Set(XPathTokenID.Lte); } else { token.Set(XPathTokenID.Lt); } break; case '>': // Watch for '>=' if (PeekChar() == '=') { AdvanceChar(); token.Set(XPathTokenID.Gte); } else { token.Set(XPathTokenID.Gt); } break; case '*': // Check if we're supposed to parse a '*' as a multiply if (IsSpecialPrev()) { token.Set(XPathTokenID.Multiply); } else { token.Set(XPathTokenID.Wildcard, new XPathParser.QName(string.Empty, QueryDataModel.Wildcard)); } break; case '$': // Make sure '$' was followed by something that counts as a variable name XPathParser.QName qname = GetQName(); if (qname.Prefix.Length == 0 && qname.Name.Length == 0) { AdvanceChar(); ThrowError(QueryCompileError.InvalidVariable, this.ch == char.MinValue ? string.Empty : CurrentSubstring()); } token.Set(XPathTokenID.Variable, qname); break; case '\"': TokenizeLiteral('\"'); break; case '\'': TokenizeLiteral('\''); break; default: // Unrecognized character token.Set(XPathTokenID.Unknown); break; } } // Whitespace can mark the end of a token, but is not part of the XPath syntax ConsumeWhitespace(); return(true); }