OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "core/css/parser/CSSVariableParser.h" | |
7 | |
8 #include "core/css/parser/CSSParserTokenRange.h" | |
9 #include "core/css/parser/CSSParserValues.h" | |
10 | |
11 namespace blink { | |
12 | |
13 static bool isValidVariableName(const CSSParserToken& token) | |
14 { | |
15 CSSParserString value = token.value(); | |
16 return value.length() >= 2 && value[0] == '-' && value[0] == value[1]; | |
17 } | |
18 | |
19 static bool isValidVariableReference(CSSParserTokenRange& range) | |
20 { | |
21 bool foundVariableIdentToken = false; | |
22 bool foundComma = false; | |
23 bool contentAfterComma = false; | |
24 unsigned bracketCount = 0; | |
25 while (!range.atEnd()) { | |
26 const CSSParserToken& token = range.consume(); | |
27 switch (token.type()) { | |
28 case WhitespaceToken: | |
29 if (foundComma) | |
30 contentAfterComma = true; | |
31 break; | |
32 case IdentToken: | |
33 if (foundComma) { | |
34 contentAfterComma = true; | |
35 } else if (!foundVariableIdentToken) { | |
36 if (!isValidVariableName(token)) | |
37 return false; | |
38 foundVariableIdentToken = true; | |
39 } else { | |
40 return false; | |
41 } | |
42 break; | |
43 case FunctionToken: | |
44 case LeftParenthesisToken: | |
45 if (!foundComma) | |
46 return false; | |
47 bracketCount++; | |
48 break; | |
49 case RightParenthesisToken: | |
50 if (!foundVariableIdentToken) | |
51 return false; | |
52 if (!bracketCount) | |
53 return foundVariableIdentToken && (!foundComma || contentAfterCo mma); | |
54 bracketCount--; | |
55 break; | |
56 case CommaToken: | |
57 if (!foundVariableIdentToken) | |
58 return false; | |
59 foundComma = true; | |
60 break; | |
61 case CommentToken: | |
62 case EOFToken: | |
63 ASSERT_NOT_REACHED(); | |
64 case SemicolonToken: | |
65 return false; | |
66 case CDOToken: | |
67 case CDCToken: | |
68 case AtKeywordToken: | |
69 case IncludeMatchToken: | |
70 case DashMatchToken: | |
71 case PrefixMatchToken: | |
72 case SuffixMatchToken: | |
73 case SubstringMatchToken: | |
74 case ColumnToken: | |
75 case BadStringToken: | |
76 case BadUrlToken: | |
77 case ColonToken: | |
78 // TODO(leviw): Need to match CDO/CDC tokens | |
79 if (!foundComma) | |
80 return false; | |
81 break; | |
82 default: | |
83 if (!foundComma) | |
84 return false; | |
85 break; | |
86 } | |
87 } | |
88 return false; | |
89 } | |
90 | |
91 static CSSVariableParser::DefinitionType classifyVariableRange(const CSSParserTo kenRange& originalRange, bool& important) | |
92 { | |
93 CSSParserTokenRange range = originalRange; | |
94 CSSVariableParser::DefinitionType type = CSSVariableParser::Variable; | |
95 bool lastTokenWasExclamation = false; | |
96 | |
97 // TODO(leviw): this needs to be a stack. | |
98 bool foundImportant = false; | |
99 | |
100 int bracketCount = 0; | |
101 | |
Timothy Loh
2015/07/23 08:11:47
Probably something like:
range.consumeWhitespace(
| |
102 while (!range.atEnd()) { | |
103 const CSSParserToken& token = range.consume(); | |
104 switch (token.type()) { | |
105 case FunctionToken: | |
106 if (token.valueEqualsIgnoringCase("var")) { | |
107 if (!isValidVariableReference(range)) | |
108 return CSSVariableParser::Invalid; // Bail if any references are invalid | |
109 type = CSSVariableParser::VariableWithReferences; | |
110 } else { | |
111 bracketCount++; | |
112 } | |
113 lastTokenWasExclamation = false; | |
114 break; | |
115 case CommentToken: | |
116 case EOFToken: | |
117 ASSERT_NOT_REACHED(); | |
118 case IdentToken: | |
119 // TODO(leviw): This isn't correct. | |
120 if (token.valueEqualsIgnoringCase("inherit")) { | |
121 type = CSSVariableParser::Inherit; | |
122 } else if (token.valueEqualsIgnoringCase("initial")) { | |
123 type = CSSVariableParser::Initial; | |
124 } else if (token.valueEqualsIgnoringCase("unset")) { | |
125 type = CSSVariableParser::Unset; | |
126 } else if (lastTokenWasExclamation && token.valueEqualsIgnoringCase( "important")) { | |
Timothy Loh
2015/07/23 08:11:47
Why does this need to handle !important when consu
| |
127 if (foundImportant) | |
128 return CSSVariableParser::Invalid; | |
129 foundImportant = true; | |
130 important = true; | |
131 } | |
132 lastTokenWasExclamation = false; | |
133 break; | |
134 case DelimiterToken: | |
135 lastTokenWasExclamation = token.delimiter() == '!'; | |
136 break; | |
137 case RightParenthesisToken: | |
138 if (!bracketCount) | |
139 return CSSVariableParser::Invalid; | |
140 bracketCount--; | |
141 break; | |
142 case LeftParenthesisToken: | |
143 bracketCount++; | |
144 break; | |
145 case SemicolonToken: | |
146 return CSSVariableParser::Invalid; | |
147 case CDOToken: | |
Timothy Loh
2015/07/23 08:11:47
The spec doesn't say these are invalid
| |
148 case CDCToken: | |
149 case AtKeywordToken: | |
150 case IncludeMatchToken: | |
151 case DashMatchToken: | |
152 case PrefixMatchToken: | |
153 case SuffixMatchToken: | |
154 case SubstringMatchToken: | |
155 case ColumnToken: | |
156 case BadStringToken: | |
157 case BadUrlToken: | |
158 case ColonToken: | |
159 return CSSVariableParser::Invalid; | |
160 case WhitespaceToken: | |
161 break; | |
162 default: | |
163 lastTokenWasExclamation = false; | |
164 break; | |
165 } | |
166 } | |
167 if (bracketCount) | |
168 return CSSVariableParser::Invalid; | |
169 return type; | |
170 } | |
171 | |
172 bool CSSVariableParser::containsValidVariableReferences(const CSSParserTokenRang e& originalRange) | |
173 { | |
174 bool important; | |
175 return VariableWithReferences == classifyVariableRange(originalRange, import ant); | |
176 } | |
177 | |
178 CSSVariableParser::DefinitionType CSSVariableParser::parseVariableDefinition(con st CSSParserTokenRange& originalRange, bool& important) | |
179 { | |
180 important = false; | |
181 if (originalRange.atEnd()) | |
182 return CSSVariableParser::Invalid; | |
183 return classifyVariableRange(originalRange, important); | |
184 } | |
185 | |
186 } // namespace blink | |
OLD | NEW |