protected virtual bool ParseArguments(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { if (tokens.CurrentToken.IsFunctionTerminator()) { // There could be functions without arguments (like "filter: mask();") return(false); } while (!tokens.CurrentToken.IsFunctionTerminator()) { ParseItem fa = CreateArgumentObject(this, itemFactory, Arguments.Count); if (fa.Parse(itemFactory, text, tokens)) { fa.Context = GetArgumentContext(Arguments.Count); Children.Add(fa); Arguments.Add(fa); } else { // Don't know what this is Children.AddUnknownAndAdvance(itemFactory, text, tokens, ParseErrorType.UnexpectedToken); } } FunctionArgument lastArgument = (Arguments.Count > 0) ? Arguments[Arguments.Count - 1] as FunctionArgument : null; if (lastArgument != null && lastArgument.Comma != null && lastArgument == Children[Children.Count - 1]) { Children.AddParseError(ParseErrorType.FunctionArgumentMissing); } return(true); }
protected virtual ParseItem CreateDefaultChild(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { ParseItem child = itemFactory.Create <KeyFramesRuleSet>(this); if (!child.Parse(itemFactory, text, tokens)) { child = UnknownItem.ParseUnknown(this, itemFactory, text, tokens, ParseErrorType.UnexpectedParseError); } return(child); }
protected virtual ParseItem ParseDefaultChild(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { ParseItem newChild = itemFactory.Create <RuleSet>(this); if (!newChild.Parse(itemFactory, text, tokens)) { newChild = UnknownItem.ParseUnknown(this, itemFactory, text, tokens, ParseErrorType.UnexpectedToken); } return(newChild); }
protected virtual ParseItem CreateDefaultChild(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { ParseItem newChild = itemFactory.Create <Declaration>(this); if (!newChild.Parse(itemFactory, text, tokens)) { newChild = UnknownItem.ParseUnknown(this, itemFactory, text, tokens, ParseErrorType.DeclarationExpected); } return(newChild); }
protected virtual void ParseSelectorCombineOperator(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { if (IdReferenceOperator.IsAtIdReferenceOperator(tokens)) { ParseItem combineOperator = itemFactory.Create <IdReferenceOperator>(this); if (combineOperator.Parse(itemFactory, text, tokens)) { SelectorCombineOperator = combineOperator; Children.Add(combineOperator); } } else { SelectorCombineOperator = Children.AddCurrentAndAdvance(tokens, CssClassifierContextType.SelectorCombineOperator); } }
public override bool Parse(IItemFactory itemFactory, ITextProvider text, ITokenStream stream) { if (stream.Current.Type == TokenType.Identifier && IsValidNamedRange(text.GetText(stream.Current.Start, stream.Current.Length))) { AnimationBegin = Children.AddCurrentAndAdvance(stream, SassClassifierType.Keyword); } else if (stream.Current.Type == TokenType.Number && stream.Peek(1).Type == TokenType.PercentSign) { ParseItem begin = itemFactory.Create <PercentageUnit>(this, text, stream); if (begin.Parse(itemFactory, text, stream)) { AnimationBegin = begin; Children.Add(begin); if (stream.Current.Type == TokenType.Comma) { Comma = Children.AddCurrentAndAdvance(stream, SassClassifierType.Punctuation); } ParseItem end = itemFactory.Create <PercentageUnit>(this, text, stream); if (end.Parse(itemFactory, text, stream)) { AnimationEnd = end; Children.Add(end); } } } if (AnimationBegin != null) { var block = itemFactory.CreateSpecific <RuleBlock>(this, text, stream); if (block.Parse(itemFactory, text, stream)) { Body = block; Children.Add(block); } } return(Children.Count > 0); }
internal virtual bool ParseInFunction(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { 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); } } if (Name == null || Name.AfterEnd == tokens.CurrentToken.Start) { while (!IsAtSelectorTerminator(tokens) && tokens.CurrentToken.TokenType != CssTokenType.CloseFunctionBrace) { ParseItem childItem = CreateNextAtomicPart(itemFactory, text, tokens); if (childItem == null || !childItem.Parse(itemFactory, text, tokens)) { childItem = UnknownItem.ParseUnknown(this, itemFactory, text, tokens, ParseErrorType.PseudoFunctionSelectorExpected); } else { SubSelectors.Add(childItem); } Children.Add(childItem); if (tokens.IsWhiteSpaceBeforeCurrentToken()) { break; } } } return(Children.Count > 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); }
internal static ParseItem ParseDirective(ComplexItem parent, ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { Debug.Assert(tokens.CurrentToken.TokenType == CssTokenType.At); CssToken atToken = tokens.CurrentToken; CssToken nameToken = tokens.Peek(1); ParseItem pi = null; if (nameToken.TokenType == CssTokenType.At && AllowDoubleAt(text)) { // Ignore the first @ in @@directive atToken = nameToken; nameToken = tokens.Peek(2); } if (nameToken.TokenType == CssTokenType.Identifier && nameToken.Start == atToken.AfterEnd) { if ("charset".Length == nameToken.Length && text.CompareTo(nameToken.Start, "charset", ignoreCase: false)) { // must be lowercase, and not encoded pi = itemFactory.Create <CharsetDirective>(parent); } else if ("import".Length == nameToken.Length && text.CompareTo(nameToken.Start, "import", ignoreCase: true)) { pi = itemFactory.Create <ImportDirective>(parent); } else if ("page".Length == nameToken.Length && text.CompareTo(nameToken.Start, "page", ignoreCase: true)) { pi = itemFactory.Create <PageDirective>(parent); } else if ("media".Length == nameToken.Length && text.CompareTo(nameToken.Start, "media", ignoreCase: true)) { pi = itemFactory.Create <MediaDirective>(parent); } else if ("namespace".Length == nameToken.Length && text.CompareTo(nameToken.Start, "namespace", ignoreCase: true)) { // CSS3 Namespaces // http://www.w3.org/TR/css3-namespace/ pi = itemFactory.Create <NamespaceDirective>(parent); } else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "keyframes", ignoreCase: true) || TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-moz-keyframes", ignoreCase: true) || TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-ms-keyframes", ignoreCase: true) || TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-o-keyframes", ignoreCase: true) || TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "-webkit-keyframes", ignoreCase: true)) { // CSS3 Animations // http://www.w3.org/TR/2009/WD-css3-animations-20090320/ pi = itemFactory.Create <KeyFramesDirective>(parent); } else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "font-face", ignoreCase: true)) { // CSS3 Webfonts // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#font-descriptions pi = itemFactory.Create <FontFaceDirective>(parent); } else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "counter", ignoreCase: true)) { pi = itemFactory.Create <CounterDirective>(parent); } else if (TextRange.CompareDecoded(nameToken.Start, nameToken.Length, text, "viewport", ignoreCase: true)) { pi = itemFactory.Create <ViewportDirective>(parent); } } if (pi == null) { // some other stuff, like @top-center/left/top/middle... or @footnoote in CSS3 pi = itemFactory.Create <UnknownDirective>(parent); } pi.Parse(itemFactory, text, tokens); return(pi); }