| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/css/parser/MediaQueryParser.h" | 6 #include "core/css/parser/MediaQueryParser.h" |
| 7 | 7 |
| 8 #include "MediaTypeNames.h" | 8 #include "MediaTypeNames.h" |
| 9 #include "core/css/parser/CSSPropertyParser.h" | 9 #include "core/css/parser/CSSPropertyParser.h" |
| 10 #include "core/css/parser/MediaQueryTokenizer.h" | 10 #include "core/css/parser/MediaQueryTokenizer.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 | 48 |
| 49 MediaQueryParser::~MediaQueryParser() { }; | 49 MediaQueryParser::~MediaQueryParser() { }; |
| 50 | 50 |
| 51 void MediaQueryParser::setStateAndRestrict(State state, MediaQuery::Restrictor r
estrictor) | 51 void MediaQueryParser::setStateAndRestrict(State state, MediaQuery::Restrictor r
estrictor) |
| 52 { | 52 { |
| 53 m_mediaQueryData.setRestrictor(restrictor); | 53 m_mediaQueryData.setRestrictor(restrictor); |
| 54 m_state = state; | 54 m_state = state; |
| 55 } | 55 } |
| 56 | 56 |
| 57 // State machine member functions start here | 57 // State machine member functions start here |
| 58 void MediaQueryParser::readRestrictor(MediaQueryTokenType type, TokenIterator& t
oken) | 58 void MediaQueryParser::readRestrictor(MediaQueryTokenType type, const MediaQuery
Token& token) |
| 59 { | 59 { |
| 60 readMediaType(type, token); | 60 readMediaType(type, token); |
| 61 } | 61 } |
| 62 | 62 |
| 63 void MediaQueryParser::readMediaType(MediaQueryTokenType type, TokenIterator& to
ken) | 63 void MediaQueryParser::readMediaType(MediaQueryTokenType type, const MediaQueryT
oken& token) |
| 64 { | 64 { |
| 65 if (type == LeftParenthesisToken) { | 65 if (type == LeftParenthesisToken) { |
| 66 m_state = ReadFeature; | 66 m_state = ReadFeature; |
| 67 } else if (type == IdentToken) { | 67 } else if (type == IdentToken) { |
| 68 if (m_state == ReadRestrictor && equalIgnoringCase(token->value(), "not"
)) { | 68 if (m_state == ReadRestrictor && equalIgnoringCase(token.value(), "not")
) { |
| 69 setStateAndRestrict(ReadMediaType, MediaQuery::Not); | 69 setStateAndRestrict(ReadMediaType, MediaQuery::Not); |
| 70 } else if (m_state == ReadRestrictor && equalIgnoringCase(token->value()
, "only")) { | 70 } else if (m_state == ReadRestrictor && equalIgnoringCase(token.value(),
"only")) { |
| 71 setStateAndRestrict(ReadMediaType, MediaQuery::Only); | 71 setStateAndRestrict(ReadMediaType, MediaQuery::Only); |
| 72 } else { | 72 } else { |
| 73 m_mediaQueryData.setMediaType(token->value()); | 73 m_mediaQueryData.setMediaType(token.value()); |
| 74 m_state = ReadAnd; | 74 m_state = ReadAnd; |
| 75 } | 75 } |
| 76 } else if (type == EOFToken && (!m_querySet->queryVector().size() || m_state
!= ReadRestrictor)) { | 76 } else if (type == EOFToken && (!m_querySet->queryVector().size() || m_state
!= ReadRestrictor)) { |
| 77 m_state = Done; | 77 m_state = Done; |
| 78 } else { | 78 } else { |
| 79 m_state = SkipUntilComma; |
| 79 if (type == CommaToken) | 80 if (type == CommaToken) |
| 80 --token; | 81 skipUntilComma(type, token); |
| 81 m_state = SkipUntilComma; | |
| 82 } | 82 } |
| 83 } | 83 } |
| 84 | 84 |
| 85 void MediaQueryParser::readAnd(MediaQueryTokenType type, TokenIterator& token) | 85 void MediaQueryParser::readAnd(MediaQueryTokenType type, const MediaQueryToken&
token) |
| 86 { | 86 { |
| 87 if (type == IdentToken && equalIgnoringCase(token->value(), "and")) { | 87 if (type == IdentToken && equalIgnoringCase(token.value(), "and")) { |
| 88 m_state = ReadFeatureStart; | 88 m_state = ReadFeatureStart; |
| 89 } else if (type == CommaToken) { | 89 } else if (type == CommaToken) { |
| 90 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQuery()); | 90 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQuery()); |
| 91 m_state = ReadRestrictor; | 91 m_state = ReadRestrictor; |
| 92 } else if (type == EOFToken) { | 92 } else if (type == EOFToken) { |
| 93 m_state = Done; | 93 m_state = Done; |
| 94 } else { | 94 } else { |
| 95 m_state = SkipUntilComma; | 95 m_state = SkipUntilComma; |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 | 98 |
| 99 void MediaQueryParser::readFeatureStart(MediaQueryTokenType type, TokenIterator&
token) | 99 void MediaQueryParser::readFeatureStart(MediaQueryTokenType type, const MediaQue
ryToken& token) |
| 100 { | 100 { |
| 101 if (type == LeftParenthesisToken) | 101 if (type == LeftParenthesisToken) |
| 102 m_state = ReadFeature; | 102 m_state = ReadFeature; |
| 103 else | 103 else |
| 104 m_state = SkipUntilComma; | 104 m_state = SkipUntilComma; |
| 105 } | 105 } |
| 106 | 106 |
| 107 void MediaQueryParser::readFeature(MediaQueryTokenType type, TokenIterator& toke
n) | 107 void MediaQueryParser::readFeature(MediaQueryTokenType type, const MediaQueryTok
en& token) |
| 108 { | 108 { |
| 109 if (type == IdentToken) { | 109 if (type == IdentToken) { |
| 110 m_mediaQueryData.setMediaFeature(token->value()); | 110 m_mediaQueryData.setMediaFeature(token.value()); |
| 111 m_state = ReadFeatureColon; | 111 m_state = ReadFeatureColon; |
| 112 } else { | 112 } else { |
| 113 m_state = SkipUntilComma; | 113 m_state = SkipUntilComma; |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 | 116 |
| 117 void MediaQueryParser::readFeatureColon(MediaQueryTokenType type, TokenIterator&
token) | 117 void MediaQueryParser::readFeatureColon(MediaQueryTokenType type, const MediaQue
ryToken& token) |
| 118 { | 118 { |
| 119 if (type == ColonToken) { | 119 if (type == ColonToken) |
| 120 m_state = ReadFeatureValue; | 120 m_state = ReadFeatureValue; |
| 121 } else if (type == RightParenthesisToken || type == EOFToken) { | 121 else if (type == RightParenthesisToken || type == EOFToken) |
| 122 --token; | 122 readFeatureEnd(type, token); |
| 123 m_state = ReadFeatureEnd; | 123 else |
| 124 } else { | |
| 125 m_state = SkipUntilBlockEnd; | 124 m_state = SkipUntilBlockEnd; |
| 126 } | |
| 127 } | 125 } |
| 128 | 126 |
| 129 void MediaQueryParser::readFeatureValue(MediaQueryTokenType type, TokenIterator&
token) | 127 void MediaQueryParser::readFeatureValue(MediaQueryTokenType type, const MediaQue
ryToken& token) |
| 130 { | 128 { |
| 131 if (type == DimensionToken && token->unitType() == CSSPrimitiveValue::CSS_UN
KNOWN) { | 129 if (type == DimensionToken && token.unitType() == CSSPrimitiveValue::CSS_UNK
NOWN) { |
| 132 m_state = SkipUntilComma; | 130 m_state = SkipUntilComma; |
| 133 } else { | 131 } else { |
| 134 m_mediaQueryData.addParserValue(type, *token); | 132 m_mediaQueryData.addParserValue(type, token); |
| 135 m_state = ReadFeatureEnd; | 133 m_state = ReadFeatureEnd; |
| 136 } | 134 } |
| 137 } | 135 } |
| 138 | 136 |
| 139 void MediaQueryParser::readFeatureEnd(MediaQueryTokenType type, TokenIterator& t
oken) | 137 void MediaQueryParser::readFeatureEnd(MediaQueryTokenType type, const MediaQuery
Token& token) |
| 140 { | 138 { |
| 141 if (type == RightParenthesisToken || type == EOFToken) { | 139 if (type == RightParenthesisToken || type == EOFToken) { |
| 142 if (m_mediaQueryData.addExpression()) | 140 if (m_mediaQueryData.addExpression()) |
| 143 m_state = ReadAnd; | 141 m_state = ReadAnd; |
| 144 else | 142 else |
| 145 m_state = SkipUntilComma; | 143 m_state = SkipUntilComma; |
| 146 } else if (type == DelimiterToken && token->delimiter() == '/') { | 144 } else if (type == DelimiterToken && token.delimiter() == '/') { |
| 147 m_mediaQueryData.addParserValue(type, *token); | 145 m_mediaQueryData.addParserValue(type, token); |
| 148 m_state = ReadFeatureValue; | 146 m_state = ReadFeatureValue; |
| 149 } else { | 147 } else { |
| 150 m_state = SkipUntilBlockEnd; | 148 m_state = SkipUntilBlockEnd; |
| 151 } | 149 } |
| 152 } | 150 } |
| 153 | 151 |
| 154 void MediaQueryParser::skipUntilComma(MediaQueryTokenType type, TokenIterator& t
oken) | 152 void MediaQueryParser::skipUntilComma(MediaQueryTokenType type, const MediaQuery
Token& token) |
| 155 { | 153 { |
| 156 if ((type == CommaToken && m_blockStack.isEmpty()) || type == EOFToken) { | 154 if ((type == CommaToken && !m_blockWatcher.blockLevel()) || type == EOFToken
) { |
| 157 m_state = ReadRestrictor; | 155 m_state = ReadRestrictor; |
| 158 m_mediaQueryData.clear(); | 156 m_mediaQueryData.clear(); |
| 159 m_querySet->addMediaQuery(MediaQuery::createNotAll()); | 157 m_querySet->addMediaQuery(MediaQuery::createNotAll()); |
| 160 } | 158 } |
| 161 } | 159 } |
| 162 | 160 |
| 163 void MediaQueryParser::skipUntilBlockEnd(MediaQueryTokenType type, TokenIterator
& token) | 161 void MediaQueryParser::skipUntilBlockEnd(MediaQueryTokenType type, const MediaQu
eryToken& token) |
| 164 { | 162 { |
| 165 if (m_blockStack.isEmpty()) | 163 if (token.blockType() == MediaQueryToken::BlockEnd && !m_blockWatcher.blockL
evel()) |
| 166 m_state = SkipUntilComma; | 164 m_state = SkipUntilComma; |
| 167 } | 165 } |
| 168 | 166 |
| 169 void MediaQueryParser::done(MediaQueryTokenType type, TokenIterator& token) { } | 167 void MediaQueryParser::done(MediaQueryTokenType type, const MediaQueryToken& tok
en) { } |
| 170 | 168 |
| 171 void MediaQueryParser::popIfBlockMatches(Vector<BlockType>& blockStack, BlockTyp
e type) | 169 void MediaQueryParser::handleBlocks(const MediaQueryToken& token) |
| 172 { | 170 { |
| 173 if (!blockStack.isEmpty() && blockStack.last() == type) | 171 if (token.blockType() == MediaQueryToken::BlockStart |
| 174 blockStack.removeLast(); | 172 && (token.type() != LeftParenthesisToken || m_blockWatcher.blockLevel())
) |
| 173 m_state = SkipUntilBlockEnd; |
| 175 } | 174 } |
| 176 | 175 |
| 177 bool MediaQueryParser::observeBlock(BlockParameters& parameters, MediaQueryToken
Type type) | 176 void MediaQueryParser::processToken(const MediaQueryToken& token) |
| 178 { | 177 { |
| 179 if (type == parameters.leftToken) { | 178 MediaQueryTokenType type = token.type(); |
| 180 if (parameters.stateChange == ModifyState) | |
| 181 m_state = SkipUntilBlockEnd; | |
| 182 m_blockStack.append(parameters.blockType); | |
| 183 } else if (type == parameters.rightToken) { | |
| 184 popIfBlockMatches(m_blockStack, parameters.blockType); | |
| 185 } else { | |
| 186 return false; | |
| 187 } | |
| 188 return true; | |
| 189 } | |
| 190 | 179 |
| 191 void MediaQueryParser::observeBlocks(MediaQueryTokenType type) | 180 handleBlocks(token); |
| 192 { | 181 m_blockWatcher.handleToken(token); |
| 193 enum { BlockParametersCount = 4 }; | |
| 194 BlockParameters blockParameterSet[BlockParametersCount] = { | |
| 195 { LeftParenthesisToken, RightParenthesisToken, ParenthesisBlock, DoNotMo
difyState }, | |
| 196 { FunctionToken, RightParenthesisToken, ParenthesisBlock, ModifyState }, | |
| 197 { LeftBracketToken, RightBracketToken, BracketsBlock, ModifyState }, | |
| 198 { LeftBraceToken, RightBraceToken, BracesBlock, ModifyState } | |
| 199 }; | |
| 200 | |
| 201 for (unsigned i = 0; i < BlockParametersCount; ++i) { | |
| 202 if (observeBlock(blockParameterSet[i], type)) | |
| 203 break; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 void MediaQueryParser::processToken(TokenIterator& token) | |
| 208 { | |
| 209 MediaQueryTokenType type = token->type(); | |
| 210 | |
| 211 observeBlocks(type); | |
| 212 | 182 |
| 213 // Call the function that handles current state | 183 // Call the function that handles current state |
| 214 if (type != WhitespaceToken && type != CommentToken) | 184 if (type != WhitespaceToken && type != CommentToken) |
| 215 ((this)->*(m_state))(type, token); | 185 ((this)->*(m_state))(type, token); |
| 216 } | 186 } |
| 217 | 187 |
| 218 // The state machine loop | 188 // The state machine loop |
| 219 PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseImpl(TokenIterator
token, TokenIterator endToken) | 189 PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseImpl(TokenIterator
token, TokenIterator endToken) |
| 220 { | 190 { |
| 221 for (; token != endToken; ++token) | 191 for (; token != endToken; ++token) |
| 222 processToken(token); | 192 processToken(*token); |
| 223 | 193 |
| 224 if (m_state != ReadAnd && m_state != ReadRestrictor && m_state != Done) | 194 if (m_state != ReadAnd && m_state != ReadRestrictor && m_state != Done) |
| 225 m_querySet->addMediaQuery(MediaQuery::createNotAll()); | 195 m_querySet->addMediaQuery(MediaQuery::createNotAll()); |
| 226 else if (m_mediaQueryData.currentMediaQueryChanged()) | 196 else if (m_mediaQueryData.currentMediaQueryChanged()) |
| 227 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQuery()); | 197 m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQuery()); |
| 228 | 198 |
| 229 return m_querySet; | 199 return m_querySet; |
| 230 } | 200 } |
| 231 | 201 |
| 232 MediaQueryData::MediaQueryData() | 202 MediaQueryData::MediaQueryData() |
| (...skipping 23 matching lines...) Expand all Loading... |
| 256 | 226 |
| 257 bool MediaQueryData::addExpression() | 227 bool MediaQueryData::addExpression() |
| 258 { | 228 { |
| 259 OwnPtrWillBeRawPtr<MediaQueryExp> expression = MediaQueryExp::createIfValid(
m_mediaFeature, &m_valueList); | 229 OwnPtrWillBeRawPtr<MediaQueryExp> expression = MediaQueryExp::createIfValid(
m_mediaFeature, &m_valueList); |
| 260 bool isValid = !!expression; | 230 bool isValid = !!expression; |
| 261 m_expressions->append(expression.release()); | 231 m_expressions->append(expression.release()); |
| 262 m_valueList.clear(); | 232 m_valueList.clear(); |
| 263 return isValid; | 233 return isValid; |
| 264 } | 234 } |
| 265 | 235 |
| 266 void MediaQueryData::addParserValue(MediaQueryTokenType type, MediaQueryToken& t
oken) | 236 void MediaQueryData::addParserValue(MediaQueryTokenType type, const MediaQueryTo
ken& token) |
| 267 { | 237 { |
| 268 CSSParserValue value; | 238 CSSParserValue value; |
| 269 if (type == NumberToken || type == PercentageToken || type == DimensionToken
) { | 239 if (type == NumberToken || type == PercentageToken || type == DimensionToken
) { |
| 270 value.setFromNumber(token.numericValue(), token.unitType()); | 240 value.setFromNumber(token.numericValue(), token.unitType()); |
| 271 value.isInt = (token.numericValueType() == IntegerValueType); | 241 value.isInt = (token.numericValueType() == IntegerValueType); |
| 272 } else if (type == DelimiterToken) { | 242 } else if (type == DelimiterToken) { |
| 273 value.unit = CSSParserValue::Operator; | 243 value.unit = CSSParserValue::Operator; |
| 274 value.iValue = token.delimiter(); | 244 value.iValue = token.delimiter(); |
| 275 } else { | 245 } else { |
| 276 CSSParserFunction* function = new CSSParserFunction; | 246 CSSParserFunction* function = new CSSParserFunction; |
| 277 function->name.init(token.value()); | 247 function->name.init(token.value()); |
| 278 value.setFromFunction(function); | 248 value.setFromFunction(function); |
| 279 CSSParserString tokenValue; | 249 CSSParserString tokenValue; |
| 280 tokenValue.init(token.value()); | 250 tokenValue.init(token.value()); |
| 281 value.id = cssValueKeywordID(tokenValue); | 251 value.id = cssValueKeywordID(tokenValue); |
| 282 } | 252 } |
| 283 m_valueList.addValue(value); | 253 m_valueList.addValue(value); |
| 284 } | 254 } |
| 285 | 255 |
| 286 void MediaQueryData::setMediaType(const String& mediaType) | 256 void MediaQueryData::setMediaType(const String& mediaType) |
| 287 { | 257 { |
| 288 m_mediaType = mediaType; | 258 m_mediaType = mediaType; |
| 289 m_mediaTypeSet = true; | 259 m_mediaTypeSet = true; |
| 290 } | 260 } |
| 291 | 261 |
| 292 } // namespace WebCore | 262 } // namespace WebCore |
| OLD | NEW |