Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(445)

Side by Side Diff: lib/src/tokenizer.dart

Issue 998843003: pkg/csslib: formatting (Closed) Base URL: https://github.com/dart-lang/csslib@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of csslib.parser; 5 part of csslib.parser;
6 6
7 class Tokenizer extends TokenizerBase { 7 class Tokenizer extends TokenizerBase {
8 /** U+ prefix for unicode characters. */ 8 /** U+ prefix for unicode characters. */
9 final UNICODE_U = 'U'.codeUnitAt(0); 9 final UNICODE_U = 'U'.codeUnitAt(0);
10 final UNICODE_LOWER_U = 'u'.codeUnitAt(0); 10 final UNICODE_LOWER_U = 'u'.codeUnitAt(0);
11 final UNICODE_PLUS = '+'.codeUnitAt(0); 11 final UNICODE_PLUS = '+'.codeUnitAt(0);
12 12
13 final QUESTION_MARK = '?'.codeUnitAt(0); 13 final QUESTION_MARK = '?'.codeUnitAt(0);
14 14
15 /** CDATA keyword. */ 15 /** CDATA keyword. */
16 final List CDATA_NAME = 'CDATA'.codeUnits; 16 final List CDATA_NAME = 'CDATA'.codeUnits;
17 17
18 Tokenizer(SourceFile file, String text, bool skipWhitespace, 18 Tokenizer(SourceFile file, String text, bool skipWhitespace, [int index = 0])
19 [int index = 0])
20 : super(file, text, skipWhitespace, index); 19 : super(file, text, skipWhitespace, index);
21 20
22 Token next({unicodeRange: false}) { 21 Token next({unicodeRange: false}) {
23 // keep track of our starting position 22 // keep track of our starting position
24 _startIndex = _index; 23 _startIndex = _index;
25 24
26 int ch; 25 int ch;
27 ch = _nextChar(); 26 ch = _nextChar();
28 switch (ch) { 27 switch (ch) {
29 case TokenChar.NEWLINE: 28 case TokenChar.NEWLINE:
30 case TokenChar.RETURN: 29 case TokenChar.RETURN:
31 case TokenChar.SPACE: 30 case TokenChar.SPACE:
32 case TokenChar.TAB: 31 case TokenChar.TAB:
33 return finishWhitespace(); 32 return finishWhitespace();
34 case TokenChar.END_OF_FILE: 33 case TokenChar.END_OF_FILE:
35 return _finishToken(TokenKind.END_OF_FILE); 34 return _finishToken(TokenKind.END_OF_FILE);
36 case TokenChar.AT: 35 case TokenChar.AT:
37 int peekCh = _peekChar(); 36 int peekCh = _peekChar();
38 if (TokenizerHelpers.isIdentifierStart(peekCh)) { 37 if (TokenizerHelpers.isIdentifierStart(peekCh)) {
39 var oldIndex = _index; 38 var oldIndex = _index;
40 var oldStartIndex = _startIndex; 39 var oldStartIndex = _startIndex;
41 40
42 _startIndex = _index; 41 _startIndex = _index;
43 ch = _nextChar(); 42 ch = _nextChar();
44 Token ident = finishIdentifier(); 43 Token ident = finishIdentifier();
45 44
46 // Is it a directive? 45 // Is it a directive?
47 int tokId = TokenKind.matchDirectives(_text, _startIndex, 46 int tokId = TokenKind.matchDirectives(
48 _index - _startIndex); 47 _text, _startIndex, _index - _startIndex);
49 if (tokId == -1) { 48 if (tokId == -1) {
50 // No, is it a margin directive? 49 // No, is it a margin directive?
51 tokId = TokenKind.matchMarginDirectives(_text, _startIndex, 50 tokId = TokenKind.matchMarginDirectives(
52 _index - _startIndex); 51 _text, _startIndex, _index - _startIndex);
53 } 52 }
54 53
55 if (tokId != -1) { 54 if (tokId != -1) {
56 return _finishToken(tokId); 55 return _finishToken(tokId);
57 } else { 56 } else {
58 // Didn't find a CSS directive or margin directive so the @name is 57 // Didn't find a CSS directive or margin directive so the @name is
59 // probably the Less definition '@name: value_variable_definition'. 58 // probably the Less definition '@name: value_variable_definition'.
60 _startIndex = oldStartIndex; 59 _startIndex = oldStartIndex;
61 _index = oldIndex; 60 _index = oldIndex;
62 } 61 }
63 } 62 }
64 return _finishToken(TokenKind.AT); 63 return _finishToken(TokenKind.AT);
65 case TokenChar.DOT: 64 case TokenChar.DOT:
66 int start = _startIndex; // Start where the dot started. 65 int start = _startIndex; // Start where the dot started.
67 if (maybeEatDigit()) { 66 if (maybeEatDigit()) {
68 // looks like a number dot followed by digit(s). 67 // looks like a number dot followed by digit(s).
69 Token number = finishNumber(); 68 Token number = finishNumber();
70 if (number.kind == TokenKind.INTEGER) { 69 if (number.kind == TokenKind.INTEGER) {
71 // It's a number but it's preceeded by a dot, so make it a double. 70 // It's a number but it's preceeded by a dot, so make it a double.
72 _startIndex = start; 71 _startIndex = start;
73 return _finishToken(TokenKind.DOUBLE); 72 return _finishToken(TokenKind.DOUBLE);
74 } else { 73 } else {
75 // Don't allow dot followed by a double (e.g, '..1'). 74 // Don't allow dot followed by a double (e.g, '..1').
76 return _errorToken(); 75 return _errorToken();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } else if (maybeEatDigit()) { 108 } else if (maybeEatDigit()) {
110 return finishNumber(); 109 return finishNumber();
111 } else if (TokenizerHelpers.isIdentifierStart(ch)) { 110 } else if (TokenizerHelpers.isIdentifierStart(ch)) {
112 return finishIdentifier(); 111 return finishIdentifier();
113 } 112 }
114 return _finishToken(TokenKind.MINUS); 113 return _finishToken(TokenKind.MINUS);
115 case TokenChar.GREATER: 114 case TokenChar.GREATER:
116 return _finishToken(TokenKind.GREATER); 115 return _finishToken(TokenKind.GREATER);
117 case TokenChar.TILDE: 116 case TokenChar.TILDE:
118 if (_maybeEatChar(TokenChar.EQUALS)) { 117 if (_maybeEatChar(TokenChar.EQUALS)) {
119 return _finishToken(TokenKind.INCLUDES); // ~= 118 return _finishToken(TokenKind.INCLUDES); // ~=
120 } 119 }
121 return _finishToken(TokenKind.TILDE); 120 return _finishToken(TokenKind.TILDE);
122 case TokenChar.ASTERISK: 121 case TokenChar.ASTERISK:
123 if (_maybeEatChar(TokenChar.EQUALS)) { 122 if (_maybeEatChar(TokenChar.EQUALS)) {
124 return _finishToken(TokenKind.SUBSTRING_MATCH); // *= 123 return _finishToken(TokenKind.SUBSTRING_MATCH); // *=
125 } 124 }
126 return _finishToken(TokenKind.ASTERISK); 125 return _finishToken(TokenKind.ASTERISK);
127 case TokenChar.AMPERSAND: 126 case TokenChar.AMPERSAND:
128 return _finishToken(TokenKind.AMPERSAND); 127 return _finishToken(TokenKind.AMPERSAND);
129 case TokenChar.NAMESPACE: 128 case TokenChar.NAMESPACE:
130 if (_maybeEatChar(TokenChar.EQUALS)) { 129 if (_maybeEatChar(TokenChar.EQUALS)) {
131 return _finishToken(TokenKind.DASH_MATCH); // |= 130 return _finishToken(TokenKind.DASH_MATCH); // |=
132 } 131 }
133 return _finishToken(TokenKind.NAMESPACE); 132 return _finishToken(TokenKind.NAMESPACE);
134 case TokenChar.COLON: 133 case TokenChar.COLON:
135 return _finishToken(TokenKind.COLON); 134 return _finishToken(TokenKind.COLON);
136 case TokenChar.COMMA: 135 case TokenChar.COMMA:
137 return _finishToken(TokenKind.COMMA); 136 return _finishToken(TokenKind.COMMA);
138 case TokenChar.SEMICOLON: 137 case TokenChar.SEMICOLON:
139 return _finishToken(TokenKind.SEMICOLON); 138 return _finishToken(TokenKind.SEMICOLON);
140 case TokenChar.PERCENT: 139 case TokenChar.PERCENT:
141 return _finishToken(TokenKind.PERCENT); 140 return _finishToken(TokenKind.PERCENT);
142 case TokenChar.SINGLE_QUOTE: 141 case TokenChar.SINGLE_QUOTE:
143 return _finishToken(TokenKind.SINGLE_QUOTE); 142 return _finishToken(TokenKind.SINGLE_QUOTE);
144 case TokenChar.DOUBLE_QUOTE: 143 case TokenChar.DOUBLE_QUOTE:
145 return _finishToken(TokenKind.DOUBLE_QUOTE); 144 return _finishToken(TokenKind.DOUBLE_QUOTE);
146 case TokenChar.SLASH: 145 case TokenChar.SLASH:
147 if (_maybeEatChar(TokenChar.ASTERISK)) return finishMultiLineComment(); 146 if (_maybeEatChar(TokenChar.ASTERISK)) return finishMultiLineComment();
148 return _finishToken(TokenKind.SLASH); 147 return _finishToken(TokenKind.SLASH);
149 case TokenChar.LESS: // <!-- 148 case TokenChar.LESS: // <!--
150 if (_maybeEatChar(TokenChar.BANG)) { 149 if (_maybeEatChar(TokenChar.BANG)) {
151 if (_maybeEatChar(TokenChar.MINUS) && 150 if (_maybeEatChar(TokenChar.MINUS) &&
152 _maybeEatChar(TokenChar.MINUS)) { 151 _maybeEatChar(TokenChar.MINUS)) {
153 return finishMultiLineComment(); 152 return finishMultiLineComment();
154 } else if (_maybeEatChar(TokenChar.LBRACK) && 153 } else if (_maybeEatChar(TokenChar.LBRACK) &&
155 _maybeEatChar(CDATA_NAME[0]) && 154 _maybeEatChar(CDATA_NAME[0]) &&
156 _maybeEatChar(CDATA_NAME[1]) && 155 _maybeEatChar(CDATA_NAME[1]) &&
157 _maybeEatChar(CDATA_NAME[2]) && 156 _maybeEatChar(CDATA_NAME[2]) &&
158 _maybeEatChar(CDATA_NAME[3]) && 157 _maybeEatChar(CDATA_NAME[3]) &&
159 _maybeEatChar(CDATA_NAME[4]) && 158 _maybeEatChar(CDATA_NAME[4]) &&
160 _maybeEatChar(TokenChar.LBRACK)) { 159 _maybeEatChar(TokenChar.LBRACK)) {
161 // <![CDATA[ 160 // <![CDATA[
162 return next(); 161 return next();
163 } 162 }
164 } 163 }
165 return _finishToken(TokenKind.LESS); 164 return _finishToken(TokenKind.LESS);
166 case TokenChar.EQUALS: 165 case TokenChar.EQUALS:
167 return _finishToken(TokenKind.EQUALS); 166 return _finishToken(TokenKind.EQUALS);
168 case TokenChar.CARET: 167 case TokenChar.CARET:
169 if (_maybeEatChar(TokenChar.EQUALS)) { 168 if (_maybeEatChar(TokenChar.EQUALS)) {
170 return _finishToken(TokenKind.PREFIX_MATCH); // ^= 169 return _finishToken(TokenKind.PREFIX_MATCH); // ^=
171 } 170 }
172 return _finishToken(TokenKind.CARET); 171 return _finishToken(TokenKind.CARET);
173 case TokenChar.DOLLAR: 172 case TokenChar.DOLLAR:
174 if (_maybeEatChar(TokenChar.EQUALS)) { 173 if (_maybeEatChar(TokenChar.EQUALS)) {
175 return _finishToken(TokenKind.SUFFIX_MATCH); // $= 174 return _finishToken(TokenKind.SUFFIX_MATCH); // $=
176 } 175 }
177 return _finishToken(TokenKind.DOLLAR); 176 return _finishToken(TokenKind.DOLLAR);
178 case TokenChar.BANG: 177 case TokenChar.BANG:
179 Token tok = finishIdentifier(); 178 Token tok = finishIdentifier();
180 return (tok == null) ? _finishToken(TokenKind.BANG) : tok; 179 return (tok == null) ? _finishToken(TokenKind.BANG) : tok;
181 default: 180 default:
182 // TODO(jmesserly): this is used for IE8 detection; I'm not sure it's 181 // TODO(jmesserly): this is used for IE8 detection; I'm not sure it's
183 // appropriate outside of a few specific places; certainly shouldn't 182 // appropriate outside of a few specific places; certainly shouldn't
184 // be parsed in selectors. 183 // be parsed in selectors.
185 if (!inSelector && ch == TokenChar.BACKSLASH) { 184 if (!inSelector && ch == TokenChar.BACKSLASH) {
(...skipping 14 matching lines...) Expand all
200 } else if (maybeEatQuestionMark()) { 199 } else if (maybeEatQuestionMark()) {
201 // HEX_RANGE U+N??? 200 // HEX_RANGE U+N???
202 return finishUnicodeRange(); 201 return finishUnicodeRange();
203 } else { 202 } else {
204 return _errorToken(); 203 return _errorToken();
205 } 204 }
206 } else if ((ch == UNICODE_U || ch == UNICODE_LOWER_U) && 205 } else if ((ch == UNICODE_U || ch == UNICODE_LOWER_U) &&
207 (_peekChar() == UNICODE_PLUS)) { 206 (_peekChar() == UNICODE_PLUS)) {
208 // Unicode range: U+uNumber[-U+uNumber] 207 // Unicode range: U+uNumber[-U+uNumber]
209 // uNumber = 0..10FFFF 208 // uNumber = 0..10FFFF
210 _nextChar(); // Skip + 209 _nextChar(); // Skip +
211 _startIndex = _index; // Starts at the number 210 _startIndex = _index; // Starts at the number
212 return _finishToken(TokenKind.UNICODE_RANGE); 211 return _finishToken(TokenKind.UNICODE_RANGE);
213 } else if (varDef(ch)) { 212 } else if (varDef(ch)) {
214 return _finishToken(TokenKind.VAR_DEFINITION); 213 return _finishToken(TokenKind.VAR_DEFINITION);
215 } else if (varUsage(ch)) { 214 } else if (varUsage(ch)) {
216 return _finishToken(TokenKind.VAR_USAGE); 215 return _finishToken(TokenKind.VAR_USAGE);
217 } else if (TokenizerHelpers.isIdentifierStart(ch)) { 216 } else if (TokenizerHelpers.isIdentifierStart(ch)) {
218 return finishIdentifier(); 217 return finishIdentifier();
219 } else if (TokenizerHelpers.isDigit(ch)) { 218 } else if (TokenizerHelpers.isDigit(ch)) {
220 return finishNumber(); 219 return finishNumber();
221 } 220 }
222 return _errorToken(); 221 return _errorToken();
223 } 222 }
224 } 223 }
225 224
226 bool varDef(int ch) { 225 bool varDef(int ch) {
227 return ch == 'v'.codeUnitAt(0) && _maybeEatChar('a'.codeUnitAt(0)) && 226 return ch == 'v'.codeUnitAt(0) &&
228 _maybeEatChar('r'.codeUnitAt(0)) && _maybeEatChar('-'.codeUnitAt(0)); 227 _maybeEatChar('a'.codeUnitAt(0)) &&
228 _maybeEatChar('r'.codeUnitAt(0)) &&
229 _maybeEatChar('-'.codeUnitAt(0));
229 } 230 }
230 231
231 bool varUsage(int ch) { 232 bool varUsage(int ch) {
232 return ch == 'v'.codeUnitAt(0) && _maybeEatChar('a'.codeUnitAt(0)) && 233 return ch == 'v'.codeUnitAt(0) &&
233 _maybeEatChar('r'.codeUnitAt(0)) && (_peekChar() == '-'.codeUnitAt(0)); 234 _maybeEatChar('a'.codeUnitAt(0)) &&
235 _maybeEatChar('r'.codeUnitAt(0)) &&
236 (_peekChar() == '-'.codeUnitAt(0));
234 } 237 }
235 238
236 Token _errorToken([String message = null]) { 239 Token _errorToken([String message = null]) {
237 return _finishToken(TokenKind.ERROR); 240 return _finishToken(TokenKind.ERROR);
238 } 241 }
239 242
240 int getIdentifierKind() { 243 int getIdentifierKind() {
241 // Is the identifier a unit type? 244 // Is the identifier a unit type?
242 int tokId = -1; 245 int tokId = -1;
243 246
244 // Don't match units in selectors or selector expressions. 247 // Don't match units in selectors or selector expressions.
245 if (!inSelectorExpression && !inSelector) { 248 if (!inSelectorExpression && !inSelector) {
246 tokId = TokenKind.matchUnits(_text, _startIndex, _index - _startIndex); 249 tokId = TokenKind.matchUnits(_text, _startIndex, _index - _startIndex);
247 } 250 }
248 if (tokId == -1) { 251 if (tokId == -1) {
249 tokId = (_text.substring(_startIndex, _index) == '!important') ? 252 tokId = (_text.substring(_startIndex, _index) == '!important')
250 TokenKind.IMPORTANT : -1; 253 ? TokenKind.IMPORTANT
254 : -1;
251 } 255 }
252 256
253 return tokId >= 0 ? tokId : TokenKind.IDENTIFIER; 257 return tokId >= 0 ? tokId : TokenKind.IDENTIFIER;
254 } 258 }
255 259
256 Token finishIdentifier() { 260 Token finishIdentifier() {
257 // If we encounter an escape sequence, remember it so we can post-process 261 // If we encounter an escape sequence, remember it so we can post-process
258 // to unescape. 262 // to unescape.
259 bool hasEscapedChars = false; 263 bool hasEscapedChars = false;
260 var chars = []; 264 var chars = [];
261 265
262 // backup so we can start with the first character 266 // backup so we can start with the first character
263 int validateFrom = _index; 267 int validateFrom = _index;
264 _index = _startIndex; 268 _index = _startIndex;
265 while (_index < _text.length) { 269 while (_index < _text.length) {
266 int ch = _text.codeUnitAt(_index); 270 int ch = _text.codeUnitAt(_index);
267 271
268 // If the previous character was "\" we need to escape. T 272 // If the previous character was "\" we need to escape. T
269 // http://www.w3.org/TR/CSS21/syndata.html#characters 273 // http://www.w3.org/TR/CSS21/syndata.html#characters
270 // if followed by hexadecimal digits, create the appropriate character. 274 // if followed by hexadecimal digits, create the appropriate character.
271 // otherwise, include the character in the identifier and don't treat it 275 // otherwise, include the character in the identifier and don't treat it
272 // specially. 276 // specially.
273 if (ch == 92/*\*/) { 277 if (ch == 92 /*\*/) {
274 int startHex = ++_index; 278 int startHex = ++_index;
275 eatHexDigits(startHex + 6); 279 eatHexDigits(startHex + 6);
276 if (_index != startHex) { 280 if (_index != startHex) {
277 // Parse the hex digits and add that character. 281 // Parse the hex digits and add that character.
278 chars.add(int.parse('0x' + _text.substring(startHex, _index))); 282 chars.add(int.parse('0x' + _text.substring(startHex, _index)));
279 283
280 if (_index == _text.length) break; 284 if (_index == _text.length) break;
281 285
282 // if we stopped the hex because of a whitespace char, skip it 286 // if we stopped the hex because of a whitespace char, skip it
283 ch = _text.codeUnitAt(_index); 287 ch = _text.codeUnitAt(_index);
284 if (_index - startHex != 6 && 288 if (_index - startHex != 6 &&
285 (ch == TokenChar.SPACE || ch == TokenChar.TAB || 289 (ch == TokenChar.SPACE ||
286 ch == TokenChar.RETURN || ch == TokenChar.NEWLINE)) { 290 ch == TokenChar.TAB ||
291 ch == TokenChar.RETURN ||
292 ch == TokenChar.NEWLINE)) {
287 _index++; 293 _index++;
288 } 294 }
289 } else { 295 } else {
290 // not a digit, just add the next character literally 296 // not a digit, just add the next character literally
291 if (_index == _text.length) break; 297 if (_index == _text.length) break;
292 chars.add(_text.codeUnitAt(_index++)); 298 chars.add(_text.codeUnitAt(_index++));
293 } 299 }
294 } else if (_index < validateFrom || (inSelectorExpression 300 } else if (_index < validateFrom ||
295 ? TokenizerHelpers.isIdentifierPartExpr(ch) 301 (inSelectorExpression
296 : TokenizerHelpers.isIdentifierPart(ch))) { 302 ? TokenizerHelpers.isIdentifierPartExpr(ch)
303 : TokenizerHelpers.isIdentifierPart(ch))) {
297 chars.add(ch); 304 chars.add(ch);
298 _index++; 305 _index++;
299 } else { 306 } else {
300 // Not an identifier or escaped character. 307 // Not an identifier or escaped character.
301 break; 308 break;
302 } 309 }
303 } 310 }
304 311
305 var span = _file.span(_startIndex, _index); 312 var span = _file.span(_startIndex, _index);
306 var text = new String.fromCharCodes(chars); 313 var text = new String.fromCharCodes(chars);
307 314
308 return new IdentifierToken(text, getIdentifierKind(), span); 315 return new IdentifierToken(text, getIdentifierKind(), span);
309 } 316 }
310 317
311 Token finishNumber() { 318 Token finishNumber() {
312 eatDigits(); 319 eatDigits();
313 320
314 if (_peekChar() == 46/*.*/) { 321 if (_peekChar() == 46 /*.*/) {
315 // Handle the case of 1.toString(). 322 // Handle the case of 1.toString().
316 _nextChar(); 323 _nextChar();
317 if (TokenizerHelpers.isDigit(_peekChar())) { 324 if (TokenizerHelpers.isDigit(_peekChar())) {
318 eatDigits(); 325 eatDigits();
319 return _finishToken(TokenKind.DOUBLE); 326 return _finishToken(TokenKind.DOUBLE);
320 } else { 327 } else {
321 _index -= 1; 328 _index -= 1;
322 } 329 }
323 } 330 }
324 331
325 return _finishToken(TokenKind.INTEGER); 332 return _finishToken(TokenKind.INTEGER);
326 } 333 }
327 334
328 bool maybeEatDigit() { 335 bool maybeEatDigit() {
329 if (_index < _text.length 336 if (_index < _text.length &&
330 && TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) { 337 TokenizerHelpers.isDigit(_text.codeUnitAt(_index))) {
331 _index += 1; 338 _index += 1;
332 return true; 339 return true;
333 } 340 }
334 return false; 341 return false;
335 } 342 }
336 343
337 Token finishHexNumber() { 344 Token finishHexNumber() {
338 eatHexDigits(_text.length); 345 eatHexDigits(_text.length);
339 return _finishToken(TokenKind.HEX_INTEGER); 346 return _finishToken(TokenKind.HEX_INTEGER);
340 } 347 }
341 348
342 void eatHexDigits(int end) { 349 void eatHexDigits(int end) {
343 end = math.min(end, _text.length); 350 end = math.min(end, _text.length);
344 while (_index < end) { 351 while (_index < end) {
345 if (TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) { 352 if (TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
346 _index += 1; 353 _index += 1;
347 } else { 354 } else {
348 return; 355 return;
349 } 356 }
350 } 357 }
351 } 358 }
352 359
353 bool maybeEatHexDigit() { 360 bool maybeEatHexDigit() {
354 if (_index < _text.length 361 if (_index < _text.length &&
355 && TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) { 362 TokenizerHelpers.isHexDigit(_text.codeUnitAt(_index))) {
356 _index += 1; 363 _index += 1;
357 return true; 364 return true;
358 } 365 }
359 return false; 366 return false;
360 } 367 }
361 368
362 bool maybeEatQuestionMark() { 369 bool maybeEatQuestionMark() {
363 if (_index < _text.length && 370 if (_index < _text.length && _text.codeUnitAt(_index) == QUESTION_MARK) {
364 _text.codeUnitAt(_index) == QUESTION_MARK) {
365 _index += 1; 371 _index += 1;
366 return true; 372 return true;
367 } 373 }
368 return false; 374 return false;
369 } 375 }
370 376
371 void eatQuestionMarks() { 377 void eatQuestionMarks() {
372 while (_index < _text.length) { 378 while (_index < _text.length) {
373 if (_text.codeUnitAt(_index) == QUESTION_MARK) { 379 if (_text.codeUnitAt(_index) == QUESTION_MARK) {
374 _index += 1; 380 _index += 1;
375 } else { 381 } else {
376 return; 382 return;
377 } 383 }
378 } 384 }
379 } 385 }
380 386
381 Token finishUnicodeRange() { 387 Token finishUnicodeRange() {
382 eatQuestionMarks(); 388 eatQuestionMarks();
383 return _finishToken(TokenKind.HEX_RANGE); 389 return _finishToken(TokenKind.HEX_RANGE);
384 } 390 }
385 391
386 Token finishMultiLineComment() { 392 Token finishMultiLineComment() {
387 while (true) { 393 while (true) {
388 int ch = _nextChar(); 394 int ch = _nextChar();
389 if (ch == 0) { 395 if (ch == 0) {
390 return _finishToken(TokenKind.INCOMPLETE_COMMENT); 396 return _finishToken(TokenKind.INCOMPLETE_COMMENT);
391 } else if (ch == 42/*'*'*/) { 397 } else if (ch == 42 /*'*'*/) {
392 if (_maybeEatChar(47/*'/'*/)) { 398 if (_maybeEatChar(47 /*'/'*/)) {
393 if (_skipWhitespace) { 399 if (_skipWhitespace) {
394 return next(); 400 return next();
395 } else { 401 } else {
396 return _finishToken(TokenKind.COMMENT); 402 return _finishToken(TokenKind.COMMENT);
397 } 403 }
398 } 404 }
399 } else if (ch == TokenChar.MINUS) { 405 } else if (ch == TokenChar.MINUS) {
400 /* Check if close part of Comment Definition --> (CDC). */ 406 /* Check if close part of Comment Definition --> (CDC). */
401 if (_maybeEatChar(TokenChar.MINUS)) { 407 if (_maybeEatChar(TokenChar.MINUS)) {
402 if (_maybeEatChar(TokenChar.GREATER)) { 408 if (_maybeEatChar(TokenChar.GREATER)) {
403 if (_skipWhitespace) { 409 if (_skipWhitespace) {
404 return next(); 410 return next();
405 } else { 411 } else {
406 return _finishToken(TokenKind.HTML_COMMENT); 412 return _finishToken(TokenKind.HTML_COMMENT);
407 } 413 }
408 } 414 }
409 } 415 }
410 } 416 }
411 } 417 }
412 return _errorToken(); 418 return _errorToken();
413 } 419 }
414
415 } 420 }
416 421
417 /** Static helper methods. */ 422 /** Static helper methods. */
418 class TokenizerHelpers { 423 class TokenizerHelpers {
419 static bool isIdentifierStart(int c) { 424 static bool isIdentifierStart(int c) {
420 return isIdentifierStartExpr(c) || c == 45 /*-*/; 425 return isIdentifierStartExpr(c) || c == 45 /*-*/;
421 } 426 }
422 427
423 static bool isDigit(int c) { 428 static bool isDigit(int c) {
424 return (c >= 48/*0*/ && c <= 57/*9*/); 429 return (c >= 48 /*0*/ && c <= 57 /*9*/);
425 } 430 }
426 431
427 static bool isHexDigit(int c) { 432 static bool isHexDigit(int c) {
428 return (isDigit(c) || (c >= 97/*a*/ && c <= 102/*f*/) 433 return (isDigit(c) ||
429 || (c >= 65/*A*/ && c <= 70/*F*/)); 434 (c >= 97 /*a*/ && c <= 102 /*f*/) ||
435 (c >= 65 /*A*/ && c <= 70 /*F*/));
430 } 436 }
431 437
432 static bool isIdentifierPart(int c) { 438 static bool isIdentifierPart(int c) {
433 return isIdentifierPartExpr(c) || c == 45 /*-*/; 439 return isIdentifierPartExpr(c) || c == 45 /*-*/;
434 } 440 }
435 441
436 /** Pseudo function expressions identifiers can't have a minus sign. */ 442 /** Pseudo function expressions identifiers can't have a minus sign. */
437 static bool isIdentifierStartExpr(int c) { 443 static bool isIdentifierStartExpr(int c) {
438 return ((c >= 97/*a*/ && c <= 122/*z*/) || (c >= 65/*A*/ && c <= 90/*Z*/) || 444 return ((c >= 97 /*a*/ && c <= 122 /*z*/) ||
445 (c >= 65 /*A*/ && c <= 90 /*Z*/) ||
439 // Note: Unicode 10646 chars U+00A0 or higher are allowed, see: 446 // Note: Unicode 10646 chars U+00A0 or higher are allowed, see:
440 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier 447 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
441 // http://www.w3.org/TR/CSS21/syndata.html#characters 448 // http://www.w3.org/TR/CSS21/syndata.html#characters
442 // Also, escaped character should be allowed. 449 // Also, escaped character should be allowed.
443 c == 95/*_*/ || c >= 0xA0 || c == 92/*\*/); 450 c == 95 /*_*/ || c >= 0xA0 || c == 92 /*\*/);
444 } 451 }
445 452
446 /** Pseudo function expressions identifiers can't have a minus sign. */ 453 /** Pseudo function expressions identifiers can't have a minus sign. */
447 static bool isIdentifierPartExpr(int c) { 454 static bool isIdentifierPartExpr(int c) {
448 return (isIdentifierStartExpr(c) || isDigit(c)); 455 return (isIdentifierStartExpr(c) || isDigit(c));
449 } 456 }
450 } 457 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698