コード例 #1
0
        public override bool Parse(ItemFactory itemFactory, ITextProvider text, TokenStream tokens)
        {
            bool hasSubject = false;

            // Allow a bang before the tag name.
            while (tokens.CurrentToken.TokenType == CssTokenType.Bang)
            {
                ParseItem item = itemFactory.Create <SubjectSelector>(this);
                if (item.Parse(itemFactory, text, tokens))
                {
                    Children.Add(item);

                    if (hasSubject)
                    {
                        item.AddParseError(ParseErrorType.UnexpectedBangInSelector, ParseErrorLocation.WholeItem);
                    }

                    hasSubject = true;
                }

                if (tokens.IsWhiteSpaceBeforeCurrentToken())
                {
                    break;
                }
            }

            if (ItemName.IsAtItemName(tokens))
            {
                ItemName name = itemFactory.CreateSpecific <ItemName>(this);
                if (name.Parse(itemFactory, text, tokens))
                {
                    name.Context = CssClassifierContextCache.FromTypeEnum(CssClassifierContextType.ElementTagName);
                    Name         = name;
                    Children.Add(name);
                }
            }

            ParseItem lastItem = (Children.Count > 0) ? Children[Children.Count - 1] : null;

            // Only continue parsing the simple selector if the name touches the next token.
            if (lastItem == null || lastItem.AfterEnd == tokens.CurrentToken.Start)
            {
                bool addedErrorItem = false;

                while (!IsAtSelectorTerminator(tokens))
                {
                    ParseItem pi = CreateNextAtomicPart(itemFactory, text, tokens);
                    if (pi == null)
                    {
                        // Only treat the first bad token as an error (don't need more than one in a row)

                        if (addedErrorItem)
                        {
                            pi = UnknownItem.ParseUnknown(this, itemFactory, text, tokens);
                        }
                        else
                        {
                            pi             = UnknownItem.ParseUnknown(this, itemFactory, text, tokens, ParseErrorType.SimpleSelectorExpected);
                            addedErrorItem = true;
                        }
                    }
                    else if (!pi.Parse(itemFactory, text, tokens))
                    {
                        break;
                    }

                    if (pi is SubjectSelector)
                    {
                        if (hasSubject)
                        {
                            pi.AddParseError(ParseErrorType.UnexpectedBangInSelector, ParseErrorLocation.WholeItem);
                        }
                        hasSubject = true;
                    }

                    SubSelectors.Add(pi);
                    Children.Add(pi);

                    if (tokens.IsWhiteSpaceBeforeCurrentToken())
                    {
                        break;
                    }
                }
            }

            if (IsAtSelectorCombineOperator(text, tokens))
            {
                ParseSelectorCombineOperator(itemFactory, text, tokens);

                if (Name == null &&
                    SelectorCombineOperator != null &
                    SubSelectors.Count == 0 &&
                    !CanStartWithCombineOperator(SelectorCombineOperator))
                {
                    SelectorCombineOperator.AddParseError(ParseErrorType.SelectorBeforeCombineOperatorMissing, ParseErrorLocation.BeforeItem);
                }
            }

            return(Children.Count > 0);
        }