Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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 | 6 |
| 7 interface TokenSource { | 7 interface TokenSource { |
| 8 Token next(); | 8 Token next(); |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 | 89 |
| 90 Token _finishToken(int kind) { | 90 Token _finishToken(int kind) { |
| 91 return new Token(kind, _source, _startIndex, _index); | 91 return new Token(kind, _source, _startIndex, _index); |
| 92 } | 92 } |
| 93 | 93 |
| 94 Token _errorToken([String message = null]) { | 94 Token _errorToken([String message = null]) { |
| 95 return new ErrorToken( | 95 return new ErrorToken( |
| 96 TokenKind.ERROR, _source, _startIndex, _index, message); | 96 TokenKind.ERROR, _source, _startIndex, _index, message); |
| 97 } | 97 } |
| 98 | 98 |
| 99 Token nextFromPreviousLine(int kind) { | |
| 100 _startIndex = _index; | |
| 101 | |
| 102 switch(kind) { | |
| 103 case TokenKind.INCOMPLETE_COMMENT: | |
| 104 return finishMultiLineComment(); | |
| 105 case TokenKind.INCOMPLETE_MULTILINE_STRING_DQ: | |
| 106 return finishMultilineString(34/*"*/); | |
| 107 case TokenKind.INCOMPLETE_MULTILINE_STRING_SQ: | |
| 108 return finishMultilineString(39/*'*/); | |
| 109 default: | |
| 110 return next(); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 Token finishWhitespace() { | 99 Token finishWhitespace() { |
| 115 _index--; | 100 _index--; |
| 116 while (_index < _text.length) { | 101 while (_index < _text.length) { |
| 117 final ch = _text.charCodeAt(_index++); | 102 final ch = _text.charCodeAt(_index++); |
| 118 if (ch == 32/*' '*/ || ch == 9/*'\t'*/ || ch == 13/*'\r'*/) { | 103 if (ch == 32/*' '*/ || ch == 9/*'\t'*/ || ch == 13/*'\r'*/) { |
| 119 // do nothing | 104 // do nothing |
| 120 } else if (ch == 10/*'\n'*/) { | 105 } else if (ch == 10/*'\n'*/) { |
| 121 if (!_skipWhitespace) { | 106 if (!_skipWhitespace) { |
| 122 return _finishToken(TokenKind.WHITESPACE); // note the newline? | 107 return _finishToken(TokenKind.WHITESPACE); // note the newline? |
| 123 } | 108 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 154 } | 139 } |
| 155 } | 140 } |
| 156 } | 141 } |
| 157 } | 142 } |
| 158 | 143 |
| 159 Token finishMultiLineComment() { | 144 Token finishMultiLineComment() { |
| 160 int nesting = 1; | 145 int nesting = 1; |
| 161 do { | 146 do { |
| 162 int ch = _nextChar(); | 147 int ch = _nextChar(); |
| 163 if (ch == 0) { | 148 if (ch == 0) { |
| 164 return _finishToken(TokenKind.INCOMPLETE_COMMENT); | 149 return _errorToken(); |
| 165 } else if (ch == 42/*'*'*/) { | 150 } else if (ch == 42/*'*'*/) { |
| 166 if (_maybeEatChar(47/*'/'*/)) { | 151 if (_maybeEatChar(47/*'/'*/)) { |
| 167 nesting--; | 152 nesting--; |
| 168 } | 153 } |
| 169 } else if (ch == 47/*'/'*/) { | 154 } else if (ch == 47/*'/'*/) { |
| 170 if (_maybeEatChar(42/*'*'*/)) { | 155 if (_maybeEatChar(42/*'*'*/)) { |
| 171 nesting++; | 156 nesting++; |
| 172 } | 157 } |
| 173 } | 158 } |
| 174 } while (nesting > 0); | 159 } while (nesting > 0); |
| 175 | 160 |
| 176 if (_skipWhitespace) { | 161 if (_skipWhitespace) { |
| 177 return next(); | 162 return next(); |
| 178 } else { | 163 } else { |
| 179 return _finishToken(TokenKind.COMMENT); | 164 return _finishToken(TokenKind.COMMENT); |
| 180 } | 165 } |
| 181 } | 166 } |
| 182 | 167 |
| 183 void eatDigits() { | 168 void eatDigits() { |
| 184 while (_index < _text.length) { | 169 while (_index < _text.length) { |
| 185 if (isDigit(_text.charCodeAt(_index))) { | 170 if (isDigit(_text.charCodeAt(_index))) { |
| 186 _index++; | 171 _index++; |
| 187 } else { | 172 } else { |
| 188 return; | 173 return; |
| 189 } | 174 } |
| 190 } | 175 } |
| 191 } | 176 } |
| 192 | 177 |
| 193 void eatHexDigits() { | 178 static int _hexDigit(int c) { |
| 194 while (_index < _text.length) { | 179 if(c >= 48/*0*/ && c <= 57/*9*/) { |
| 195 if (isHexDigit(_text.charCodeAt(_index))) { | 180 return c - 48; |
| 196 _index++; | 181 } else if (c >= 97/*a*/ && c <= 102/*f*/) { |
| 197 } else { | 182 return c - 87; |
| 198 return; | 183 } else if (c >= 65/*A*/ && c <= 70/*F*/) { |
| 199 } | 184 return c - 55; |
| 185 } else { | |
| 186 return -1; | |
| 200 } | 187 } |
| 201 } | 188 } |
| 202 | 189 |
| 203 bool maybeEatHexDigit() { | 190 int readHex([int hexLength]) { |
| 204 if (_index < _text.length && isHexDigit(_text.charCodeAt(_index))) { | 191 int maxIndex; |
| 192 if (hexLength === null) { | |
| 193 maxIndex = _text.length - 1; | |
| 194 } else { | |
| 195 // TODO(jimhug): What if this is too long? | |
| 196 maxIndex = _index + hexLength; | |
| 197 if (maxIndex >= _text.length) return -1; | |
| 198 } | |
| 199 var result = 0; | |
| 200 while (_index < maxIndex) { | |
| 201 final digit = _hexDigit(_text.charCodeAt(_index)); | |
| 202 if (digit == -1) { | |
| 203 if (hexLength === null) { | |
| 204 return result; | |
| 205 } else { | |
| 206 return -1; | |
| 207 } | |
| 208 } | |
| 209 _hexDigit(_text.charCodeAt(_index)); | |
| 210 // Multiply by 16 rather than shift by 4 since that will result in a | |
| 211 // correct value for numbers that exceed the 32 bit precision of JS | |
| 212 // 'integers'. | |
| 213 // TODO: Figure out a better solution to integer truncation. Issue 638. | |
| 214 result = (result * 16) + digit; | |
| 205 _index++; | 215 _index++; |
| 206 return true; | |
| 207 } | 216 } |
| 208 return false; | 217 |
| 218 return result; | |
| 209 } | 219 } |
| 210 | 220 |
| 211 Token finishHex() { | 221 Token finishHex() { |
| 212 eatHexDigits(); | 222 final value = readHex(); |
| 213 return _finishToken(TokenKind.HEX_INTEGER); | 223 return new LiteralToken(TokenKind.HEX_INTEGER, _source, _startIndex, |
| 224 _index, value); | |
| 214 } | 225 } |
| 215 | 226 |
| 216 Token finishNumber() { | 227 Token finishNumber() { |
| 217 eatDigits(); | 228 eatDigits(); |
| 218 | 229 |
| 219 if (_peekChar() == 46/*.*/) { | 230 if (_peekChar() == 46/*.*/) { |
| 220 // Handle the case of 1.toString(). | 231 // Handle the case of 1.toString(). |
| 221 _nextChar(); | 232 _nextChar(); |
| 222 if (isDigit(_peekChar())) { | 233 if (isDigit(_peekChar())) { |
| 223 eatDigits(); | 234 eatDigits(); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 238 eatDigits(); | 249 eatDigits(); |
| 239 } | 250 } |
| 240 if (_peekChar() != 0 && isIdentifierStart(_peekChar())) { | 251 if (_peekChar() != 0 && isIdentifierStart(_peekChar())) { |
| 241 _nextChar(); | 252 _nextChar(); |
| 242 return _errorToken("illegal character in number"); | 253 return _errorToken("illegal character in number"); |
| 243 } | 254 } |
| 244 | 255 |
| 245 return _finishToken(kind); | 256 return _finishToken(kind); |
| 246 } | 257 } |
| 247 | 258 |
| 259 Token _makeStringToken(List<int> buf, bool isPart) { | |
| 260 final s = new String.fromCharCodes(buf); | |
| 261 final kind = isPart ? TokenKind.STRING_PART : TokenKind.STRING; | |
| 262 return new LiteralToken(kind, _source, _startIndex, _index, s); | |
| 263 } | |
| 264 | |
| 265 Token _makeRawStringToken(bool isMultiline) { | |
| 266 String s; | |
| 267 if (isMultiline) { | |
| 268 // Skip initial newline in multiline strings | |
| 269 if (_source.text[_startIndex + 4] == '\n') { | |
|
Jennifer Messerly
2012/01/09 20:16:26
might be nice to tweak this as:
int start = _star
jimhug
2012/01/09 21:19:05
Nice - done.
On 2012/01/09 20:16:26, John Messerly
| |
| 270 s = _source.text.substring(_startIndex + 5, _index - 3); | |
| 271 } else { | |
| 272 s = _source.text.substring(_startIndex + 4, _index - 3); | |
| 273 } | |
| 274 } else { | |
| 275 s = _source.text.substring(_startIndex + 2, _index - 1); | |
| 276 } | |
| 277 return new LiteralToken(TokenKind.STRING, _source, _startIndex, _index, s); | |
| 278 } | |
| 279 | |
| 248 Token finishMultilineString(int quote) { | 280 Token finishMultilineString(int quote) { |
| 281 var buf = new List<int>(); | |
|
Jennifer Messerly
2012/01/09 20:16:26
<int>[] ?
jimhug
2012/01/09 21:19:05
Done.
| |
| 249 while (true) { | 282 while (true) { |
| 250 int ch = _nextChar(); | 283 int ch = _nextChar(); |
| 251 if (ch == 0) { | 284 if (ch == 0) { |
| 252 final kind = quote == 34/*"*/ ? | 285 return _errorToken(); |
| 253 TokenKind.INCOMPLETE_MULTILINE_STRING_DQ : | |
| 254 TokenKind.INCOMPLETE_MULTILINE_STRING_SQ; | |
| 255 return _finishToken(kind); | |
| 256 } else if (ch == quote) { | 286 } else if (ch == quote) { |
| 257 if (_maybeEatChar(quote)) { | 287 if (_maybeEatChar(quote)) { |
| 258 if (_maybeEatChar(quote)) { | 288 if (_maybeEatChar(quote)) { |
| 259 return _finishToken(TokenKind.STRING); | 289 return _makeStringToken(buf, false); |
| 260 } | 290 } |
| 291 buf.add(quote); | |
| 261 } | 292 } |
| 293 buf.add(quote); | |
| 262 } else if (ch == 36/*$*/) { | 294 } else if (ch == 36/*$*/) { |
| 263 // start of string interp | 295 // start of string interp |
| 264 _interpStack = InterpStack.push(_interpStack, quote, true); | 296 _interpStack = InterpStack.push(_interpStack, quote, true); |
| 265 return _finishToken(TokenKind.INCOMPLETE_STRING); // TODO | 297 return _makeStringToken(buf, true); |
| 266 } else if (ch == 92/*\*/) { | 298 } else if (ch == 92/*\*/) { |
| 267 if (!eatEscapeSequence()) { | 299 var escapeVal = readEscapeSequence(); |
| 300 if (escapeVal == -1) { | |
| 268 return _errorToken("invalid hex escape sequence"); | 301 return _errorToken("invalid hex escape sequence"); |
| 302 } else { | |
| 303 buf.add(escapeVal); | |
| 269 } | 304 } |
| 305 } else { | |
| 306 buf.add(ch); | |
| 270 } | 307 } |
| 271 } | 308 } |
| 272 } | 309 } |
| 273 | 310 |
| 274 Token _finishOpenBrace() { | 311 Token _finishOpenBrace() { |
| 275 if (_interpStack != null) { | 312 if (_interpStack != null) { |
| 276 if (_interpStack.depth == -1) { | 313 if (_interpStack.depth == -1) { |
| 277 _interpStack.depth = 1; | 314 _interpStack.depth = 1; |
| 278 } else { | 315 } else { |
| 279 assert(_interpStack.depth >= 0); | 316 assert(_interpStack.depth >= 0); |
| 280 _interpStack.depth += 1; | 317 _interpStack.depth += 1; |
| 281 } | 318 } |
| 282 } | 319 } |
| 283 return _finishToken(TokenKind.LBRACE); | 320 return _finishToken(TokenKind.LBRACE); |
| 284 } | 321 } |
| 285 | 322 |
| 286 Token _finishCloseBrace() { | 323 Token _finishCloseBrace() { |
| 287 if (_interpStack != null) { | 324 if (_interpStack != null) { |
| 288 _interpStack.depth -= 1; | 325 _interpStack.depth -= 1; |
| 289 assert(_interpStack.depth >= 0); | 326 assert(_interpStack.depth >= 0); |
| 290 } | 327 } |
| 291 return _finishToken(TokenKind.RBRACE); | 328 return _finishToken(TokenKind.RBRACE); |
| 292 } | 329 } |
| 293 | 330 |
| 294 Token finishString(int quote) { | 331 Token finishString(int quote) { |
| 295 if (_maybeEatChar(quote)) { | 332 if (_maybeEatChar(quote)) { |
| 296 if (_maybeEatChar(quote)) { | 333 if (_maybeEatChar(quote)) { |
| 334 // skip an initial newline | |
| 335 _maybeEatChar(10/*'\n'*/); | |
| 297 return finishMultilineString(quote); | 336 return finishMultilineString(quote); |
| 298 } else { | 337 } else { |
| 299 return _finishToken(TokenKind.STRING); | 338 return _makeStringToken(new List<int>(), false); |
| 300 } | 339 } |
| 301 } | 340 } |
| 302 return finishStringBody(quote); | 341 return finishStringBody(quote); |
| 303 } | 342 } |
| 304 | 343 |
| 305 Token finishRawString(int quote) { | 344 Token finishRawString(int quote) { |
| 306 if (_maybeEatChar(quote)) { | 345 if (_maybeEatChar(quote)) { |
| 307 if (_maybeEatChar(quote)) { | 346 if (_maybeEatChar(quote)) { |
| 308 return finishMultilineRawString(quote); | 347 return finishMultilineRawString(quote); |
| 309 } else { | 348 } else { |
| 310 return _finishToken(TokenKind.STRING); | 349 return _makeStringToken(new List<int>(), false); |
|
Jennifer Messerly
2012/01/09 20:16:26
<int>[] ?
jimhug
2012/01/09 21:19:05
Done.
| |
| 311 } | 350 } |
| 312 } | 351 } |
| 313 while (true) { | 352 while (true) { |
| 314 int ch = _nextChar(); | 353 int ch = _nextChar(); |
| 315 if (ch == quote) { | 354 if (ch == quote) { |
| 316 return _finishToken(TokenKind.STRING); | 355 return _makeRawStringToken(false); |
| 317 } else if (ch == 0) { | 356 } else if (ch == 0) { |
| 318 return _finishToken(TokenKind.INCOMPLETE_STRING); | 357 return _errorToken(); |
| 319 } | 358 } |
| 320 } | 359 } |
| 321 } | 360 } |
| 322 | 361 |
| 323 Token finishMultilineRawString(int quote) { | 362 Token finishMultilineRawString(int quote) { |
| 324 while (true) { | 363 while (true) { |
| 325 int ch = _nextChar(); | 364 int ch = _nextChar(); |
| 326 if (ch == 0) { | 365 if (ch == 0) { |
| 327 final kind = quote == 34/*"*/ ? | 366 return _errorToken(); |
| 328 TokenKind.INCOMPLETE_MULTILINE_STRING_DQ : | |
| 329 TokenKind.INCOMPLETE_MULTILINE_STRING_SQ; | |
| 330 return _finishToken(kind); | |
| 331 } else if (ch == quote && _maybeEatChar(quote) && _maybeEatChar(quote)) { | 367 } else if (ch == quote && _maybeEatChar(quote) && _maybeEatChar(quote)) { |
| 332 return _finishToken(TokenKind.STRING); | 368 return _makeRawStringToken(true); |
| 333 } | 369 } |
| 334 } | 370 } |
| 335 } | 371 } |
| 336 | 372 |
| 337 Token finishStringBody(int quote) { | 373 Token finishStringBody(int quote) { |
| 374 var buf = new List<int>(); | |
| 338 while (true) { | 375 while (true) { |
| 339 int ch = _nextChar(); | 376 int ch = _nextChar(); |
| 340 if (ch == quote) { | 377 if (ch == quote) { |
| 341 return _finishToken(TokenKind.STRING); | 378 return _makeStringToken(buf, false); |
| 342 } else if (ch == 36/*$*/) { | 379 } else if (ch == 36/*$*/) { |
| 343 // start of string interp | 380 // start of string interp |
| 344 _interpStack = InterpStack.push(_interpStack, quote, false); | 381 _interpStack = InterpStack.push(_interpStack, quote, false); |
| 345 return _finishToken(TokenKind.INCOMPLETE_STRING); // TODO | 382 return _makeStringToken(buf, true); |
| 346 } else if (ch == 0) { | 383 } else if (ch == 0) { |
| 347 return _finishToken(TokenKind.INCOMPLETE_STRING); | 384 return _errorToken(); |
| 348 } else if (ch == 92/*\*/) { | 385 } else if (ch == 92/*\*/) { |
| 349 if (!eatEscapeSequence()) { | 386 var escapeVal = readEscapeSequence(); |
| 387 if (escapeVal == -1) { | |
| 350 return _errorToken("invalid hex escape sequence"); | 388 return _errorToken("invalid hex escape sequence"); |
| 389 } else { | |
| 390 buf.add(escapeVal); | |
| 351 } | 391 } |
| 392 } else { | |
| 393 buf.add(ch); | |
| 352 } | 394 } |
| 353 } | 395 } |
| 354 } | 396 } |
| 355 | 397 |
| 356 bool eatEscapeSequence() { | 398 int readEscapeSequence() { |
| 357 String hex; | 399 final ch = _nextChar(); |
| 358 switch (_nextChar()) { | 400 int hexValue; |
| 401 switch (ch) { | |
| 402 case 110/*n*/: | |
| 403 return 0x0a/*'\n'*/; | |
| 404 case 114/*r*/: | |
| 405 return 0x0d/*'\r'*/; | |
| 406 case 102/*f*/: | |
| 407 return 0x0c/*'\f'*/; | |
| 408 case 98/*b*/: | |
| 409 return 0x08/*'\b'*/; | |
| 410 case 116/*t*/: | |
| 411 return 0x09/*'\t'*/; | |
| 412 case 118/*v*/: | |
| 413 return 0x0b/*'\v'*/; | |
| 359 case 120/*x*/: | 414 case 120/*x*/: |
| 360 return maybeEatHexDigit() && maybeEatHexDigit(); | 415 hexValue = readHex(2); |
| 416 break; | |
| 361 case 117/*u*/: | 417 case 117/*u*/: |
| 362 if (_maybeEatChar(123/*{*/)) { | 418 if (_maybeEatChar(123/*{*/)) { |
| 363 int start = _index; | 419 hexValue = readHex(); |
| 364 eatHexDigits(); | 420 if (!_maybeEatChar(125/*}*/)) { |
| 365 int chars = _index - start; | 421 return -1; |
| 366 if (chars > 0 && chars <= 6 && _maybeEatChar(125/*}*/)) { | 422 } else { |
| 367 hex = _text.substring(start, start + chars); | |
| 368 break; | 423 break; |
| 369 } else { | |
| 370 return false; | |
| 371 } | 424 } |
| 372 } else { | 425 } else { |
| 373 if (maybeEatHexDigit() && maybeEatHexDigit() && | 426 hexValue = readHex(4); |
| 374 maybeEatHexDigit() && maybeEatHexDigit()) { | 427 break; |
| 375 hex = _text.substring(_index - 4, _index); | |
| 376 break; | |
| 377 } else { | |
| 378 return false; | |
| 379 } | |
| 380 } | 428 } |
| 381 default: return true; | 429 default: return ch; |
| 382 } | 430 } |
| 431 | |
| 432 if (hexValue == -1) return -1; | |
| 433 | |
| 383 // According to the Unicode standard the high and low surrogate halves | 434 // According to the Unicode standard the high and low surrogate halves |
| 384 // used by UTF-16 (U+D800 through U+DFFF) and values above U+10FFFF | 435 // used by UTF-16 (U+D800 through U+DFFF) and values above U+10FFFF |
| 385 // are not legal Unicode values. | 436 // are not legal Unicode values. |
| 386 num n = Parser.parseHex(hex); | 437 if (hexValue < 0xD800 || hexValue > 0xDFFF && hexValue <= 0xFFFF) { |
| 387 return n < 0xD800 || n > 0xDFFF && n <= 0x10FFFF; | 438 return hexValue; |
| 439 } else if (hexValue <= 0x10FFFF){ | |
| 440 world.fatal('unicode values greater than 2 bytes not implemented yet'); | |
| 441 return -1; | |
| 442 } else { | |
| 443 return -1; | |
| 444 } | |
| 388 } | 445 } |
| 389 | 446 |
| 390 Token finishDot() { | 447 Token finishDot() { |
| 391 if (isDigit(_peekChar())) { | 448 if (isDigit(_peekChar())) { |
| 392 eatDigits(); | 449 eatDigits(); |
| 393 return finishNumberExtra(TokenKind.DOUBLE); | 450 return finishNumberExtra(TokenKind.DOUBLE); |
| 394 } else { | 451 } else { |
| 395 return _finishToken(TokenKind.DOT); | 452 return _finishToken(TokenKind.DOT); |
| 396 } | 453 } |
| 397 } | 454 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 418 } | 475 } |
| 419 } | 476 } |
| 420 int kind = getIdentifierKind(); | 477 int kind = getIdentifierKind(); |
| 421 if (kind == TokenKind.IDENTIFIER) { | 478 if (kind == TokenKind.IDENTIFIER) { |
| 422 return _finishToken(TokenKind.IDENTIFIER); | 479 return _finishToken(TokenKind.IDENTIFIER); |
| 423 } else { | 480 } else { |
| 424 return _finishToken(kind); | 481 return _finishToken(kind); |
| 425 } | 482 } |
| 426 } | 483 } |
| 427 } | 484 } |
| OLD | NEW |