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);
        }
Exemple #2
0
        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);
        }