void MediaQueryParser::readMediaType(CSSParserTokenType type, const CSSParserToken& token) { if (type == LeftParenthesisToken) { if (m_mediaQueryData.restrictor() != MediaQuery::None) m_state = SkipUntilComma; else m_state = ReadFeature; } else if (type == IdentToken) { if (m_state == ReadRestrictor && token.valueEqualsIgnoringASCIICase("not")) { setStateAndRestrict(ReadMediaType, MediaQuery::Not); } else if (m_state == ReadRestrictor && token.valueEqualsIgnoringASCIICase("only")) { setStateAndRestrict(ReadMediaType, MediaQuery::Only); } else if (m_mediaQueryData.restrictor() != MediaQuery::None && isRestrictorOrLogicalOperator(token)) { m_state = SkipUntilComma; } else { m_mediaQueryData.setMediaType(token.value()); m_state = ReadAnd; } } else if (type == EOFToken && (!m_querySet->queryVector().size() || m_state != ReadRestrictor)) { m_state = Done; } else { m_state = SkipUntilComma; if (type == CommaToken) skipUntilComma(type, token); } }
CSSTokenizer::Scope::Scope(const String& string) : m_string(string) { // According to the spec, we should perform preprocessing here. // See: http://dev.w3.org/csswg/css-syntax/#input-preprocessing // // However, we can skip this step since: // * We're using HTML spaces (which accept \r and \f as a valid white space) // * Do not count white spaces // * CSSTokenizerInputStream::peek replaces NULLs for replacement characters if (string.isEmpty()) return; // To avoid resizing we err on the side of reserving too much space. // Most strings we tokenize have about 3.5 to 5 characters per token. m_tokens.reserveInitialCapacity(string.length() / 3); CSSTokenizerInputStream input(string); CSSTokenizer tokenizer(input, *this); while (true) { CSSParserToken token = tokenizer.nextToken(); if (token.type() == CommentToken) continue; if (token.type() == EOFToken) return; m_tokens.append(token); } }
CSSTokenizer::Scope::Scope(const String& string, CSSParserObserverWrapper& wrapper) : m_string(string) { if (string.isEmpty()) return; CSSTokenizerInputStream input(string); CSSTokenizer tokenizer(input, *this); unsigned offset = 0; while (true) { CSSParserToken token = tokenizer.nextToken(); if (token.type() == EOFToken) break; if (token.type() == CommentToken) { wrapper.addComment(offset, input.offset(), m_tokens.size()); } else { m_tokens.append(token); wrapper.addToken(offset); } offset = input.offset(); } wrapper.addToken(offset); wrapper.finalizeConstruction(m_tokens.begin()); }
bool consumeCommaIncludingWhitespace(CSSParserTokenRange& range) { CSSParserToken value = range.peek(); if (value.type() != CommaToken) return false; range.consumeIncludingWhitespace(); return true; }
bool consumeSlashIncludingWhitespace(CSSParserTokenRange& range) { CSSParserToken value = range.peek(); if (value.type() != DelimiterToken || value.delimiter() != '/') return false; range.consumeIncludingWhitespace(); return true; }
bool CSSVariableParser::isValidVariableName(const CSSParserToken& token) { if (token.type() != IdentToken) return false; CSSParserString value = token.value(); return value.length() >= 2 && value[0] == '-' && value[1] == '-'; }
static bool isRestrictorOrLogicalOperator(const CSSParserToken& token) { // FIXME: it would be more efficient to use lower-case always for tokenValue. return token.valueEqualsIgnoringASCIICase("not") || token.valueEqualsIgnoringASCIICase("and") || token.valueEqualsIgnoringASCIICase("or") || token.valueEqualsIgnoringASCIICase("only"); }
void MediaQueryBlockWatcher::handleToken(const CSSParserToken& token) { if (token.blockType() == CSSParserToken::BlockStart) { ++m_blockLevel; } else if (token.blockType() == CSSParserToken::BlockEnd) { ASSERT(m_blockLevel); --m_blockLevel; } }
// http://www.w3.org/TR/css3-syntax/#consume-a-numeric-token CSSParserToken CSSTokenizer::consumeNumericToken() { CSSParserToken token = consumeNumber(); if (nextCharsAreIdentifier()) token.convertToDimensionWithUnit(consumeName()); else if (consumeIfNext('%')) token.convertToPercentage(); return token; }
bool SizesCalcParser::appendLength(const CSSParserToken& token) { SizesCalcValue value; double result = 0; if (!m_mediaValues->computeLength(token.numericValue(), token.unitType(), result)) return false; value.value = result; value.isLength = true; m_valueList.append(value); return true; }
bool CSSParserToken::operator==(const CSSParserToken& other) const { if (m_type != other.m_type) return false; switch (m_type) { case DelimiterToken: return delimiter() == other.delimiter(); case HashToken: if (m_hashTokenType != other.m_hashTokenType) return false; FALLTHROUGH; case IdentToken: case FunctionToken: case StringToken: case UrlToken: return valueDataCharRawEqual(other); case DimensionToken: if (!valueDataCharRawEqual(other)) return false; FALLTHROUGH; case NumberToken: case PercentageToken: return m_numericSign == other.m_numericSign && m_numericValue == other.m_numericValue && m_numericValueType == other.m_numericValueType; case UnicodeRangeToken: return m_unicodeRange.start == other.m_unicodeRange.start && m_unicodeRange.end == other.m_unicodeRange.end; default: return true; } }
void MediaQueryParser::readMediaNot(CSSParserTokenType type, const CSSParserToken& token) { if (type == IdentToken && token.valueEqualsIgnoringASCIICase("not")) setStateAndRestrict(ReadFeatureStart, MediaQuery::Not); else readFeatureStart(type, token); }
void CSSVariableData::consumeAndUpdateTokens(const CSSParserTokenRange& range) { StringBuilder stringBuilder; CSSParserTokenRange localRange = range; while (!localRange.atEnd()) { CSSParserToken token = localRange.consume(); if (token.hasStringBacking()) stringBuilder.append(token.value()); } m_backingString = stringBuilder.toString(); if (m_backingString.is8Bit()) updateTokens<LChar>(range); else updateTokens<UChar>(range); }
void testTokens(const String& string, const CSSParserToken& token1, const CSSParserToken& token2 = CSSParserToken(EOFToken), const CSSParserToken& token3 = CSSParserToken(EOFToken)) { Vector<CSSParserToken> expectedTokens; expectedTokens.append(token1); if (token2.type() != EOFToken) { expectedTokens.append(token2); if (token3.type() != EOFToken) expectedTokens.append(token3); } Vector<CSSParserToken> actualTokens; CSSTokenizer::tokenize(string, actualTokens); ASSERT_EQ(expectedTokens.size(), actualTokens.size()); for (size_t i = 0; i < expectedTokens.size(); ++i) compareTokens(expectedTokens[i], actualTokens[i]); }
void MediaQueryParser::readFeatureValue(CSSParserTokenType type, const CSSParserToken& token) { if (type == DimensionToken && token.unitType() == CSSPrimitiveValue::CSS_UNKNOWN) { m_state = SkipUntilComma; } else { m_mediaQueryData.addParserValue(type, token); m_state = ReadFeatureEnd; } }
void MediaQueryParser::readFeature(CSSParserTokenType type, const CSSParserToken& token) { if (type == IdentToken) { m_mediaQueryData.setMediaFeature(token.value()); m_state = ReadFeatureColon; } else { m_state = SkipUntilComma; } }
void MediaQueryParser::readFeature(CSSParserTokenType type, const CSSParserToken& token) { if (type == IdentToken) { // FIXME-NEWPARSER: Find a way to avoid this. const_cast<CSSParserToken&>(token).convertToASCIILowercaseInPlace(); m_mediaQueryData.setMediaFeature(token.value().toString()); m_state = ReadFeatureColon; } else m_state = SkipUntilComma; }
void MediaQueryParser::readFeatureValue(CSSParserTokenType type, const CSSParserToken& token) { if (type == DimensionToken && token.unitType() == CSSPrimitiveValue::UnitType::Unknown) { m_state = SkipUntilComma; } else { if (m_mediaQueryData.tryAddParserToken(type, token)) m_state = ReadFeatureEnd; else m_state = SkipUntilBlockEnd; } }
void MediaQueryParser::processToken(const CSSParserToken& token) { CSSParserTokenType type = token.type(); handleBlocks(token); m_blockWatcher.handleToken(token); // Call the function that handles current state if (type != WhitespaceToken) ((this)->*(m_state))(type, token); }
void MediaQueryParser::readAnd(CSSParserTokenType type, const CSSParserToken& token) { if (type == IdentToken && equalIgnoringASCIICase(token.value(), "and")) { m_state = ReadFeatureStart; } else if (type == CommaToken && m_parserType != MediaConditionParser) { commitMediaQuery(); m_state = ReadRestrictor; } else if (type == EOFToken) m_state = Done; else m_state = SkipUntilComma; }
void testTokens(const String& string, const CSSParserToken& token1, const CSSParserToken& token2 = CSSParserToken(EOFToken), const CSSParserToken& token3 = CSSParserToken(EOFToken)) { Vector<CSSParserToken> expectedTokens; expectedTokens.append(token1); if (token2.type() != EOFToken) { expectedTokens.append(token2); if (token3.type() != EOFToken) expectedTokens.append(token3); } CSSParserTokenRange expected(expectedTokens); CSSTokenizer::Scope actualScope(string); CSSParserTokenRange actual = actualScope.tokenRange(); // Just check that serialization doesn't hit any asserts actual.serialize(); while (!expected.atEnd() || !actual.atEnd()) compareTokens(expected.consume(), actual.consume()); }
void MediaQueryData::addParserValue(CSSParserTokenType type, const CSSParserToken& token) { CSSParserValue value; if (type == NumberToken || type == PercentageToken || type == DimensionToken) { value.setFromNumber(token.numericValue(), token.unitType()); value.isInt = (token.numericValueType() == IntegerValueType); } else if (type == DelimiterToken) { value.unit = CSSParserValue::Operator; value.iValue = token.delimiter(); value.id = CSSValueInvalid; value.isInt = false; } else { CSSParserString tokenValue; tokenValue.init(token.value()); value.unit = CSSPrimitiveValue::CSS_IDENT; value.string = tokenValue; value.id = cssValueKeywordID(tokenValue); value.isInt = false; } m_valueList.addValue(value); }
void MediaQueryParser::readFeatureEnd(CSSParserTokenType type, const CSSParserToken& token) { if (type == RightParenthesisToken || type == EOFToken) { if (type != EOFToken && m_mediaQueryData.addExpression()) m_state = ReadAnd; else m_state = SkipUntilComma; } else if (type == DelimiterToken && token.delimiter() == '/') { m_mediaQueryData.tryAddParserToken(type, token); m_state = ReadFeatureValue; } else m_state = SkipUntilBlockEnd; }
void CSSTokenizer::tokenize(String string, Vector<CSSParserToken>& outTokens) { // According to the spec, we should perform preprocessing here. // See: http://dev.w3.org/csswg/css-syntax/#input-preprocessing // // However, we can skip this step since: // * We're using HTML spaces (which accept \r and \f as a valid white space) // * Do not count white spaces // * consumeEscape replaces NULLs for replacement characters if (string.isEmpty()) return; CSSTokenizerInputStream input(string); CSSTokenizer tokenizer(input); while (true) { CSSParserToken token = tokenizer.nextToken(); outTokens.append(token); if (token.type() == EOFToken) return; } }
void MediaQueryParser::readAnd(CSSParserTokenType type, const CSSParserToken& token) { if (type == IdentToken && token.valueEqualsIgnoringASCIICase("and")) { m_state = ReadFeatureStart; } else if (type == CommaToken && m_parserType != MediaConditionParser) { m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQuery()); m_state = ReadRestrictor; } else if (type == EOFToken) { m_state = Done; } else { m_state = SkipUntilComma; } }
bool parseValue(CSSParserTokenRange& tokens, Value* result) { CSSParserToken token = tokens.consumeIncludingWhitespace(); if (!(token.type() == NumberToken || token.type() == PercentageToken || token.type() == DimensionToken)) return false; CSSPrimitiveValue::UnitType type = token.unitType(); if (unitCategory(type) == CalcOther) return false; result->value = CSSCalcPrimitiveValue::create( CSSPrimitiveValue::create(token.numericValue(), type), token.numericValueType() == IntegerValueType); return true; }
bool SizesCalcParser::handleOperator(Vector<CSSParserToken>& stack, const CSSParserToken& token) { // If the token is an operator, o1, then: // while there is an operator token, o2, at the top of the stack, and // either o1 is left-associative and its precedence is equal to that of o2, // or o1 has precedence less than that of o2, // pop o2 off the stack, onto the output queue; // push o1 onto the stack. bool stackOperatorPriority; bool incomingOperatorPriority; if (!operatorPriority(token.delimiter(), incomingOperatorPriority)) return false; if (!stack.isEmpty() && stack.last().type() == DelimiterToken) { if (!operatorPriority(stack.last().delimiter(), stackOperatorPriority)) return false; if (!incomingOperatorPriority || stackOperatorPriority) { appendOperator(stack.last()); stack.removeLast(); } } stack.append(token); return true; }
static CSSParserToken percentage(NumericValueType type, double value) { CSSParserToken token = number(type, value, NoSign); // sign ignored token.convertToPercentage(); return token; }
static CSSParserToken dimension(NumericValueType type, double value, const String& string) { CSSParserToken token = number(type, value, NoSign); // sign ignored token.convertToDimensionWithUnit(toParserString(string)); return token; }
void SizesCalcParser::appendOperator(const CSSParserToken& token) { SizesCalcValue value; value.operation = token.delimiter(); m_valueList.append(value); }