void CSSParserImpl::consumeDeclarationList(CSSParserTokenRange range, StyleRule::Type ruleType) { ASSERT(m_parsedProperties.isEmpty()); bool useObserver = m_observerWrapper && ruleType == StyleRule::Style; if (useObserver) { m_observerWrapper->observer().startRuleBody(m_observerWrapper->previousTokenStartOffset(range)); m_observerWrapper->skipCommentsBefore(range, true); } while (!range.atEnd()) { switch (range.peek().type()) { case WhitespaceToken: case SemicolonToken: range.consume(); break; case IdentToken: { const CSSParserToken* declarationStart = &range.peek(); if (useObserver) m_observerWrapper->yieldCommentsBefore(range); while (!range.atEnd() && range.peek().type() != SemicolonToken) range.consumeComponentValue(); consumeDeclaration(range.makeSubRange(declarationStart, &range.peek()), ruleType); if (useObserver) m_observerWrapper->skipCommentsBefore(range, false); break; } case AtKeywordToken: { RefPtrWillBeRawPtr<StyleRuleBase> rule = consumeAtRule(range, NoRules); ASSERT_UNUSED(rule, !rule); break; } default: // Parse error, unexpected token in declaration list while (!range.atEnd() && range.peek().type() != SemicolonToken) range.consumeComponentValue(); break; } } // Yield remaining comments if (useObserver) { m_observerWrapper->yieldCommentsBefore(range); m_observerWrapper->observer().endRuleBody(m_observerWrapper->endOffset(range)); } }
bool SizesAttributeParser::parse(CSSParserTokenRange range) { // Split on a comma token and parse the result tokens as (media-condition, length) pairs while (!range.atEnd()) { const CSSParserToken* mediaConditionStart = &range.peek(); // The length is the last component value before the comma which isn't whitespace or a comment const CSSParserToken* lengthTokenStart = &range.peek(); const CSSParserToken* lengthTokenEnd = &range.peek(); while (!range.atEnd() && range.peek().type() != CommaToken) { lengthTokenStart = &range.peek(); range.consumeComponentValue(); lengthTokenEnd = &range.peek(); range.consumeWhitespace(); } range.consume(); float length; if (!calculateLengthInPixels(range.makeSubRange(lengthTokenStart, lengthTokenEnd), length)) continue; RefPtrWillBeRawPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition(range.makeSubRange(mediaConditionStart, lengthTokenStart)); if (!mediaCondition || !mediaConditionMatches(mediaCondition)) continue; m_length = length; m_lengthWasSet = true; return true; } return false; }
PassRefPtrWillBeRawPtr<StyleRuleBase> CSSParserImpl::consumeAtRule(CSSParserTokenRange& range, AllowedRulesType allowedRules) { ASSERT(range.peek().type() == AtKeywordToken); const CSSParserString& name = range.consume().value(); const CSSParserToken* preludeStart = &range.peek(); while (!range.atEnd() && range.peek().type() != LeftBraceToken && range.peek().type() != SemicolonToken) range.consumeComponentValue(); CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek()); CSSAtRuleID id = cssAtRuleID(name); if (id != CSSAtRuleInvalid && m_context.useCounter()) countAtRule(m_context.useCounter(), id); if (range.atEnd() || range.peek().type() == SemicolonToken) { range.consume(); if (allowedRules == AllowCharsetRules && id == CSSAtRuleCharset) return consumeCharsetRule(prelude); if (allowedRules <= AllowImportRules && id == CSSAtRuleImport) return consumeImportRule(prelude); if (allowedRules <= AllowNamespaceRules && id == CSSAtRuleNamespace) return consumeNamespaceRule(prelude); return nullptr; // Parse error, unrecognised at-rule without block } CSSParserTokenRange block = range.consumeBlock(); if (allowedRules == KeyframeRules) return nullptr; // Parse error, no at-rules supported inside @keyframes if (allowedRules == NoRules) return nullptr; // Parse error, no at-rules supported inside declaration lists ASSERT(allowedRules <= RegularRules); switch (id) { case CSSAtRuleMedia: return consumeMediaRule(prelude, block); case CSSAtRuleSupports: return consumeSupportsRule(prelude, block); case CSSAtRuleViewport: return consumeViewportRule(prelude, block); case CSSAtRuleFontFace: return consumeFontFaceRule(prelude, block); case CSSAtRuleWebkitKeyframes: return consumeKeyframesRule(true, prelude, block); case CSSAtRuleKeyframes: return consumeKeyframesRule(false, prelude, block); case CSSAtRulePage: return consumePageRule(prelude, block); default: return nullptr; // Parse error, unrecognised at-rule with block } }
PassRefPtrWillBeRawPtr<StyleRuleBase> CSSParserImpl::consumeAtRule(CSSParserTokenRange& range, AllowedRulesType allowedRules) { ASSERT(range.peek().type() == AtKeywordToken); const CSSParserString& name = range.consume().value(); const CSSParserToken* preludeStart = &range.peek(); while (!range.atEnd() && range.peek().type() != LeftBraceToken && range.peek().type() != SemicolonToken) range.consumeComponentValue(); CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek()); if (range.atEnd() || range.peek().type() == SemicolonToken) { range.consume(); if (allowedRules == AllowCharsetRules && name.equalIgnoringCase("charset")) return consumeCharsetRule(prelude); if (allowedRules <= AllowImportRules && name.equalIgnoringCase("import")) return consumeImportRule(prelude); if (allowedRules <= AllowNamespaceRules && name.equalIgnoringCase("namespace")) return consumeNamespaceRule(prelude); return nullptr; // Parse error, unrecognised at-rule without block } CSSParserTokenRange block = range.consumeBlock(); if (allowedRules == KeyframeRules) return nullptr; // Parse error, no at-rules supported inside @keyframes if (allowedRules == NoRules) return nullptr; // Parse error, no at-rules supported inside declaration lists ASSERT(allowedRules <= RegularRules); if (name.equalIgnoringCase("media")) return consumeMediaRule(prelude, block); if (name.equalIgnoringCase("supports")) return consumeSupportsRule(prelude, block); if (name.equalIgnoringCase("viewport")) return consumeViewportRule(prelude, block); if (name.equalIgnoringCase("font-face")) return consumeFontFaceRule(prelude, block); if (name.equalIgnoringCase("-webkit-keyframes")) return consumeKeyframesRule(true, prelude, block); if (name.equalIgnoringCase("keyframes")) return consumeKeyframesRule(false, prelude, block); if (name.equalIgnoringCase("page")) return consumePageRule(prelude, block); return nullptr; // Parse error, unrecognised at-rule with block }
CSSSupportsParser::SupportsResult CSSSupportsParser::consumeConditionInParenthesis(CSSParserTokenRange& range) { if (range.peek().type() == FunctionToken) { range.consumeComponentValue(); return Unsupported; } if (range.peek().type() != LeftParenthesisToken) return Invalid; CSSParserTokenRange innerRange = range.consumeBlock(); innerRange.consumeWhitespace(); SupportsResult result = consumeCondition(innerRange); if (result != Invalid) return result; return innerRange.peek().type() == IdentToken && m_parser.supportsDeclaration(innerRange) ? Supported : Unsupported; }
static void observeSelectors(CSSParserObserverWrapper& wrapper, CSSParserTokenRange selectors) { // This is easier than hooking into the CSSSelectorParser selectors.consumeWhitespace(); CSSParserTokenRange originalRange = selectors; wrapper.observer().startRuleHeader(StyleRule::Style, wrapper.startOffset(originalRange)); while (!selectors.atEnd()) { const CSSParserToken* selectorStart = &selectors.peek(); while (!selectors.atEnd() && selectors.peek().type() != CommaToken) selectors.consumeComponentValue(); CSSParserTokenRange selector = selectors.makeSubRange(selectorStart, &selectors.peek()); selectors.consumeIncludingWhitespace(); wrapper.observer().observeSelector(wrapper.startOffset(selector), wrapper.endOffset(selector)); } wrapper.observer().endRuleHeader(wrapper.endOffset(originalRange)); }
PassRefPtrWillBeRawPtr<StyleRuleBase> CSSParserImpl::consumeQualifiedRule(CSSParserTokenRange& range, AllowedRulesType allowedRules) { const CSSParserToken* preludeStart = &range.peek(); while (!range.atEnd() && range.peek().type() != LeftBraceToken) range.consumeComponentValue(); if (range.atEnd()) return nullptr; // Parse error, EOF instead of qualified rule block CSSParserTokenRange prelude = range.makeSubRange(preludeStart, &range.peek()); CSSParserTokenRange block = range.consumeBlock(); if (allowedRules <= RegularRules) return consumeStyleRule(prelude, block); if (allowedRules == KeyframeRules) return consumeKeyframeStyleRule(prelude, block); ASSERT_NOT_REACHED(); return nullptr; }