Chromium Code Reviews| 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 /* | |
|
jimhug
2011/11/10 17:58:56
Is this relevant at all for css?
terry
2011/11/16 14:00:22
I think we might want this for string interpolatio
| |
| 21 if (istack.isMultiline) { | |
| 22 return finishMultilineStringBody(istack.quote); | |
| 23 } else { | |
| 24 return finishStringBody(istack.quote); | |
| 25 } | |
| 26 */ | |
| 27 } | |
| 28 | |
| 29 int ch; | |
| 30 ch = _nextChar(); | |
| 31 switch(ch) { | |
| 32 case 0: | |
| 33 return _finishToken(TokenKind.END_OF_FILE); | |
| 34 case TokenizerHelpers.WS_SPACE: | |
| 35 case TokenizerHelpers.WS_TAB: | |
| 36 case TokenizerHelpers.WS_NEWLINE: | |
| 37 case TokenizerHelpers.WS_RETURN: | |
| 38 return finishWhitespace(); | |
| 39 case cssTokens.tokens[TokenKind.END_OF_FILE]: | |
| 40 return _finishToken(TokenKind.END_OF_FILE); | |
| 41 case cssTokens.tokens[TokenKind.AT]: | |
| 42 return _finishToken(TokenKind.AT); | |
| 43 case cssTokens.tokens[TokenKind.DOT]: | |
| 44 return _finishToken(TokenKind.DOT); | |
| 45 case cssTokens.tokens[TokenKind.LBRACE]: | |
| 46 return _finishToken(TokenKind.LBRACE); | |
| 47 case cssTokens.tokens[TokenKind.RBRACE]: | |
| 48 return _finishToken(TokenKind.RBRACE); | |
| 49 case cssTokens.tokens[TokenKind.HASH]: | |
| 50 return _finishToken(TokenKind.HASH); | |
| 51 case cssTokens.tokens[TokenKind.COMBINATOR_PLUS]: | |
| 52 return _finishToken(TokenKind.COMBINATOR_PLUS); | |
| 53 case cssTokens.tokens[TokenKind.COMBINATOR_GREATER]: | |
| 54 return _finishToken(TokenKind.COMBINATOR_GREATER); | |
| 55 case cssTokens.tokens[TokenKind.COMBINATOR_TILDE]: | |
| 56 return _finishToken(TokenKind.COMBINATOR_TILDE); | |
| 57 case cssTokens.tokens[TokenKind.ASTERISK]: | |
| 58 return _finishToken(TokenKind.ASTERISK); | |
| 59 case cssTokens.tokens[TokenKind.NAMESPACE]: | |
| 60 return _finishToken(TokenKind.NAMESPACE); | |
| 61 case cssTokens.tokens[TokenKind.PSEUDO]: | |
| 62 return _finishToken(TokenKind.PSEUDO); | |
| 63 case cssTokens.tokens[TokenKind.COMMA]: | |
| 64 return _finishToken(TokenKind.COMMA); | |
| 65 | |
| 66 default: | |
| 67 if (isIdentifierStart(ch)) { | |
| 68 return this.finishIdentifier(); | |
| 69 } else if (isDigit(ch)) { | |
| 70 return this.finishNumber(); | |
| 71 } else { | |
| 72 return _errorToken(); | |
| 73 } | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 // TODO(jmesserly): we need a way to emit human readable error messages from | |
| 78 // the tokenizer. | |
| 79 lang.Token _errorToken() { | |
| 80 return _finishToken(TokenKind.ERROR); | |
| 81 } | |
| 82 | |
| 83 int getIdentifierKind() { | |
| 84 return TokenKind.IDENTIFIER; | |
| 85 } | |
| 86 | |
| 87 // Need to override so CSS version of isIdentifierPart is used. | |
| 88 lang.Token finishIdentifier() { | |
| 89 while (_index < _text.length) { | |
| 90 if (!TokenizerHelpers.isIdentifierPart(_text.charCodeAt(_index++))) { | |
| 91 _index--; | |
| 92 break; | |
| 93 } | |
| 94 } | |
| 95 int kind = getIdentifierKind(); | |
| 96 if (_interpStack != null && _interpStack.depth == -1) { | |
| 97 _interpStack.depth = 0; | |
| 98 } | |
| 99 if (kind == TokenKind.IDENTIFIER) { | |
| 100 return _finishToken(TokenKind.IDENTIFIER); | |
| 101 } else { | |
| 102 return _finishToken(kind); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 } | |
| 107 | |
| 108 /** Static helper methods. */ | |
| 109 class TokenizerHelpers { | |
|
jimhug
2011/11/10 17:58:56
Any reason not to use lang.TokenizerHelpers here?
terry
2011/11/16 14:00:22
Good point.
Done.
| |
| 110 final static int WS_SPACE = 32; // ' ' | |
| 111 final static int WS_TAB = 9; // '\t' | |
| 112 final static int WS_NEWLINE = 10; // '\n' | |
| 113 final static int WS_RETURN = 13; // '\r' | |
| 114 | |
| 115 static bool isIdentifierStart(int c) { | |
| 116 return ((c >= 97/*a*/ && c <= 122/*z*/) || (c >= 65/*A*/ && c <= 90/*Z*/) || c == 95/*_*/); | |
| 117 } | |
| 118 | |
| 119 static bool isDigit(int c) { | |
| 120 return (c >= 48/*0*/ && c <= 57/*9*/); | |
| 121 } | |
| 122 | |
| 123 static bool isHexDigit(int c) { | |
| 124 return (isDigit(c) || (c >= 97/*a*/ && c <= 102/*f*/) || (c >= 65/*A*/ && c <= 70/*F*/)); | |
| 125 } | |
| 126 | |
| 127 static bool isWhitespace(int c) { | |
| 128 return (c == 32/*' '*/ || c == 9/*'\t'*/ || c == 10/*'\n'*/ || c == 13/*'\r' */); | |
| 129 } | |
| 130 | |
| 131 static bool isIdentifierPart(int c) { | |
| 132 return (isIdentifierStart(c) || isDigit(c) || c == 45/*-*/); | |
| 133 } | |
| 134 } | |
| OLD | NEW |