| 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 // Generated by scripts/tokenizer_gen.py. | 4 // Generated by scripts/tokenizer_gen.py. |
| 5 | 5 |
| 6 part of csslib.parser; | 6 part of csslib.parser; |
| 7 | 7 |
| 8 /** Tokenizer state to support look ahead for Less' nested selectors. */ | 8 /** Tokenizer state to support look ahead for Less' nested selectors. */ |
| 9 class TokenizerState { | 9 class TokenizerState { |
| 10 final int index; | 10 final int index; |
| 11 final int startIndex; | 11 final int startIndex; |
| 12 final bool selectorExpression; | 12 final bool inSelectorExpression; |
| 13 final bool inSelector; |
| 13 | 14 |
| 14 TokenizerState(TokenizerBase base) : | 15 TokenizerState(TokenizerBase base) : |
| 15 this.index = base._index, | 16 index = base._index, |
| 16 this.startIndex = base._startIndex, | 17 startIndex = base._startIndex, |
| 17 this.selectorExpression = base.selectorExpression; | 18 inSelectorExpression = base.inSelectorExpression, |
| 19 inSelector = base.inSelector; |
| 18 } | 20 } |
| 19 | 21 |
| 20 /** | 22 /** |
| 21 * The base class for our tokenizer. The hand coded parts are in this file, with | 23 * The base class for our tokenizer. The hand coded parts are in this file, with |
| 22 * the generated parts in the subclass Tokenizer. | 24 * the generated parts in the subclass Tokenizer. |
| 23 */ | 25 */ |
| 24 abstract class TokenizerBase { | 26 abstract class TokenizerBase { |
| 25 final SourceFile _file; | 27 final SourceFile _file; |
| 26 final bool _skipWhitespace; | |
| 27 final String _text; | 28 final String _text; |
| 28 | 29 |
| 30 bool _skipWhitespace; |
| 31 |
| 29 /** | 32 /** |
| 30 * Changes tokenization when in a pseudo function expression. If true then | 33 * Changes tokenization when in a pseudo function expression. If true then |
| 31 * minus signs are handled as operators instead of identifiers. | 34 * minus signs are handled as operators instead of identifiers. |
| 32 */ | 35 */ |
| 33 bool selectorExpression = false; | 36 bool inSelectorExpression = false; |
| 37 |
| 38 /** |
| 39 * Changes tokenization when in selectors. If true, it prevents identifiers |
| 40 * from being treated as units. This would break things like ":lang(fr)" or |
| 41 * the HTML (unknown) tag name "px", which is legal to use in a selector. |
| 42 */ |
| 43 // TODO(jmesserly): is this a problem elsewhere? "fr" for example will be |
| 44 // processed as a "fraction" unit token, preventing it from working in |
| 45 // places where an identifier is expected. This was breaking selectors like: |
| 46 // :lang(fr) |
| 47 // The assumption that "fr" always means fraction (and similar issue with |
| 48 // other units) doesn't seem valid. We probably should defer this |
| 49 // analysis until we reach places in the parser where units are expected. |
| 50 // I'm not sure this is tokenizing as described in the specs: |
| 51 // http://dev.w3.org/csswg/css-syntax/ |
| 52 // http://dev.w3.org/csswg/selectors4/ |
| 53 bool inSelector = false; |
| 34 | 54 |
| 35 int _index; | 55 int _index; |
| 36 int _startIndex; | 56 int _startIndex; |
| 37 | 57 |
| 38 static const String _CDATA_START = '<![CDATA['; | 58 static const String _CDATA_START = '<![CDATA['; |
| 39 static const String _CDATA_END = ']]>'; | 59 static const String _CDATA_END = ']]>'; |
| 40 | 60 |
| 41 TokenizerBase(this._file, this._text, this._skipWhitespace, | 61 TokenizerBase(this._file, this._text, this._skipWhitespace, |
| 42 [this._index = 0]); | 62 [this._index = 0]); |
| 43 | 63 |
| 44 Token next(); | 64 Token next(); |
| 45 int getIdentifierKind(); | 65 int getIdentifierKind(); |
| 46 | 66 |
| 47 /** Snapshot of Tokenizer scanning state. */ | 67 /** Snapshot of Tokenizer scanning state. */ |
| 48 TokenizerState get mark => new TokenizerState(this); | 68 TokenizerState get mark => new TokenizerState(this); |
| 49 | 69 |
| 50 /** Restore Tokenizer scanning state. */ | 70 /** Restore Tokenizer scanning state. */ |
| 51 void restore(TokenizerState markedData) { | 71 void restore(TokenizerState markedData) { |
| 52 _index = markedData.index; | 72 _index = markedData.index; |
| 53 _startIndex = markedData.startIndex; | 73 _startIndex = markedData.startIndex; |
| 54 selectorExpression = markedData.selectorExpression; | 74 inSelectorExpression = markedData.inSelectorExpression; |
| 75 inSelector = markedData.inSelector; |
| 55 } | 76 } |
| 56 | 77 |
| 57 int _nextChar() { | 78 int _nextChar() { |
| 58 if (_index < _text.length) { | 79 if (_index < _text.length) { |
| 59 return _text.codeUnitAt(_index++); | 80 return _text.codeUnitAt(_index++); |
| 60 } else { | 81 } else { |
| 61 return 0; | 82 return 0; |
| 62 } | 83 } |
| 63 } | 84 } |
| 64 | 85 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 return next(); | 139 return next(); |
| 119 } else { | 140 } else { |
| 120 return _finishToken(TokenKind.WHITESPACE); | 141 return _finishToken(TokenKind.WHITESPACE); |
| 121 } | 142 } |
| 122 } | 143 } |
| 123 | 144 |
| 124 } | 145 } |
| 125 return _finishToken(TokenKind.END_OF_FILE); | 146 return _finishToken(TokenKind.END_OF_FILE); |
| 126 } | 147 } |
| 127 | 148 |
| 128 Token finishSingleLineComment() { | |
| 129 while (true) { | |
| 130 int ch = _nextChar(); | |
| 131 if (ch == 0 || ch == TokenChar.NEWLINE || ch == TokenChar.RETURN) { | |
| 132 if (_skipWhitespace) { | |
| 133 return next(); | |
| 134 } else { | |
| 135 return _finishToken(TokenKind.COMMENT); | |
| 136 } | |
| 137 } | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 Token finishMultiLineComment() { | 149 Token finishMultiLineComment() { |
| 142 int nesting = 1; | 150 int nesting = 1; |
| 143 do { | 151 do { |
| 144 int ch = _nextChar(); | 152 int ch = _nextChar(); |
| 145 if (ch == 0) { | 153 if (ch == 0) { |
| 146 return _errorToken(); | 154 return _errorToken(); |
| 147 } else if (ch == TokenChar.ASTERISK) { | 155 } else if (ch == TokenChar.ASTERISK) { |
| 148 if (_maybeEatChar(TokenChar.SLASH)) { | 156 if (_maybeEatChar(TokenChar.SLASH)) { |
| 149 nesting--; | 157 nesting--; |
| 150 } | 158 } |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 } | 427 } |
| 420 | 428 |
| 421 Token finishDot() { | 429 Token finishDot() { |
| 422 if (TokenizerHelpers.isDigit(_peekChar())) { | 430 if (TokenizerHelpers.isDigit(_peekChar())) { |
| 423 eatDigits(); | 431 eatDigits(); |
| 424 return finishNumberExtra(TokenKind.DOUBLE); | 432 return finishNumberExtra(TokenKind.DOUBLE); |
| 425 } else { | 433 } else { |
| 426 return _finishToken(TokenKind.DOT); | 434 return _finishToken(TokenKind.DOT); |
| 427 } | 435 } |
| 428 } | 436 } |
| 429 | |
| 430 Token finishIdentifier(int ch) { | |
| 431 while (_index < _text.length) { | |
| 432 if (!TokenizerHelpers.isIdentifierPart(_text.codeUnitAt(_index++))) { | |
| 433 _index--; | |
| 434 break; | |
| 435 } | |
| 436 } | |
| 437 int kind = getIdentifierKind(); | |
| 438 if (kind == TokenKind.IDENTIFIER) { | |
| 439 return _finishToken(TokenKind.IDENTIFIER); | |
| 440 } else { | |
| 441 return _finishToken(kind); | |
| 442 } | |
| 443 } | |
| 444 } | 437 } |
| 445 | 438 |
| OLD | NEW |