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) | |
92 { | |
93 CSSParserTokenRange range = originalRange; | |
94 CSSVariableParser::DefinitionType type = CSSVariableParser::Variable; | |
95 bool lastTokenWasExclamation = false; | |
96 bool foundImportant = false; | |
97 | |
98 int bracketCount = 0; | |
99 | |
100 while (!range.atEnd()) { | |
101 const CSSParserToken& token = range.consume(); | |
102 switch (token.type()) { | |
103 case FunctionToken: | |
104 if (token.valueEqualsIgnoringCase("var")) { | |
105 if (!isValidVariableReference(range)) | |
106 return CSSVariableParser::Invalid; // Bail if any references are invalid | |
107 type = CSSVariableParser::VariableWithReferences; | |
108 } else { | |
109 bracketCount++; | |
110 } | |
111 lastTokenWasExclamation = false; | |
112 break; | |
113 case CommentToken: | |
114 case EOFToken: | |
115 ASSERT_NOT_REACHED(); | |
116 case IdentToken: | |
117 // TODO(leviw): This isn't correct. | |
118 if (token.valueEqualsIgnoringCase("inherit") || token.valueEqualsIgn oringCase("unset")) { | |
alancutter (OOO until 2018)
2015/07/14 06:12:57
We still want unset to serialise as unset, this lo
| |
119 type = CSSVariableParser::Inherit; | |
120 } else if (token.valueEqualsIgnoringCase("initial")) { | |
121 type = CSSVariableParser::Initial; | |
122 } else if (lastTokenWasExclamation && token.valueEqualsIgnoringCase( "important")) { | |
123 if (foundImportant) | |
124 return CSSVariableParser::Invalid; | |
125 foundImportant = true; | |
126 } | |
127 lastTokenWasExclamation = false; | |
128 break; | |
129 case DelimiterToken: | |
130 lastTokenWasExclamation = token.delimiter() == '!'; | |
131 break; | |
132 case RightParenthesisToken: | |
133 if (!bracketCount) | |
134 return CSSVariableParser::Invalid; | |
135 bracketCount--; | |
136 break; | |
137 case LeftParenthesisToken: | |
138 bracketCount++; | |
139 break; | |
140 case SemicolonToken: | |
141 return CSSVariableParser::Invalid; | |
142 case CDOToken: | |
143 case CDCToken: | |
144 case AtKeywordToken: | |
145 case IncludeMatchToken: | |
146 case DashMatchToken: | |
147 case PrefixMatchToken: | |
148 case SuffixMatchToken: | |
149 case SubstringMatchToken: | |
150 case ColumnToken: | |
151 case BadStringToken: | |
152 case BadUrlToken: | |
153 case ColonToken: | |
154 return CSSVariableParser::Invalid; | |
155 case WhitespaceToken: | |
156 break; | |
157 default: | |
158 lastTokenWasExclamation = false; | |
159 break; | |
160 } | |
161 } | |
162 if (bracketCount) | |
163 return CSSVariableParser::Invalid; | |
164 return type; | |
165 } | |
166 | |
167 bool CSSVariableParser::containsValidVariableReferences(const CSSParserTokenRang e& originalRange) | |
168 { | |
169 return VariableWithReferences == classifyVariableRange(originalRange); | |
170 } | |
171 | |
172 CSSVariableParser::DefinitionType CSSVariableParser::parseVariableDefinition(con st CSSParserTokenRange& originalRange) | |
173 { | |
174 if (originalRange.atEnd()) | |
175 return CSSVariableParser::Invalid; | |
176 return classifyVariableRange(originalRange); | |
177 } | |
178 | |
179 } // namespace blink | |
OLD | NEW |