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); }