| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 // in object literals. | 335 // in object literals. |
| 336 Init(); | 336 Init(); |
| 337 // Skip initial whitespace allowing HTML comment ends just like | 337 // Skip initial whitespace allowing HTML comment ends just like |
| 338 // after a newline and scan first token. | 338 // after a newline and scan first token. |
| 339 has_line_terminator_before_next_ = true; | 339 has_line_terminator_before_next_ = true; |
| 340 SkipWhiteSpace(); | 340 SkipWhiteSpace(); |
| 341 Scan(); | 341 Scan(); |
| 342 } | 342 } |
| 343 | 343 |
| 344 | 344 |
| 345 // ---------------------------------------------------------------------------- | |
| 346 // JsonScanner | |
| 347 | |
| 348 JsonScanner::JsonScanner(UnicodeCache* unicode_cache) | |
| 349 : Scanner(unicode_cache) { } | |
| 350 | |
| 351 | |
| 352 void JsonScanner::Initialize(UC16CharacterStream* source) { | |
| 353 source_ = source; | |
| 354 Init(); | |
| 355 // Skip initial whitespace. | |
| 356 SkipJsonWhiteSpace(); | |
| 357 // Preload first token as look-ahead. | |
| 358 ScanJson(); | |
| 359 } | |
| 360 | |
| 361 | |
| 362 Token::Value JsonScanner::Next() { | |
| 363 // BUG 1215673: Find a thread safe way to set a stack limit in | |
| 364 // pre-parse mode. Otherwise, we cannot safely pre-parse from other | |
| 365 // threads. | |
| 366 current_ = next_; | |
| 367 // Check for stack-overflow before returning any tokens. | |
| 368 ScanJson(); | |
| 369 return current_.token; | |
| 370 } | |
| 371 | |
| 372 | |
| 373 bool JsonScanner::SkipJsonWhiteSpace() { | |
| 374 int start_position = source_pos(); | |
| 375 // JSON WhiteSpace is tab, carrige-return, newline and space. | |
| 376 while (c0_ == ' ' || c0_ == '\n' || c0_ == '\r' || c0_ == '\t') { | |
| 377 Advance(); | |
| 378 } | |
| 379 return source_pos() != start_position; | |
| 380 } | |
| 381 | |
| 382 | |
| 383 void JsonScanner::ScanJson() { | |
| 384 next_.literal_chars = NULL; | |
| 385 Token::Value token; | |
| 386 do { | |
| 387 // Remember the position of the next token | |
| 388 next_.location.beg_pos = source_pos(); | |
| 389 switch (c0_) { | |
| 390 case '\t': | |
| 391 case '\r': | |
| 392 case '\n': | |
| 393 case ' ': | |
| 394 Advance(); | |
| 395 token = Token::WHITESPACE; | |
| 396 break; | |
| 397 case '{': | |
| 398 Advance(); | |
| 399 token = Token::LBRACE; | |
| 400 break; | |
| 401 case '}': | |
| 402 Advance(); | |
| 403 token = Token::RBRACE; | |
| 404 break; | |
| 405 case '[': | |
| 406 Advance(); | |
| 407 token = Token::LBRACK; | |
| 408 break; | |
| 409 case ']': | |
| 410 Advance(); | |
| 411 token = Token::RBRACK; | |
| 412 break; | |
| 413 case ':': | |
| 414 Advance(); | |
| 415 token = Token::COLON; | |
| 416 break; | |
| 417 case ',': | |
| 418 Advance(); | |
| 419 token = Token::COMMA; | |
| 420 break; | |
| 421 case '"': | |
| 422 token = ScanJsonString(); | |
| 423 break; | |
| 424 case '-': | |
| 425 case '0': | |
| 426 case '1': | |
| 427 case '2': | |
| 428 case '3': | |
| 429 case '4': | |
| 430 case '5': | |
| 431 case '6': | |
| 432 case '7': | |
| 433 case '8': | |
| 434 case '9': | |
| 435 token = ScanJsonNumber(); | |
| 436 break; | |
| 437 case 't': | |
| 438 token = ScanJsonIdentifier("true", Token::TRUE_LITERAL); | |
| 439 break; | |
| 440 case 'f': | |
| 441 token = ScanJsonIdentifier("false", Token::FALSE_LITERAL); | |
| 442 break; | |
| 443 case 'n': | |
| 444 token = ScanJsonIdentifier("null", Token::NULL_LITERAL); | |
| 445 break; | |
| 446 default: | |
| 447 if (c0_ < 0) { | |
| 448 Advance(); | |
| 449 token = Token::EOS; | |
| 450 } else { | |
| 451 Advance(); | |
| 452 token = Select(Token::ILLEGAL); | |
| 453 } | |
| 454 } | |
| 455 } while (token == Token::WHITESPACE); | |
| 456 | |
| 457 next_.location.end_pos = source_pos(); | |
| 458 next_.token = token; | |
| 459 } | |
| 460 | |
| 461 | |
| 462 Token::Value JsonScanner::ScanJsonString() { | |
| 463 ASSERT_EQ('"', c0_); | |
| 464 Advance(); | |
| 465 LiteralScope literal(this); | |
| 466 while (c0_ != '"') { | |
| 467 // Check for control character (0x00-0x1f) or unterminated string (<0). | |
| 468 if (c0_ < 0x20) return Token::ILLEGAL; | |
| 469 if (c0_ != '\\') { | |
| 470 AddLiteralCharAdvance(); | |
| 471 } else { | |
| 472 Advance(); | |
| 473 switch (c0_) { | |
| 474 case '"': | |
| 475 case '\\': | |
| 476 case '/': | |
| 477 AddLiteralChar(c0_); | |
| 478 break; | |
| 479 case 'b': | |
| 480 AddLiteralChar('\x08'); | |
| 481 break; | |
| 482 case 'f': | |
| 483 AddLiteralChar('\x0c'); | |
| 484 break; | |
| 485 case 'n': | |
| 486 AddLiteralChar('\x0a'); | |
| 487 break; | |
| 488 case 'r': | |
| 489 AddLiteralChar('\x0d'); | |
| 490 break; | |
| 491 case 't': | |
| 492 AddLiteralChar('\x09'); | |
| 493 break; | |
| 494 case 'u': { | |
| 495 uc32 value = 0; | |
| 496 for (int i = 0; i < 4; i++) { | |
| 497 Advance(); | |
| 498 int digit = HexValue(c0_); | |
| 499 if (digit < 0) { | |
| 500 return Token::ILLEGAL; | |
| 501 } | |
| 502 value = value * 16 + digit; | |
| 503 } | |
| 504 AddLiteralChar(value); | |
| 505 break; | |
| 506 } | |
| 507 default: | |
| 508 return Token::ILLEGAL; | |
| 509 } | |
| 510 Advance(); | |
| 511 } | |
| 512 } | |
| 513 literal.Complete(); | |
| 514 Advance(); | |
| 515 return Token::STRING; | |
| 516 } | |
| 517 | |
| 518 | |
| 519 Token::Value JsonScanner::ScanJsonNumber() { | |
| 520 LiteralScope literal(this); | |
| 521 bool negative = false; | |
| 522 | |
| 523 if (c0_ == '-') { | |
| 524 AddLiteralCharAdvance(); | |
| 525 negative = true; | |
| 526 } | |
| 527 if (c0_ == '0') { | |
| 528 AddLiteralCharAdvance(); | |
| 529 // Prefix zero is only allowed if it's the only digit before | |
| 530 // a decimal point or exponent. | |
| 531 if ('0' <= c0_ && c0_ <= '9') return Token::ILLEGAL; | |
| 532 } else { | |
| 533 int i = 0; | |
| 534 int digits = 0; | |
| 535 if (c0_ < '1' || c0_ > '9') return Token::ILLEGAL; | |
| 536 do { | |
| 537 i = i * 10 + c0_ - '0'; | |
| 538 digits++; | |
| 539 AddLiteralCharAdvance(); | |
| 540 } while (c0_ >= '0' && c0_ <= '9'); | |
| 541 if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) { | |
| 542 number_ = (negative ? -i : i); | |
| 543 return Token::NUMBER; | |
| 544 } | |
| 545 } | |
| 546 if (c0_ == '.') { | |
| 547 AddLiteralCharAdvance(); | |
| 548 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; | |
| 549 do { | |
| 550 AddLiteralCharAdvance(); | |
| 551 } while (c0_ >= '0' && c0_ <= '9'); | |
| 552 } | |
| 553 if (AsciiAlphaToLower(c0_) == 'e') { | |
| 554 AddLiteralCharAdvance(); | |
| 555 if (c0_ == '-' || c0_ == '+') AddLiteralCharAdvance(); | |
| 556 if (c0_ < '0' || c0_ > '9') return Token::ILLEGAL; | |
| 557 do { | |
| 558 AddLiteralCharAdvance(); | |
| 559 } while (c0_ >= '0' && c0_ <= '9'); | |
| 560 } | |
| 561 literal.Complete(); | |
| 562 ASSERT_NOT_NULL(next_.literal_chars); | |
| 563 number_ = StringToDouble(unicode_cache_, | |
| 564 next_.literal_chars->ascii_literal(), | |
| 565 NO_FLAGS, // Hex, octal or trailing junk. | |
| 566 OS::nan_value()); | |
| 567 return Token::NUMBER; | |
| 568 } | |
| 569 | |
| 570 | |
| 571 Token::Value JsonScanner::ScanJsonIdentifier(const char* text, | |
| 572 Token::Value token) { | |
| 573 LiteralScope literal(this); | |
| 574 while (*text != '\0') { | |
| 575 if (c0_ != *text) return Token::ILLEGAL; | |
| 576 Advance(); | |
| 577 text++; | |
| 578 } | |
| 579 if (unicode_cache_->IsIdentifierPart(c0_)) return Token::ILLEGAL; | |
| 580 literal.Complete(); | |
| 581 return token; | |
| 582 } | |
| 583 | |
| 584 | |
| 585 } } // namespace v8::internal | 345 } } // namespace v8::internal |
| OLD | NEW |