コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
 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);
     }
 }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        // 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);
        }
コード例 #12
0
 internal void Set(XPathTokenID id, XPathParser.QName qname)
 {
     this.Set(id, qname.Name);
     this.prefix = qname.Prefix;
 }
コード例 #13
0
        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);
            }
        }