| 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 |