示例#1
0
        public override bool Parse(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            // Parse namespace: foo|bar, *|, *, |A, ..., applies to both elements and attributes
            // note that there should not be spaces between namespace, | and name i.e.
            // foo | bar are actually three selectors and middle one is missing namespace and name.
            //
            // Note that we are not going to parse 3|3 as a valid name. Technically we could do it and
            // leave validation to verify and squiggle with it, but parsing such construct as a legal
            // name would cause colorizer to colorize sequence as an item name which would be confusing
            // to the user. I'd rather have it not colorized as legal name and have it apper black instead
            // telling customer that it is wrong as she types, well before validation pass hits.

            if (tokens.CurrentToken.TokenType == CssTokenType.Identifier || tokens.CurrentToken.TokenType == CssTokenType.Asterisk)
            {
                // There should be no spaces between namespace, | and the element name
                if (tokens.IsWhiteSpaceAfterCurrentToken() || tokens.Peek(1).IsSelectorTerminator())
                {
                    Name = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.ItemName);
                }
                else if (tokens.Peek(1).TokenType == CssTokenType.Or)
                {
                    // validator will deal with invalid namespaces
                    Namespace = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.ItemNamespace);
                    Separator = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.Default);
                }
            }
            else if (tokens.CurrentToken.TokenType == CssTokenType.Or)
            {
                Separator = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.Default);
            }

            if (Name == null && (tokens.CurrentToken.TokenType == CssTokenType.Identifier || tokens.CurrentToken.TokenType == CssTokenType.Asterisk))
            {
                if (Separator == null || !tokens.IsWhiteSpaceBeforeCurrentToken())
                {
                    Name = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.ItemName);
                }
            }
            else
            {
                // It is OK for the name to be missing. Lonely | is the same as *|*
                // so we are not going to add missing item here
            }

            return(Children.Count > 0);
        }
        public static ParseItem ParseUnknown(
            ComplexItem parent,
            ItemFactory itemFactory,
            ITextProvider text,
            TokenStream tokens,
            ParseErrorType?errorType = null)
        {
            ParseItem pi            = null;
            bool      alreadyParsed = false;

            // For a single unknown token, let this switch fall through where a
            // ParseErrorItem will get created. For multiple unknown tokens, deal with
            // them in this switch and let them automatically get wrapped in an unknown block.

            CssClassifierContextType contextType = CssClassifierContextType.Default;

            switch (tokens.CurrentToken.TokenType)
            {
            case CssTokenType.Url:
                pi = itemFactory.Create <UrlItem>(parent);
                break;

            case CssTokenType.Function:
                pi            = Function.ParseFunction(parent, itemFactory, text, tokens);
                alreadyParsed = true;
                break;

            case CssTokenType.OpenFunctionBrace:
            case CssTokenType.OpenSquareBracket:
            case CssTokenType.OpenCurlyBrace:
                pi = itemFactory.Create <UnknownBlock>(parent);
                break;

            case CssTokenType.String:
            case CssTokenType.MultilineString:
            case CssTokenType.InvalidString:
                contextType = CssClassifierContextType.String;
                break;
            }

            if (pi == null)
            {
                pi = new TokenItem(tokens.CurrentToken, contextType);
            }

            if (!alreadyParsed && !pi.Parse(itemFactory, text, tokens))
            {
                Debug.Fail("Parse of an unknown item failed.");

                // I've done all I can do to deal with this unknown token, but now
                // it must be totally ignored so that parsing doesn't get into an infinite loop.
                tokens.AdvanceToken();
                pi = null;
            }

            if (pi != null && errorType.HasValue)
            {
                pi.AddParseError(errorType.Value, ParseErrorLocation.WholeItem);
            }

            return(pi);
        }