OLD | NEW |
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); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 case TokenChar.RBRACK: | 90 case TokenChar.RBRACK: |
91 if (_maybeEatChar(TokenChar.RBRACK) && | 91 if (_maybeEatChar(TokenChar.RBRACK) && |
92 _maybeEatChar(TokenChar.GREATER)) { | 92 _maybeEatChar(TokenChar.GREATER)) { |
93 // ]]> | 93 // ]]> |
94 return next(); | 94 return next(); |
95 } | 95 } |
96 return _finishToken(TokenKind.RBRACK); | 96 return _finishToken(TokenKind.RBRACK); |
97 case TokenChar.HASH: | 97 case TokenChar.HASH: |
98 return _finishToken(TokenKind.HASH); | 98 return _finishToken(TokenKind.HASH); |
99 case TokenChar.PLUS: | 99 case TokenChar.PLUS: |
100 if (maybeEatDigit()) return finishNumber(); | 100 if (_nextCharsAreNumber(ch)) return finishNumber(); |
101 return _finishToken(TokenKind.PLUS); | 101 return _finishToken(TokenKind.PLUS); |
102 case TokenChar.MINUS: | 102 case TokenChar.MINUS: |
103 if (inSelectorExpression || unicodeRange) { | 103 if (inSelectorExpression || unicodeRange) { |
104 // If parsing in pseudo function expression then minus is an operator | 104 // If parsing in pseudo function expression then minus is an operator |
105 // not part of identifier e.g., interval value range (e.g. U+400-4ff) | 105 // not part of identifier e.g., interval value range (e.g. U+400-4ff) |
106 // or minus operator in selector expression. | 106 // or minus operator in selector expression. |
107 return _finishToken(TokenKind.MINUS); | 107 return _finishToken(TokenKind.MINUS); |
108 } else if (maybeEatDigit()) { | 108 } else if (_nextCharsAreNumber(ch)) { |
109 return finishNumber(); | 109 return finishNumber(); |
110 } else if (TokenizerHelpers.isIdentifierStart(ch)) { | 110 } else if (TokenizerHelpers.isIdentifierStart(ch)) { |
111 return finishIdentifier(); | 111 return finishIdentifier(); |
112 } | 112 } |
113 return _finishToken(TokenKind.MINUS); | 113 return _finishToken(TokenKind.MINUS); |
114 case TokenChar.GREATER: | 114 case TokenChar.GREATER: |
115 return _finishToken(TokenKind.GREATER); | 115 return _finishToken(TokenKind.GREATER); |
116 case TokenChar.TILDE: | 116 case TokenChar.TILDE: |
117 if (_maybeEatChar(TokenChar.EQUALS)) { | 117 if (_maybeEatChar(TokenChar.EQUALS)) { |
118 return _finishToken(TokenKind.INCLUDES); // ~= | 118 return _finishToken(TokenKind.INCLUDES); // ~= |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 var t = finishHexNumber(); | 195 var t = finishHexNumber(); |
196 // Any question marks then it's a HEX_RANGE not HEX_NUMBER. | 196 // Any question marks then it's a HEX_RANGE not HEX_NUMBER. |
197 if (maybeEatQuestionMark()) finishUnicodeRange(); | 197 if (maybeEatQuestionMark()) finishUnicodeRange(); |
198 return t; | 198 return t; |
199 } else if (maybeEatQuestionMark()) { | 199 } else if (maybeEatQuestionMark()) { |
200 // HEX_RANGE U+N??? | 200 // HEX_RANGE U+N??? |
201 return finishUnicodeRange(); | 201 return finishUnicodeRange(); |
202 } else { | 202 } else { |
203 return _errorToken(); | 203 return _errorToken(); |
204 } | 204 } |
205 } else if ((ch == UNICODE_U || ch == UNICODE_LOWER_U) && | 205 } else if (_inString && |
| 206 (ch == UNICODE_U || ch == UNICODE_LOWER_U) && |
206 (_peekChar() == UNICODE_PLUS)) { | 207 (_peekChar() == UNICODE_PLUS)) { |
| 208 // `_inString` is misleading. We actually DON'T want to enter this |
| 209 // block while tokenizing a string, but the parser sets this value to |
| 210 // false while it IS consuming tokens within a string. |
| 211 // |
207 // Unicode range: U+uNumber[-U+uNumber] | 212 // Unicode range: U+uNumber[-U+uNumber] |
208 // uNumber = 0..10FFFF | 213 // uNumber = 0..10FFFF |
209 _nextChar(); // Skip + | 214 _nextChar(); // Skip + |
210 _startIndex = _index; // Starts at the number | 215 _startIndex = _index; // Starts at the number |
211 return _finishToken(TokenKind.UNICODE_RANGE); | 216 return _finishToken(TokenKind.UNICODE_RANGE); |
212 } else if (varDef(ch)) { | 217 } else if (varDef(ch)) { |
213 return _finishToken(TokenKind.VAR_DEFINITION); | 218 return _finishToken(TokenKind.VAR_DEFINITION); |
214 } else if (varUsage(ch)) { | 219 } else if (varUsage(ch)) { |
215 return _finishToken(TokenKind.VAR_USAGE); | 220 return _finishToken(TokenKind.VAR_USAGE); |
216 } else if (TokenizerHelpers.isIdentifierStart(ch)) { | 221 } else if (TokenizerHelpers.isIdentifierStart(ch)) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 ? TokenKind.IMPORTANT | 258 ? TokenKind.IMPORTANT |
254 : -1; | 259 : -1; |
255 } | 260 } |
256 | 261 |
257 return tokId >= 0 ? tokId : TokenKind.IDENTIFIER; | 262 return tokId >= 0 ? tokId : TokenKind.IDENTIFIER; |
258 } | 263 } |
259 | 264 |
260 Token finishIdentifier() { | 265 Token finishIdentifier() { |
261 // If we encounter an escape sequence, remember it so we can post-process | 266 // If we encounter an escape sequence, remember it so we can post-process |
262 // to unescape. | 267 // to unescape. |
263 var chars = []; | 268 var chars = <int>[]; |
264 | 269 |
265 // backup so we can start with the first character | 270 // backup so we can start with the first character |
266 int validateFrom = _index; | 271 int validateFrom = _index; |
267 _index = _startIndex; | 272 _index = _startIndex; |
268 while (_index < _text.length) { | 273 while (_index < _text.length) { |
269 int ch = _text.codeUnitAt(_index); | 274 int ch = _text.codeUnitAt(_index); |
270 | 275 |
271 // If the previous character was "\" we need to escape. T | 276 // If the previous character was "\" we need to escape. T |
272 // http://www.w3.org/TR/CSS21/syndata.html#characters | 277 // http://www.w3.org/TR/CSS21/syndata.html#characters |
273 // if followed by hexadecimal digits, create the appropriate character. | 278 // if followed by hexadecimal digits, create the appropriate character. |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 if (_maybeEatChar(TokenChar.GREATER)) { | 412 if (_maybeEatChar(TokenChar.GREATER)) { |
408 if (_inString) { | 413 if (_inString) { |
409 return next(); | 414 return next(); |
410 } else { | 415 } else { |
411 return _finishToken(TokenKind.HTML_COMMENT); | 416 return _finishToken(TokenKind.HTML_COMMENT); |
412 } | 417 } |
413 } | 418 } |
414 } | 419 } |
415 } | 420 } |
416 } | 421 } |
417 return _errorToken(); | |
418 } | 422 } |
419 } | 423 } |
420 | 424 |
421 /** Static helper methods. */ | 425 /** Static helper methods. */ |
422 class TokenizerHelpers { | 426 class TokenizerHelpers { |
423 static bool isIdentifierStart(int c) { | 427 static bool isIdentifierStart(int c) { |
424 return isIdentifierStartExpr(c) || c == 45 /*-*/; | 428 return isIdentifierStartExpr(c) || c == 45 /*-*/; |
425 } | 429 } |
426 | 430 |
427 static bool isDigit(int c) { | 431 static bool isDigit(int c) { |
(...skipping 11 matching lines...) Expand all Loading... |
439 } | 443 } |
440 | 444 |
441 /** Pseudo function expressions identifiers can't have a minus sign. */ | 445 /** Pseudo function expressions identifiers can't have a minus sign. */ |
442 static bool isIdentifierStartExpr(int c) { | 446 static bool isIdentifierStartExpr(int c) { |
443 return ((c >= 97 /*a*/ && c <= 122 /*z*/) || | 447 return ((c >= 97 /*a*/ && c <= 122 /*z*/) || |
444 (c >= 65 /*A*/ && c <= 90 /*Z*/) || | 448 (c >= 65 /*A*/ && c <= 90 /*Z*/) || |
445 // Note: Unicode 10646 chars U+00A0 or higher are allowed, see: | 449 // Note: Unicode 10646 chars U+00A0 or higher are allowed, see: |
446 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier | 450 // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier |
447 // http://www.w3.org/TR/CSS21/syndata.html#characters | 451 // http://www.w3.org/TR/CSS21/syndata.html#characters |
448 // Also, escaped character should be allowed. | 452 // Also, escaped character should be allowed. |
449 c == 95 /*_*/ || c >= 0xA0 || c == 92 /*\*/); | 453 c == 95 /*_*/ || |
| 454 c >= 0xA0 || |
| 455 c == 92 /*\*/); |
450 } | 456 } |
451 | 457 |
452 /** Pseudo function expressions identifiers can't have a minus sign. */ | 458 /** Pseudo function expressions identifiers can't have a minus sign. */ |
453 static bool isIdentifierPartExpr(int c) { | 459 static bool isIdentifierPartExpr(int c) { |
454 return (isIdentifierStartExpr(c) || isDigit(c)); | 460 return (isIdentifierStartExpr(c) || isDigit(c)); |
455 } | 461 } |
456 } | 462 } |
OLD | NEW |