Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: pkg/csslib/lib/src/tokenizer_base.dart

Issue 23168002: move csslib into dart svn (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/csslib/lib/src/tokenizer.dart ('k') | pkg/csslib/lib/src/tokenkind.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, 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 7
7 abstract class TokenSource { 8 /** Tokenizer state to support look ahead for Less' nested selectors. */
8 Token next(); 9 class TokenizerState {
9 } 10 final int index;
11 final int startIndex;
12 final bool selectorExpression;
10 13
11 class InterpStack { 14 TokenizerState(TokenizerBase base) :
12 InterpStack next, previous; 15 this.index = base._index,
13 final int quote; 16 this.startIndex = base._startIndex,
14 final bool isMultiline; 17 this.selectorExpression = base.selectorExpression;
15 int depth;
16
17 InterpStack(this.previous, this.quote, this.isMultiline): depth = -1;
18
19 InterpStack pop() {
20 return this.previous;
21 }
22
23 static InterpStack push(InterpStack stack, int quote, bool isMultiline) {
24 var newStack = new InterpStack(stack, quote, isMultiline);
25 if (stack != null) newStack.previous = stack;
26 return newStack;
27 }
28 } 18 }
29 19
30 /** 20 /**
31 * The base class for our tokenizer. The hand coded parts are in this file, with 21 * The base class for our tokenizer. The hand coded parts are in this file, with
32 * the generated parts in the subclass Tokenizer. 22 * the generated parts in the subclass Tokenizer.
33 */ 23 */
34 class CSSTokenizerBase implements TokenSource { 24 abstract class TokenizerBase {
35 final SourceFile _source; 25 final SourceFile _file;
36 final bool _skipWhitespace; 26 final bool _skipWhitespace;
37 String _text; 27 final String _text;
28
29 /**
30 * Changes tokenization when in a pseudo function expression. If true then
31 * minus signs are handled as operators instead of identifiers.
32 */
33 bool selectorExpression = false;
38 34
39 int _index; 35 int _index;
40 int _startIndex; 36 int _startIndex;
41 37
42 /** Keeps track of string interpolation state. */ 38 static const String _CDATA_START = '<![CDATA[';
43 InterpStack _interpStack; 39 static const String _CDATA_END = ']]>';
44 40
45 CSSTokenizerBase(this._source, this._skipWhitespace, [index = 0]) 41 TokenizerBase(this._file, this._text, this._skipWhitespace,
46 : this._index = index { 42 [this._index = 0]);
47 _text = _source.text; 43
44 Token next();
45 int getIdentifierKind();
46
47 /** Snapshot of Tokenizer scanning state. */
48 TokenizerState get mark => new TokenizerState(this);
49
50 /** Restore Tokenizer scanning state. */
51 void restore(TokenizerState markedData) {
52 _index = markedData.index;
53 _startIndex = markedData.startIndex;
54 selectorExpression = markedData.selectorExpression;
48 } 55 }
49 56
50 abstract Token next();
51 abstract int getIdentifierKind();
52
53 int _nextChar() { 57 int _nextChar() {
54 if (_index < _text.length) { 58 if (_index < _text.length) {
55 return _text.codeUnitAt(_index++); 59 return _text.codeUnitAt(_index++);
56 } else { 60 } else {
57 return 0; 61 return 0;
58 } 62 }
59 } 63 }
60 64
61 int _peekChar() { 65 int _peekChar() {
62 if (_index < _text.length) { 66 if (_index < _text.length) {
(...skipping 18 matching lines...) Expand all
81 85
82 String _tokenText() { 86 String _tokenText() {
83 if (_index < _text.length) { 87 if (_index < _text.length) {
84 return _text.substring(_startIndex, _index); 88 return _text.substring(_startIndex, _index);
85 } else { 89 } else {
86 return _text.substring(_startIndex, _text.length); 90 return _text.substring(_startIndex, _text.length);
87 } 91 }
88 } 92 }
89 93
90 Token _finishToken(int kind) { 94 Token _finishToken(int kind) {
91 return new Token(kind, _source, _startIndex, _index); 95 return new Token(kind, _file.span(_startIndex, _index));
92 } 96 }
93 97
94 Token _errorToken([String message = null]) { 98 Token _errorToken([String message = null]) {
95 return new ErrorToken( 99 return new ErrorToken(
96 TokenKind.ERROR, _source, _startIndex, _index, message); 100 TokenKind.ERROR, _file.span(_startIndex, _index), message);
97 } 101 }
98 102
99 Token finishWhitespace() { 103 Token finishWhitespace() {
100 _index--; 104 _index--;
101 while (_index < _text.length) { 105 while (_index < _text.length) {
102 final ch = _text.codeUnitAt(_index++); 106 final ch = _text.codeUnitAt(_index++);
103 if (ch == 32/*' '*/ || ch == 9/*'\t'*/ || ch == 13/*'\r'*/) { 107 if (ch == TokenChar.SPACE ||
108 ch == TokenChar.TAB ||
109 ch == TokenChar.RETURN) {
104 // do nothing 110 // do nothing
105 } else if (ch == 10/*'\n'*/) { 111 } else if (ch == TokenChar.NEWLINE) {
106 if (!_skipWhitespace) { 112 if (!_skipWhitespace) {
107 return _finishToken(TokenKind.WHITESPACE); // note the newline? 113 return _finishToken(TokenKind.WHITESPACE); // note the newline?
108 } 114 }
109 } else { 115 } else {
110 _index--; 116 _index--;
111 if (_skipWhitespace) { 117 if (_skipWhitespace) {
112 return next(); 118 return next();
113 } else { 119 } else {
114 return _finishToken(TokenKind.WHITESPACE); 120 return _finishToken(TokenKind.WHITESPACE);
115 } 121 }
116 } 122 }
117 123
118 } 124 }
119 return _finishToken(TokenKind.END_OF_FILE); 125 return _finishToken(TokenKind.END_OF_FILE);
120 } 126 }
121 127
122 Token finishSingleLineComment() { 128 Token finishSingleLineComment() {
123 while (true) { 129 while (true) {
124 int ch = _nextChar(); 130 int ch = _nextChar();
125 if (ch == 0 || ch == 10/*'\n'*/ || ch == 13/*'\r'*/) { 131 if (ch == 0 || ch == TokenChar.NEWLINE || ch == TokenChar.RETURN) {
126 if (_skipWhitespace) { 132 if (_skipWhitespace) {
127 return next(); 133 return next();
128 } else { 134 } else {
129 return _finishToken(TokenKind.COMMENT); 135 return _finishToken(TokenKind.COMMENT);
130 } 136 }
131 } 137 }
132 } 138 }
133 } 139 }
134 140
135 Token finishMultiLineComment() { 141 Token finishMultiLineComment() {
136 int nesting = 1; 142 int nesting = 1;
137 do { 143 do {
138 int ch = _nextChar(); 144 int ch = _nextChar();
139 if (ch == 0) { 145 if (ch == 0) {
140 return _errorToken(); 146 return _errorToken();
141 } else if (ch == 42/*'*'*/) { 147 } else if (ch == TokenChar.ASTERISK) {
142 if (_maybeEatChar(47/*'/'*/)) { 148 if (_maybeEatChar(TokenChar.SLASH)) {
143 nesting--; 149 nesting--;
144 } 150 }
145 } else if (ch == 47/*'/'*/) { 151 } else if (ch == TokenChar.SLASH) {
146 if (_maybeEatChar(42/*'*'*/)) { 152 if (_maybeEatChar(TokenChar.ASTERISK)) {
147 nesting++; 153 nesting++;
148 } 154 }
149 } 155 }
150 } while (nesting > 0); 156 } while (nesting > 0);
151 157
152 if (_skipWhitespace) { 158 if (_skipWhitespace) {
153 return next(); 159 return next();
154 } else { 160 } else {
155 return _finishToken(TokenKind.COMMENT); 161 return _finishToken(TokenKind.COMMENT);
156 } 162 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 result = (result * 16) + digit; 211 result = (result * 16) + digit;
206 _index++; 212 _index++;
207 } 213 }
208 214
209 return result; 215 return result;
210 } 216 }
211 217
212 Token finishNumber() { 218 Token finishNumber() {
213 eatDigits(); 219 eatDigits();
214 220
215 if (_peekChar() == 46/*.*/) { 221 if (_peekChar() == TokenChar.DOT) {
216 // Handle the case of 1.toString(). 222 // Handle the case of 1.toString().
217 _nextChar(); 223 _nextChar();
218 if (TokenizerHelpers.isDigit(_peekChar())) { 224 if (TokenizerHelpers.isDigit(_peekChar())) {
219 eatDigits(); 225 eatDigits();
220 return finishNumberExtra(TokenKind.DOUBLE); 226 return finishNumberExtra(TokenKind.DOUBLE);
221 } else { 227 } else {
222 _index--; 228 _index--;
223 } 229 }
224 } 230 }
225 231
226 return finishNumberExtra(TokenKind.INTEGER); 232 return finishNumberExtra(TokenKind.INTEGER);
227 } 233 }
228 234
229 Token finishNumberExtra(int kind) { 235 Token finishNumberExtra(int kind) {
230 if (_maybeEatChar(101/*e*/) || _maybeEatChar(69/*E*/)) { 236 if (_maybeEatChar(101/*e*/) || _maybeEatChar(69/*E*/)) {
231 kind = TokenKind.DOUBLE; 237 kind = TokenKind.DOUBLE;
232 _maybeEatChar(45/*-*/); 238 _maybeEatChar(TokenKind.MINUS);
233 _maybeEatChar(43/*+*/); 239 _maybeEatChar(TokenKind.PLUS);
234 eatDigits(); 240 eatDigits();
235 } 241 }
236 if (_peekChar() != 0 && TokenizerHelpers.isIdentifierStart(_peekChar())) { 242 if (_peekChar() != 0 && TokenizerHelpers.isIdentifierStart(_peekChar())) {
237 _nextChar(); 243 _nextChar();
238 return _errorToken("illegal character in number"); 244 return _errorToken("illegal character in number");
239 } 245 }
240 246
241 return _finishToken(kind); 247 return _finishToken(kind);
242 } 248 }
243 249
244 Token _makeStringToken(List<int> buf, bool isPart) { 250 Token _makeStringToken(List<int> buf, bool isPart) {
245 final s = new String.fromCharCodes(buf); 251 final s = new String.fromCharCodes(buf);
246 final kind = isPart ? TokenKind.STRING_PART : TokenKind.STRING; 252 final kind = isPart ? TokenKind.STRING_PART : TokenKind.STRING;
247 return new LiteralToken(kind, _source, _startIndex, _index, s); 253 return new LiteralToken(kind, _file.span(_startIndex, _index), s);
254 }
255
256 Token makeIEFilter(int start, int end) {
257 var filter = _text.substring(start, end);
258 return new LiteralToken(TokenKind.STRING, _file.span(start, end), filter);
248 } 259 }
249 260
250 Token _makeRawStringToken(bool isMultiline) { 261 Token _makeRawStringToken(bool isMultiline) {
251 String s; 262 var s;
252 if (isMultiline) { 263 if (isMultiline) {
253 // Skip initial newline in multiline strings 264 // Skip initial newline in multiline strings
254 int start = _startIndex + 4; 265 int start = _startIndex + 4;
255 if (_source.text[start] == '\n') start++; 266 if (_text[start] == '\n') start++;
256 s = _source.text.substring(start, _index - 3); 267 s = _text.substring(start, _index - 3);
257 } else { 268 } else {
258 s = _source.text.substring(_startIndex + 2, _index - 1); 269 s = _text.substring(_startIndex + 2, _index - 1);
259 } 270 }
260 return new LiteralToken(TokenKind.STRING, _source, _startIndex, _index, s); 271 return new LiteralToken(TokenKind.STRING,
272 _file.span(_startIndex, _index), s);
261 } 273 }
262 274
263 Token finishMultilineString(int quote) { 275 Token finishMultilineString(int quote) {
264 var buf = <int>[]; 276 var buf = <int>[];
265 while (true) { 277 while (true) {
266 int ch = _nextChar(); 278 int ch = _nextChar();
267 if (ch == 0) { 279 if (ch == 0) {
268 return _errorToken(); 280 return _errorToken();
269 } else if (ch == quote) { 281 } else if (ch == quote) {
270 if (_maybeEatChar(quote)) { 282 if (_maybeEatChar(quote)) {
271 if (_maybeEatChar(quote)) { 283 if (_maybeEatChar(quote)) {
272 return _makeStringToken(buf, false); 284 return _makeStringToken(buf, false);
273 } 285 }
274 buf.add(quote); 286 buf.add(quote);
275 } 287 }
276 buf.add(quote); 288 buf.add(quote);
277 } else if (ch == 36/*$*/) { 289 } else if (ch == TokenChar.BACKSLASH) {
278 // start of string interp
279 _interpStack = InterpStack.push(_interpStack, quote, true);
280 return _makeStringToken(buf, true);
281 } else if (ch == 92/*\*/) {
282 var escapeVal = readEscapeSequence(); 290 var escapeVal = readEscapeSequence();
283 if (escapeVal == -1) { 291 if (escapeVal == -1) {
284 return _errorToken("invalid hex escape sequence"); 292 return _errorToken("invalid hex escape sequence");
285 } else { 293 } else {
286 buf.add(escapeVal); 294 buf.add(escapeVal);
287 } 295 }
288 } else { 296 } else {
289 buf.add(ch); 297 buf.add(ch);
290 } 298 }
291 } 299 }
292 } 300 }
293 301
294 Token _finishOpenBrace() { 302 Token _finishOpenBrace() {
295 if (_interpStack != null) {
296 if (_interpStack.depth == -1) {
297 _interpStack.depth = 1;
298 } else {
299 assert(_interpStack.depth >= 0);
300 _interpStack.depth += 1;
301 }
302 }
303 return _finishToken(TokenKind.LBRACE); 303 return _finishToken(TokenKind.LBRACE);
304 } 304 }
305 305
306 Token _finishCloseBrace() { 306 Token _finishCloseBrace() {
307 if (_interpStack != null) {
308 _interpStack.depth -= 1;
309 assert(_interpStack.depth >= 0);
310 }
311 return _finishToken(TokenKind.RBRACE); 307 return _finishToken(TokenKind.RBRACE);
312 } 308 }
313 309
314 Token finishString(int quote) { 310 Token finishString(int quote) {
315 if (_maybeEatChar(quote)) { 311 if (_maybeEatChar(quote)) {
316 if (_maybeEatChar(quote)) { 312 if (_maybeEatChar(quote)) {
317 // skip an initial newline 313 // skip an initial newline
318 _maybeEatChar(10/*'\n'*/); 314 _maybeEatChar(TokenChar.NEWLINE);
319 return finishMultilineString(quote); 315 return finishMultilineString(quote);
320 } else { 316 } else {
321 return _makeStringToken(new List<int>(), false); 317 return _makeStringToken(new List<int>(), false);
322 } 318 }
323 } 319 }
324 return finishStringBody(quote); 320 return finishStringBody(quote);
325 } 321 }
326 322
327 Token finishRawString(int quote) { 323 Token finishRawString(int quote) {
328 if (_maybeEatChar(quote)) { 324 if (_maybeEatChar(quote)) {
(...skipping 23 matching lines...) Expand all
352 } 348 }
353 } 349 }
354 } 350 }
355 351
356 Token finishStringBody(int quote) { 352 Token finishStringBody(int quote) {
357 var buf = new List<int>(); 353 var buf = new List<int>();
358 while (true) { 354 while (true) {
359 int ch = _nextChar(); 355 int ch = _nextChar();
360 if (ch == quote) { 356 if (ch == quote) {
361 return _makeStringToken(buf, false); 357 return _makeStringToken(buf, false);
362 } else if (ch == 36/*$*/) {
363 // start of string interp
364 _interpStack = InterpStack.push(_interpStack, quote, false);
365 return _makeStringToken(buf, true);
366 } else if (ch == 0) { 358 } else if (ch == 0) {
367 return _errorToken(); 359 return _errorToken();
368 } else if (ch == 92/*\*/) { 360 } else if (ch == TokenChar.BACKSLASH) {
369 var escapeVal = readEscapeSequence(); 361 var escapeVal = readEscapeSequence();
370 if (escapeVal == -1) { 362 if (escapeVal == -1) {
371 return _errorToken("invalid hex escape sequence"); 363 return _errorToken("invalid hex escape sequence");
372 } else { 364 } else {
373 buf.add(escapeVal); 365 buf.add(escapeVal);
374 } 366 }
375 } else { 367 } else {
376 buf.add(ch); 368 buf.add(ch);
377 } 369 }
378 } 370 }
379 } 371 }
380 372
381 int readEscapeSequence() { 373 int readEscapeSequence() {
382 final ch = _nextChar(); 374 final ch = _nextChar();
383 int hexValue; 375 int hexValue;
384 switch (ch) { 376 switch (ch) {
385 case 110/*n*/: 377 case 110/*n*/:
386 return 0x0a/*'\n'*/; 378 return TokenChar.NEWLINE;
387 case 114/*r*/: 379 case 114/*r*/:
388 return 0x0d/*'\r'*/; 380 return TokenChar.RETURN;
389 case 102/*f*/: 381 case 102/*f*/:
390 return 0x0c/*'\f'*/; 382 return TokenChar.FF;
391 case 98/*b*/: 383 case 98/*b*/:
392 return 0x08/*'\b'*/; 384 return TokenChar.BACKSPACE;
393 case 116/*t*/: 385 case 116/*t*/:
394 return 0x09/*'\t'*/; 386 return TokenChar.TAB;
395 case 118/*v*/: 387 case 118/*v*/:
396 return 0x0b/*'\v'*/; 388 return TokenChar.FF;
397 case 120/*x*/: 389 case 120/*x*/:
398 hexValue = readHex(2); 390 hexValue = readHex(2);
399 break; 391 break;
400 case 117/*u*/: 392 case 117/*u*/:
401 if (_maybeEatChar(123/*{*/)) { 393 if (_maybeEatChar(TokenChar.LBRACE)) {
402 hexValue = readHex(); 394 hexValue = readHex();
403 if (!_maybeEatChar(125/*}*/)) { 395 if (!_maybeEatChar(TokenChar.RBRACE)) {
404 return -1; 396 return -1;
405 } else {
406 break;
407 } 397 }
408 } else { 398 } else {
409 hexValue = readHex(4); 399 hexValue = readHex(4);
410 break;
411 } 400 }
401 break;
412 default: return ch; 402 default: return ch;
413 } 403 }
414 404
415 if (hexValue == -1) return -1; 405 if (hexValue == -1) return -1;
416 406
417 // According to the Unicode standard the high and low surrogate halves 407 // According to the Unicode standard the high and low surrogate halves
418 // used by UTF-16 (U+D800 through U+DFFF) and values above U+10FFFF 408 // used by UTF-16 (U+D800 through U+DFFF) and values above U+10FFFF
419 // are not legal Unicode values. 409 // are not legal Unicode values.
420 if (hexValue < 0xD800 || hexValue > 0xDFFF && hexValue <= 0xFFFF) { 410 if (hexValue < 0xD800 || hexValue > 0xDFFF && hexValue <= 0xFFFF) {
421 return hexValue; 411 return hexValue;
422 } else if (hexValue <= 0x10FFFF){ 412 } else if (hexValue <= 0x10FFFF){
423 world.fatal('unicode values greater than 2 bytes not implemented yet'); 413 messages.error('unicode values greater than 2 bytes not implemented yet',
414 _file.span(_startIndex, _startIndex + 1));
424 return -1; 415 return -1;
425 } else { 416 } else {
426 return -1; 417 return -1;
427 } 418 }
428 } 419 }
429 420
430 Token finishDot() { 421 Token finishDot() {
431 if (TokenizerHelpers.isDigit(_peekChar())) { 422 if (TokenizerHelpers.isDigit(_peekChar())) {
432 eatDigits(); 423 eatDigits();
433 return finishNumberExtra(TokenKind.DOUBLE); 424 return finishNumberExtra(TokenKind.DOUBLE);
(...skipping 11 matching lines...) Expand all
445 } 436 }
446 int kind = getIdentifierKind(); 437 int kind = getIdentifierKind();
447 if (kind == TokenKind.IDENTIFIER) { 438 if (kind == TokenKind.IDENTIFIER) {
448 return _finishToken(TokenKind.IDENTIFIER); 439 return _finishToken(TokenKind.IDENTIFIER);
449 } else { 440 } else {
450 return _finishToken(kind); 441 return _finishToken(kind);
451 } 442 }
452 } 443 }
453 } 444 }
454 445
OLDNEW
« no previous file with comments | « pkg/csslib/lib/src/tokenizer.dart ('k') | pkg/csslib/lib/src/tokenkind.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698