private XPathTokenID GetNodeTypeOrFunction(XPathParser.QName qname) { XPathTokenID namedType = this.GetNamedType(qname.Name); if ((namedType & XPathTokenID.NodeType) == XPathTokenID.Unknown) { return(XPathTokenID.Function); } if (qname.Prefix.Length > 0) { this.ThrowError(QueryCompileError.InvalidNodeType, qname.Prefix + ":" + qname.Name); } return(namedType); }
private XPathTokenID GetAxisName(XPathParser.QName qname) { if (qname.Prefix.Length != 0) { this.ThrowError(QueryCompileError.InvalidAxisSpecifier, qname.Prefix + ":" + qname.Name); } XPathTokenID namedType = this.GetNamedType(qname.Name); if (this.resolveKeywords && ((namedType & XPathTokenID.Axis) == XPathTokenID.Unknown)) { this.ThrowError(QueryCompileError.UnsupportedAxis, qname.Name); } return(namedType); }
private XPathTokenID GetNamedOperator(XPathParser.QName qname) { if (qname.Prefix.Length != 0) { this.ThrowError(QueryCompileError.InvalidOperatorName, qname.Prefix + ":" + qname.Name); } XPathTokenID namedType = this.GetNamedType(qname.Name); if (this.resolveKeywords && ((namedType & XPathTokenID.NamedOperator) == XPathTokenID.Unknown)) { this.ThrowError(QueryCompileError.UnsupportedOperator, this.previousID.ToString() + "->" + qname.Name); } return(namedType); }
private XPathTokenID GetNodeTypeOrFunction(XPathParser.QName qname) { XPathTokenID id = GetNamedType(qname.Name); // If it's not a node type, it's lexed as a function if ((id & XPathTokenID.NodeType) == 0) { id = XPathTokenID.Function; } else if (qname.Prefix.Length > 0) { // Node types don't have prefixes ThrowError(QueryCompileError.InvalidNodeType, qname.Prefix + ":" + qname.Name); } return(id); }
private XPathTokenID GetAxisName(XPathParser.QName qname) { // Axes can't have prefixes if (qname.Prefix.Length != 0) { ThrowError(QueryCompileError.InvalidAxisSpecifier, qname.Prefix + ":" + qname.Name); } // Make sure the type is 'Axis' XPathTokenID id = GetNamedType(qname.Name); if (this.resolveKeywords && (id & XPathTokenID.Axis) == 0) { ThrowError(QueryCompileError.UnsupportedAxis, qname.Name); } return(id); }
private XPathTokenID GetNamedOperator(XPathParser.QName qname) { // Named operators can't have prefixes if (qname.Prefix.Length != 0) { ThrowError(QueryCompileError.InvalidOperatorName, qname.Prefix + ":" + qname.Name); } // Make sure the type is 'NamedOperator' XPathTokenID id = GetNamedType(qname.Name); if (this.resolveKeywords && (id & XPathTokenID.NamedOperator) == 0) { ThrowError(QueryCompileError.UnsupportedOperator, this.previousID.ToString() + "->" + qname.Name); } return(id); }
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); }
internal void Set(XPathTokenID id, XPathParser.QName qname) { this.Set(id, qname.Name); this.prefix = qname.Prefix; }
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); } }