示例#1
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        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));
            }
        }
示例#6
0
 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();
 }
示例#8
0
        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);
        }
示例#9
0
        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);
            }
        }
示例#11
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);
            }
        }
示例#12
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);
        }
        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);
        }