OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 class Tokenizer extends lang.TokenizerBase { |
| 6 TokenKind cssTokens; |
| 7 |
| 8 Tokenizer(lang.SourceFile source, bool skipWhitespace, [int index = 0]) |
| 9 : super(source, skipWhitespace, index) { |
| 10 cssTokens = new TokenKind(); |
| 11 } |
| 12 |
| 13 lang.Token next() { |
| 14 // keep track of our starting position |
| 15 _startIndex = _index; |
| 16 |
| 17 if (_interpStack != null && _interpStack.depth == 0) { |
| 18 var istack = _interpStack; |
| 19 _interpStack = _interpStack.pop(); |
| 20 |
| 21 /* TODO(terry): Enable for variable and string interpolation. |
| 22 * if (istack.isMultiline) { |
| 23 * return finishMultilineStringBody(istack.quote); |
| 24 * } else { |
| 25 * return finishStringBody(istack.quote); |
| 26 * } |
| 27 */ |
| 28 } |
| 29 |
| 30 int ch; |
| 31 ch = _nextChar(); |
| 32 switch(ch) { |
| 33 case 0: |
| 34 return _finishToken(TokenKind.END_OF_FILE); |
| 35 case cssTokens.tokens[TokenKind.SPACE]: |
| 36 case cssTokens.tokens[TokenKind.TAB]: |
| 37 case cssTokens.tokens[TokenKind.NEWLINE]: |
| 38 case cssTokens.tokens[TokenKind.RETURN]: |
| 39 return finishWhitespace(); |
| 40 case cssTokens.tokens[TokenKind.END_OF_FILE]: |
| 41 return _finishToken(TokenKind.END_OF_FILE); |
| 42 case cssTokens.tokens[TokenKind.AT]: |
| 43 return _finishToken(TokenKind.AT); |
| 44 case cssTokens.tokens[TokenKind.DOT]: |
| 45 return _finishToken(TokenKind.DOT); |
| 46 case cssTokens.tokens[TokenKind.LBRACE]: |
| 47 return _finishToken(TokenKind.LBRACE); |
| 48 case cssTokens.tokens[TokenKind.RBRACE]: |
| 49 return _finishToken(TokenKind.RBRACE); |
| 50 case cssTokens.tokens[TokenKind.HASH]: |
| 51 return _finishToken(TokenKind.HASH); |
| 52 case cssTokens.tokens[TokenKind.COMBINATOR_PLUS]: |
| 53 return _finishToken(TokenKind.COMBINATOR_PLUS); |
| 54 case cssTokens.tokens[TokenKind.COMBINATOR_GREATER]: |
| 55 return _finishToken(TokenKind.COMBINATOR_GREATER); |
| 56 case cssTokens.tokens[TokenKind.COMBINATOR_TILDE]: |
| 57 return _finishToken(TokenKind.COMBINATOR_TILDE); |
| 58 case cssTokens.tokens[TokenKind.ASTERISK]: |
| 59 return _finishToken(TokenKind.ASTERISK); |
| 60 case cssTokens.tokens[TokenKind.NAMESPACE]: |
| 61 return _finishToken(TokenKind.NAMESPACE); |
| 62 case cssTokens.tokens[TokenKind.PSEUDO]: |
| 63 return _finishToken(TokenKind.PSEUDO); |
| 64 case cssTokens.tokens[TokenKind.COMMA]: |
| 65 return _finishToken(TokenKind.COMMA); |
| 66 |
| 67 default: |
| 68 if (isIdentifierStart(ch)) { |
| 69 return this.finishIdentifier(); |
| 70 } else if (isDigit(ch)) { |
| 71 return this.finishNumber(); |
| 72 } else { |
| 73 return _errorToken(); |
| 74 } |
| 75 } |
| 76 } |
| 77 |
| 78 // TODO(jmesserly): we need a way to emit human readable error messages from |
| 79 // the tokenizer. |
| 80 lang.Token _errorToken() { |
| 81 return _finishToken(TokenKind.ERROR); |
| 82 } |
| 83 |
| 84 int getIdentifierKind() { |
| 85 return TokenKind.IDENTIFIER; |
| 86 } |
| 87 |
| 88 // Need to override so CSS version of isIdentifierPart is used. |
| 89 lang.Token finishIdentifier() { |
| 90 while (_index < _text.length) { |
| 91 if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) { |
| 92 _index--; |
| 93 break; |
| 94 } |
| 95 } |
| 96 int kind = getIdentifierKind(); |
| 97 if (_interpStack != null && _interpStack.depth == -1) { |
| 98 _interpStack.depth = 0; |
| 99 } |
| 100 if (kind == TokenKind.IDENTIFIER) { |
| 101 return _finishToken(TokenKind.IDENTIFIER); |
| 102 } else { |
| 103 return _finishToken(kind); |
| 104 } |
| 105 } |
| 106 |
| 107 } |
| 108 |
| 109 /** Static helper methods. */ |
| 110 class TokenizerHelpers { |
| 111 static bool isIdentifierStart(int c) => |
| 112 lang.TokenizerHelpers.isIdentifierStart(c) || c == 95 /*_*/; |
| 113 |
| 114 static bool isDigit(int c) => lang.TokenizerHelpers.isDigit(c); |
| 115 |
| 116 static bool isHexDigit(int c) => lang.TokenizerHelpers.isHexDigit(c); |
| 117 |
| 118 static bool isWhitespace(int c) => lang.TokenizerHelpers.isWhitespace(c); |
| 119 |
| 120 static bool isIdentifierPart(int c) => |
| 121 lang.TokenizerHelpers.isIdentifierPart(c) || c == 45 /*-*/; |
| 122 } |
OLD | NEW |