Index: Source/core/css/parser/MediaQueryParser.cpp |
diff --git a/Source/core/css/parser/MediaQueryParser.cpp b/Source/core/css/parser/MediaQueryParser.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..724f0c1ef1d0ea465e0aa3f81fafd1580b2e644a |
--- /dev/null |
+++ b/Source/core/css/parser/MediaQueryParser.cpp |
@@ -0,0 +1,168 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "config.h" |
+#include "core/css/parser/MediaQueryParser.h" |
+ |
+#include "core/css/CSSParserValues.h" |
+#include "core/css/MediaList.h" |
+#include "core/css/MediaQuery.h" |
+#include "core/css/MediaQueryExp.h" |
+#include "core/css/parser/NewCSSTokenizer.h" |
+ |
+namespace WebCore { |
+ |
+PassRefPtr<MediaQuerySet> MediaQueryParser::parse(String queryString) |
+{ |
+ MediaQueryParser parser(queryString); |
+ return parser.parseImpl(); |
+} |
+ |
+MediaQueryParser::MediaQueryParser(String queryString) |
+ : m_state(ReadRestrictor) |
+{ |
+ NewCSSTokenizer::tokenize(queryString, m_tokens); |
+} |
+ |
+PassRefPtr<MediaQuerySet> MediaQueryParser::parseImpl() |
+{ |
+ RefPtr<MediaQuerySet> querySet = MediaQuerySet::create(); |
+ MediaQuery::Restrictor restrictor = MediaQuery::None; |
+ String mediaType("all"); |
+ OwnPtr<ExpressionVector> expressions = adoptPtr(new ExpressionVector()); |
+ String mediaFeature; |
+ CSSParserValueList valueList; |
+ CSSTokenType type; |
+ |
+ for (Vector<CSSToken>::iterator it = m_tokens.begin(); it != m_tokens.end(); ++it) { |
+ type = it->type(); |
+ // FIXME - turn this into a lookup table |
+ if (type == WhitespaceToken) { |
+ continue; |
+ } |
+ /* |
+ if (type == WhitespaceToken || type == DelimToken) { |
+ continue; |
+ } |
+ */ |
+ if (m_state <= ReadMediaType) { |
+ if (type == LeftParenToken) { |
+ m_state = ReadFeature; |
+ } else if (type == IdentToken) { |
+ if (m_state == ReadRestrictor && it->value() == "not") { |
+ restrictor = MediaQuery::Not; |
+ m_state = ReadMediaType; |
+ } else if (m_state == ReadRestrictor && it->value() == "only") { |
+ restrictor = MediaQuery::Only; |
+ m_state = ReadMediaType; |
+ } else { |
+ mediaType = it->value(); |
+ m_state = ReadAnd; |
+ } |
+ } else { |
+ m_state = SkipTillComma; |
+ } |
+ } else if (m_state == ReadAnd) { |
+ if (type == IdentToken && it->value() == "and") { |
+ m_state = ReadFeatureStart; |
+ } else if (type == CommaToken) { |
+ // Append the current MediaQuery and initialize a new one |
+ mediaType.ensure16Bit(); |
+ querySet->addMediaQuery(adoptPtr(new MediaQuery(restrictor, mediaType, expressions.release()))); |
+ expressions = adoptPtr(new ExpressionVector()); |
+ m_state = ReadRestrictor; |
+ mediaType = "all"; |
+ mediaFeature = ""; |
+ restrictor = MediaQuery::None; |
+ valueList.clear(); |
+ } else { |
+ m_state = SkipTillComma; |
+ } |
+ } else if (m_state == ReadFeatureStart) { |
+ if (type == LeftParenToken) { |
+ m_state = ReadFeature; |
+ } else { |
+ m_state = SkipTillComma; |
+ } |
+ } else if (m_state == ReadFeature) { |
+ if (type == IdentToken) { |
+ mediaFeature = it->value(); |
+ m_state = ReadFeatureColon; |
+ } else { |
+ m_state = SkipTillComma; |
+ } |
+ } else if (m_state == ReadFeatureColon) { |
+ if (type == ColonToken) { |
+ m_state = ReadFeatureValue; |
+ } else if (type == RightParenToken) { |
+ --it; |
+ m_state = ReadFeatureEnd; |
+ } else { |
+ m_state = SkipTillParen; |
+ } |
+ } else if (m_state == ReadFeatureValue) { |
+ // Read the value and unit |
+ CSSParserValue value; |
+ if (type == NumberToken || type == PercentageToken || type == DimensionToken) { |
+ value.setFromNumber(it->numericValue(), it->unitType()); |
+ value.isInt = (it->numericValueType() == IntegerValueType); |
+ } else { |
+ CSSParserFunction function; |
+ function.name.init(it->value()); |
+ value.setFromFunction(&function); |
+ } |
+ valueList.addValue(value); |
+ m_state = ReadFeatureEnd; |
+ } else if (m_state == ReadFeatureEnd) { |
+ if (type == RightParenToken) { |
+ OwnPtr<MediaQueryExp> expression = MediaQueryExp::create(mediaFeature, &valueList); |
+ if (expression) { |
+ expressions->append(expression.release()); |
+ m_state = ReadAnd; |
+ } else { |
+ m_state = SkipTillComma; |
+ } |
+ |
+ valueList.clear(); |
+ } else if (type == DelimToken && it->delimiter() == '/') { |
+ CSSParserValue value; |
+ value.unit = CSSParserValue::Operator; |
+ value.iValue = '/'; |
+ valueList.addValue(value); |
+ m_state = ReadFeatureValue; |
+ } else { |
+ m_state = SkipTillParen; |
+ } |
+ } else if (m_state == SkipTillComma) { |
+ if (type == CommaToken || type == EOFToken) { |
+ m_state = ReadRestrictor; |
+ mediaType = "all"; |
+ mediaFeature = ""; |
+ valueList.clear(); |
+ expressions = adoptPtr(new ExpressionVector()); |
+ mediaType.ensure16Bit(); |
+ querySet->addMediaQuery(adoptPtr(new MediaQuery(MediaQuery::Not, mediaType, nullptr))); |
+ restrictor = MediaQuery::None; |
+ } |
+ // FIXME - Should dump previousely gathered results??? |
+ } else if (m_state == SkipTillParen) { |
+ if (type == RightParenToken) { |
+ m_state = ReadAnd; |
+ mediaType = "all"; |
+ restrictor = MediaQuery::Not; |
+ mediaFeature = ""; |
+ expressions = adoptPtr(new ExpressionVector()); |
+ } |
+ // FIXME - Should dump previousely gathered results??? |
+ } |
+ } |
+ // Write down the last MQ, if there was one |
+ if (restrictor != MediaQuery::None || mediaType != "all" || expressions->size() > 0) { |
+ mediaType.ensure16Bit(); |
+ querySet->addMediaQuery(adoptPtr(new MediaQuery(restrictor, mediaType, expressions.release()))); |
+ } |
+ return querySet; |
+} |
+ |
+} // namespace WebCore |