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());
}
Beispiel #4
0
bool consumeCommaIncludingWhitespace(CSSParserTokenRange& range)
{
    CSSParserToken value = range.peek();
    if (value.type() != CommaToken)
        return false;
    range.consumeIncludingWhitespace();
    return true;
}
Beispiel #5
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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);
}
Beispiel #13
0
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);
}
Beispiel #14
0
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]);
}
Beispiel #15
0
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;
    }
}
Beispiel #17
0
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);
}
Beispiel #20
0
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());
}
Beispiel #22
0
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);
}
Beispiel #23
0
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;
}
Beispiel #24
0
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;
    }
Beispiel #27
0
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;
}
Beispiel #30
0
void SizesCalcParser::appendOperator(const CSSParserToken& token)
{
    SizesCalcValue value;
    value.operation = token.delimiter();
    m_valueList.append(value);
}