示例#1
0
        /// <summary>
        /// Consumes a sequence of tokens representing a UVSS selector part.
        /// </summary>
        /// <param name="state">The parser state.</param>
        /// <param name="allowEOF">A value indicating whether hitting the end of file is valid.</param>
        /// <param name="allowPseudoClass">A value indicating whether parts with pseduo classes are valid.</param>
        /// <param name="allowChild">A value indicating whether this selector part can be an immediate child.</param>
        /// <returns>A new <see cref="UvssSelectorPart"/> object representing the selector part that was consumed.</returns>
        private static UvssSelectorPart ConsumeSelectorPart(UvssParserState state, Boolean allowEOF, Boolean allowPseudoClass, Boolean allowChild)
        {
            var element = default(String);
            var id = default(String);
            var pseudoClass = default(String);
            var classes = new List<String>();
            var valid = false;
            var qualifier = UvssSelectorPartQualifier.None;
            var universal = false;
            var elementIsExact = false;

            while (true)
            {
                if (state.IsPastEndOfStream)
                {
                    if (allowEOF && (qualifier == UvssSelectorPartQualifier.None || valid))
                    {
                        break;
                    }
                    ThrowUnexpectedEOF(state);
                }

                var token = state.CurrentToken;

                if (token.TokenType == UvssLexerTokenType.WhiteSpace ||
                    token.TokenType == UvssLexerTokenType.Comma ||
                    token.TokenType == UvssLexerTokenType.OpenCurlyBrace ||
                    token.TokenType == UvssLexerTokenType.Pipe)
                {
                    if (qualifier != UvssSelectorPartQualifier.None && !valid)
                    {
                        ThrowUnexpectedToken(state, token);
                    }
                    break;
                }

                if (token.TokenType == UvssLexerTokenType.ChildSelector || token.TokenType == UvssLexerTokenType.LogicalChildSelector || token.TokenType == UvssLexerTokenType.TemplatedChildSelector)
                {
                    if (!allowChild)
                        ThrowUnexpectedToken(state, token);

                    switch (token.TokenType)
                    {
                        case UvssLexerTokenType.ChildSelector:
                            qualifier = UvssSelectorPartQualifier.VisualChild;
                            break;

                        case UvssLexerTokenType.LogicalChildSelector:
                            qualifier = UvssSelectorPartQualifier.LogicalChild;
                            break;

                        case UvssLexerTokenType.TemplatedChildSelector:
                            qualifier = UvssSelectorPartQualifier.TemplatedChild;
                            break;
                    }

                    state.Advance();
                    state.AdvanceBeyondWhiteSpace();

                    continue;
                }

                if (token.TokenType == UvssLexerTokenType.Identifier || token.TokenType == UvssLexerTokenType.UniversalSelector)
                {
                    if (!String.IsNullOrEmpty(pseudoClass))
                        ThrowUnexpectedToken(state, token);

                    state.Advance();

                    if (token.TokenType == UvssLexerTokenType.UniversalSelector)
                    {
                        valid = true;
                        universal = true;
                        continue;
                    }
                    else
                    {
                        var typename = default(String);
                        var specific = false;

                        if (IsSelectorForElement(token.Value, out typename, out specific))
                        {
                            if (element != null || universal)
                                ThrowUnexpectedValue(state, token);

                            valid = true;
                            element = typename;
                            elementIsExact = specific;
                            continue;
                        }
                    }

                    if (IsSelectorForID(token.Value))
                    {
                        if (id != null)
                            ThrowUnexpectedValue(state, token);

                        valid = true;
                        id = token.Value;
                        continue;
                    }

                    valid = true;
                    classes.Add(token.Value);
                    continue;
                }

                if (token.TokenType == UvssLexerTokenType.Colon)
                {
                    if (!valid)
                        ThrowUnexpectedToken(state, token);

                    state.Advance();

                    var identifier = state.TryConsume();
                    if (identifier == null)
                        ThrowUnexpectedEOF(state);

                    if (identifier.Value.TokenType != UvssLexerTokenType.Identifier)
                        ThrowExpectedToken(state, identifier.Value, UvssLexerTokenType.Identifier);

                    pseudoClass = identifier.Value.Value;
                    break;
                }

                if (valid)
                    break;

                ThrowUnexpectedToken(state, token);
            }

            return valid ? new UvssSelectorPart(qualifier, element, elementIsExact, id, pseudoClass, classes) : null;
        }