public virtual ParseItem CreateNextChild(ParseItem previousChild, ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { if (IsNestedBlock) { if (tokens.CurrentToken.IsScopeBlocker()) { return(null); } // Only nested stylesheets (like in @media) should look for braces if (previousChild is TokenItem && ((TokenItem)previousChild).TokenType == CssTokenType.CloseCurlyBrace) { // No more children after the close curly brace return(null); } if (previousChild == null && tokens.CurrentToken.TokenType != CssTokenType.OpenCurlyBrace) { // First child must be a curly brace return(null); } if (tokens.CurrentToken.TokenType == CssTokenType.OpenCurlyBrace) { return((previousChild == null) ? new TokenItem(tokens.AdvanceToken(), CssClassifierContextType.CurlyBrace) : null); } if (tokens.CurrentToken.TokenType == CssTokenType.CloseCurlyBrace) { return(new TokenItem(tokens.AdvanceToken(), CssClassifierContextType.CurlyBrace)); } } ParseItem newChild = null; switch (tokens.CurrentToken.TokenType) { case CssTokenType.EndOfFile: break; case CssTokenType.ScopeBlocker: newChild = UnknownItem.ParseUnknown(this, itemFactory, text, tokens); break; case CssTokenType.At: newChild = AtDirective.ParseDirective(this, itemFactory, text, tokens); break; default: newChild = ParseDefaultChild(itemFactory, text, tokens); break; } return(newChild); }
public virtual ParseItem CreateNextChild(ParseItem previousChild, ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { if (!IsInlineStyle) { // Look for curly braces if (previousChild is TokenItem && ((TokenItem)previousChild).TokenType == CssTokenType.CloseCurlyBrace) { // No more children after the close curly brace return(null); } if (previousChild == null && tokens.CurrentToken.TokenType != CssTokenType.OpenCurlyBrace) { // First child must be a curly brace return(null); } if (tokens.CurrentToken.TokenType == CssTokenType.OpenCurlyBrace) { return((previousChild == null) ? new TokenItem(tokens.AdvanceToken(), CssClassifierContextType.CurlyBrace) : null); } if (tokens.CurrentToken.TokenType == CssTokenType.CloseCurlyBrace) { return(new TokenItem(tokens.AdvanceToken(), CssClassifierContextType.CurlyBrace)); } } if (tokens.CurrentToken.IsScopeBlocker()) { return(null); } ParseItem newChild; switch (tokens.CurrentToken.TokenType) { case CssTokenType.At: newChild = CreateDirective(itemFactory, text, tokens); break; default: newChild = CreateDefaultChild(itemFactory, text, tokens); break; } return(newChild); }
internal TokenItem AddCurrentAndAdvance(TokenStream tokens, IClassifierContext context) { TokenItem item = new TokenItem(tokens.AdvanceToken(), context); Add(item); return(item); }
public override bool Parse(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { if (tokens != null) { Token = tokens.AdvanceToken(); } return(Token != null); }
protected override ParseItem CreateDefaultChild(ItemFactory itemFactory, ITextProvider text, TokenStream tokens) { // http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems?id=468547 - The contents of unknown directives could be rules or declarations. // Make a good guess for which one to create. int startTokenPosition = tokens.Position; bool childIsDeclaration = true; ParseItem newChild; for (bool done = false; !done && !tokens.CurrentToken.IsBlockTerminator();) { // If I see a curly brace before a semicolon, then this child is probably a RuleSet switch (tokens.CurrentToken.TokenType) { case CssTokenType.OpenCurlyBrace: childIsDeclaration = false; done = true; break; case CssTokenType.Semicolon: done = true; break; default: tokens.AdvanceToken(); break; } } tokens.Position = startTokenPosition; if (childIsDeclaration) { newChild = base.CreateDefaultChild(itemFactory, text, tokens); } else { newChild = itemFactory.Create <RuleSet>(this); if (!newChild.Parse(itemFactory, text, tokens)) { newChild = UnknownItem.ParseUnknown(this, itemFactory, text, tokens, ParseErrorType.UnexpectedToken); } } Debug.Assert(newChild != null); return(newChild); }
/// <summary> /// Extracts comment items from the supplied token collection /// </summary> /// <param name="textProvider">Text provider</param> /// <param name="tokens">Token array that matches the supplied text</param> /// <param name="startToken">Index into the token array at which parser should start</param> /// <param name="tokenCount">Number of tokens to process</param> /// <returns></returns> public IList <Comment> ExtractComments( ITextProvider text, TokenList tokens, int startToken, int tokenCount) { TokenStream tokenIter = new TokenStream(tokens); ItemFactory itemFactory = new ItemFactory(ExternalItemFactory, text, tokenIter); IList <Comment> comments = new List <Comment>(); for (tokenIter.Position = startToken; tokenIter.Position < startToken + tokenCount && tokenIter.Position < tokens.Count;) { CssToken token = tokenIter.CurrentToken; Comment comment = null; switch (token.TokenType) { case CssTokenType.OpenHtmlComment: case CssTokenType.CloseHtmlComment: comment = itemFactory.CreateSpecific <HtmlComment>(null); break; case CssTokenType.OpenCComment: comment = itemFactory.CreateSpecific <CComment>(null); break; case CssTokenType.CommentText: case CssTokenType.SingleTokenComment: case CssTokenType.SingleLineComment: comment = itemFactory.CreateSpecific <CommentTokenItem>(null); break; default: tokenIter.AdvanceToken(); break; } if (comment != null && comment.Parse(itemFactory, text, tokenIter)) { comments.Add(comment); } } return(comments); }
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); }
/// <summary> /// Returns true if the token stream was moved forward at all /// </summary> internal static bool SkipBlock(TokenStream tokens, bool allowCurlyBraces) { Stack <CssTokenType> endMatches = new Stack <CssTokenType>(); if ((tokens.CurrentToken.TokenType == CssTokenType.OpenCurlyBrace && allowCurlyBraces) || tokens.CurrentToken.TokenType == CssTokenType.OpenFunctionBrace || tokens.CurrentToken.TokenType == CssTokenType.OpenSquareBracket || tokens.CurrentToken.TokenType == CssTokenType.Function) { endMatches.Push(GetMatchingTokenType(tokens.CurrentToken.TokenType)); tokens.AdvanceToken(); } else { Debug.Fail("Called UnknownItem.SkipBlock at somewhere other than a block"); return(false); } while (!tokens.CurrentToken.IsScopeBlocker() && endMatches.Count > 0) { switch (tokens.CurrentToken.TokenType) { case CssTokenType.OpenCurlyBrace: if (!allowCurlyBraces) { // stop at the first open curly brace endMatches.Clear(); } else { endMatches.Push(GetMatchingTokenType(tokens.CurrentToken.TokenType)); tokens.AdvanceToken(); } break; case CssTokenType.OpenSquareBracket: case CssTokenType.OpenFunctionBrace: case CssTokenType.Function: endMatches.Push(GetMatchingTokenType(tokens.CurrentToken.TokenType)); tokens.AdvanceToken(); break; case CssTokenType.CloseCurlyBrace: case CssTokenType.CloseSquareBracket: case CssTokenType.CloseFunctionBrace: if (tokens.CurrentToken.TokenType == endMatches.Peek()) { endMatches.Pop(); tokens.AdvanceToken(); } else { // bad nesting, so bail out endMatches.Clear(); } break; default: tokens.AdvanceToken(); break; } } return(true); }