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 |