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

Side by Side Diff: src/parser.cc

Issue 12826: RegExp stack and zone limits. (Closed)
Patch Set: Created 12 years 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
« no previous file with comments | « no previous file | src/top.h » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 terms_.Add(new RegExpQuantifier(min, max, is_greedy, atom)); 488 terms_.Add(new RegExpQuantifier(min, max, is_greedy, atom));
489 LAST(ADD_TERM); 489 LAST(ADD_TERM);
490 } 490 }
491 491
492 492
493 class RegExpParser { 493 class RegExpParser {
494 public: 494 public:
495 RegExpParser(FlatStringReader* in, 495 RegExpParser(FlatStringReader* in,
496 Handle<String>* error, 496 Handle<String>* error,
497 bool multiline_mode); 497 bool multiline_mode);
498 RegExpTree* ParsePattern(bool* ok); 498 RegExpTree* ParsePattern();
499 RegExpTree* ParseDisjunction(bool* ok); 499 RegExpTree* ParseDisjunction();
500 RegExpTree* ParseGroup(bool* ok); 500 RegExpTree* ParseGroup();
501 RegExpTree* ParseCharacterClass(bool* ok); 501 RegExpTree* ParseCharacterClass();
502 502
503 // Parses a {...,...} quantifier and stores the range in the given 503 // Parses a {...,...} quantifier and stores the range in the given
504 // out parameters. 504 // out parameters.
505 bool ParseIntervalQuantifier(int* min_out, int* max_out); 505 bool ParseIntervalQuantifier(int* min_out, int* max_out);
506 506
507 // Parses and returns a single escaped character. The character 507 // Parses and returns a single escaped character. The character
508 // must not be 'b' or 'B' since they are usually handle specially. 508 // must not be 'b' or 'B' since they are usually handle specially.
509 uc32 ParseClassCharacterEscape(bool* ok); 509 uc32 ParseClassCharacterEscape();
510 510
511 // Checks whether the following is a length-digit hexadecimal number, 511 // Checks whether the following is a length-digit hexadecimal number,
512 // and sets the value if it is. 512 // and sets the value if it is.
513 bool ParseHexEscape(int length, uc32* value); 513 bool ParseHexEscape(int length, uc32* value);
514 514
515 uc32 ParseControlLetterEscape(bool* ok); 515 uc32 ParseControlLetterEscape();
516 uc32 ParseOctalLiteral(); 516 uc32 ParseOctalLiteral();
517 517
518 // Tries to parse the input as a back reference. If successful it 518 // Tries to parse the input as a back reference. If successful it
519 // stores the result in the output parameter and returns true. If 519 // stores the result in the output parameter and returns true. If
520 // it fails it will push back the characters read so the same characters 520 // it fails it will push back the characters read so the same characters
521 // can be reparsed. 521 // can be reparsed.
522 bool ParseBackReferenceIndex(int* index_out); 522 bool ParseBackReferenceIndex(int* index_out);
523 523
524 CharacterRange ParseClassAtom(uc16* char_class, 524 CharacterRange ParseClassAtom(uc16* char_class);
525 bool* ok); 525 RegExpTree* ReportError(Vector<const char> message);
526 RegExpTree* ReportError(Vector<const char> message, bool* ok);
527 void Advance(); 526 void Advance();
528 void Advance(int dist); 527 void Advance(int dist);
529 void Reset(int pos); 528 void Reset(int pos);
530 529
531 bool HasCharacterEscapes(); 530 bool HasCharacterEscapes();
532 531
533 int captures_started() { return captures_ == NULL ? 0 : captures_->length(); } 532 int captures_started() { return captures_ == NULL ? 0 : captures_->length(); }
534 int position() { return next_pos_ - 1; } 533 int position() { return next_pos_ - 1; }
534 bool failed() { return failed_; }
535 535
536 static const uc32 kEndMarker = (1 << 21); 536 static const uc32 kEndMarker = (1 << 21);
537 private: 537 private:
538 uc32 current() { return current_; } 538 uc32 current() { return current_; }
539 bool has_more() { return has_more_; } 539 bool has_more() { return has_more_; }
540 bool has_next() { return next_pos_ < in()->length(); } 540 bool has_next() { return next_pos_ < in()->length(); }
541 uc32 Next(); 541 uc32 Next();
542 FlatStringReader* in() { return in_; } 542 FlatStringReader* in() { return in_; }
543 void ScanForCaptures(); 543 void ScanForCaptures();
544 bool CaptureAvailable(int index); 544 bool CaptureAvailable(int index);
545 uc32 current_; 545 uc32 current_;
546 bool has_more_; 546 bool has_more_;
547 bool multiline_; 547 bool multiline_;
548 int next_pos_; 548 int next_pos_;
549 FlatStringReader* in_; 549 FlatStringReader* in_;
550 Handle<String>* error_; 550 Handle<String>* error_;
551 bool has_character_escapes_; 551 bool has_character_escapes_;
552 ZoneList<RegExpCapture*>* captures_; 552 ZoneList<RegExpCapture*>* captures_;
553 bool is_scanned_for_captures_; 553 bool is_scanned_for_captures_;
554 // The capture count is only valid after we have scanned for captures. 554 // The capture count is only valid after we have scanned for captures.
555 int capture_count_; 555 int capture_count_;
556 bool failed_;
556 }; 557 };
557 558
558 559
559 // A temporary scope stores information during parsing, just like 560 // A temporary scope stores information during parsing, just like
560 // a plain scope. However, temporary scopes are not kept around 561 // a plain scope. However, temporary scopes are not kept around
561 // after parsing or referenced by syntax trees so they can be stack- 562 // after parsing or referenced by syntax trees so they can be stack-
562 // allocated and hence used by the pre-parser. 563 // allocated and hence used by the pre-parser.
563 class TemporaryScope BASE_EMBEDDED { 564 class TemporaryScope BASE_EMBEDDED {
564 public: 565 public:
565 explicit TemporaryScope(Parser* parser); 566 explicit TemporaryScope(Parser* parser);
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 // CAUTION: This macro appends extra statements after a call, 1021 // CAUTION: This macro appends extra statements after a call,
1021 // thus it must never be used where only a single statement 1022 // thus it must never be used where only a single statement
1022 // is correct (e.g. an if statement branch w/o braces)! 1023 // is correct (e.g. an if statement branch w/o braces)!
1023 1024
1024 #define CHECK_OK ok); \ 1025 #define CHECK_OK ok); \
1025 if (!*ok) return NULL; \ 1026 if (!*ok) return NULL; \
1026 ((void)0 1027 ((void)0
1027 #define DUMMY ) // to make indentation work 1028 #define DUMMY ) // to make indentation work
1028 #undef DUMMY 1029 #undef DUMMY
1029 1030
1031 #define CHECK_FAILED ); \
1032 if (failed_) return NULL; \
1033 ((void)0
Mads Ager (chromium) 2008/12/01 15:29:09 Maybe we should add a dummy parenthesis as above s
Christian Plesner Hansen 2008/12/01 15:52:55 Aah, so that's what DUMMY was for.
1034
1030 1035
1031 // ---------------------------------------------------------------------------- 1036 // ----------------------------------------------------------------------------
1032 // Implementation of Parser 1037 // Implementation of Parser
1033 1038
1034 Parser::Parser(Handle<Script> script, 1039 Parser::Parser(Handle<Script> script,
1035 bool allow_natives_syntax, 1040 bool allow_natives_syntax,
1036 v8::Extension* extension, 1041 v8::Extension* extension,
1037 bool is_pre_parsing, 1042 bool is_pre_parsing,
1038 ParserFactory* factory, 1043 ParserFactory* factory,
1039 ParserLog* log, 1044 ParserLog* log,
(...skipping 2452 matching lines...) Expand 10 before | Expand all | Expand 10 after
3492 bool multiline) 3497 bool multiline)
3493 : current_(kEndMarker), 3498 : current_(kEndMarker),
3494 has_more_(true), 3499 has_more_(true),
3495 multiline_(multiline), 3500 multiline_(multiline),
3496 next_pos_(0), 3501 next_pos_(0),
3497 in_(in), 3502 in_(in),
3498 error_(error), 3503 error_(error),
3499 has_character_escapes_(false), 3504 has_character_escapes_(false),
3500 captures_(NULL), 3505 captures_(NULL),
3501 is_scanned_for_captures_(false), 3506 is_scanned_for_captures_(false),
3502 capture_count_(0) { 3507 capture_count_(0),
3508 failed_(false) {
3503 Advance(1); 3509 Advance(1);
3504 } 3510 }
3505 3511
3506 3512
3507 uc32 RegExpParser::Next() { 3513 uc32 RegExpParser::Next() {
3508 if (has_next()) { 3514 if (has_next()) {
3509 return in()->Get(next_pos_); 3515 return in()->Get(next_pos_);
3510 } else { 3516 } else {
3511 return kEndMarker; 3517 return kEndMarker;
3512 } 3518 }
3513 } 3519 }
3514 3520
3515 3521
3516 void RegExpParser::Advance() { 3522 void RegExpParser::Advance() {
3517 if (next_pos_ < in()->length()) { 3523 if (next_pos_ < in()->length()) {
3518 current_ = in()->Get(next_pos_); 3524 StackLimitCheck check;
3519 next_pos_++; 3525 if (check.HasOverflowed()) {
3526 ReportError(CStrVector(Top::kStackOverflowMessage));
3527 } else if (Zone::excess_allocation()) {
3528 ReportError(CStrVector("Regular expression too large"));
3529 } else {
3530 current_ = in()->Get(next_pos_);
3531 next_pos_++;
3532 }
3520 } else { 3533 } else {
3521 current_ = kEndMarker; 3534 current_ = kEndMarker;
3522 has_more_ = false; 3535 has_more_ = false;
3523 } 3536 }
3524 } 3537 }
3525 3538
3526 3539
3527 void RegExpParser::Reset(int pos) { 3540 void RegExpParser::Reset(int pos) {
3528 next_pos_ = pos; 3541 next_pos_ = pos;
3529 Advance(); 3542 Advance();
3530 } 3543 }
3531 3544
3532 3545
3533 void RegExpParser::Advance(int dist) { 3546 void RegExpParser::Advance(int dist) {
3534 for (int i = 0; i < dist; i++) 3547 for (int i = 0; i < dist; i++)
3535 Advance(); 3548 Advance();
3536 } 3549 }
3537 3550
3538 3551
3539 // Reports whether the parsed string atoms contain any characters that were 3552 // Reports whether the parsed string atoms contain any characters that were
3540 // escaped in the original pattern. If not, all atoms are proper substrings 3553 // escaped in the original pattern. If not, all atoms are proper substrings
3541 // of the original pattern. 3554 // of the original pattern.
3542 bool RegExpParser::HasCharacterEscapes() { 3555 bool RegExpParser::HasCharacterEscapes() {
3543 return has_character_escapes_; 3556 return has_character_escapes_;
3544 } 3557 }
3545 3558
3546 RegExpTree* RegExpParser::ReportError(Vector<const char> message, bool* ok) { 3559 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
3547 *ok = false; 3560 failed_ = true;
3548 *error_ = Factory::NewStringFromAscii(message, NOT_TENURED); 3561 *error_ = Factory::NewStringFromAscii(message, NOT_TENURED);
3562 // Zip to the end to make sure the no more input is read.
3563 current_ = kEndMarker;
3564 next_pos_ = in()->length();
3549 return NULL; 3565 return NULL;
3550 } 3566 }
3551 3567
3552 3568
3553 // Pattern :: 3569 // Pattern ::
3554 // Disjunction 3570 // Disjunction
3555 RegExpTree* RegExpParser::ParsePattern(bool* ok) { 3571 RegExpTree* RegExpParser::ParsePattern() {
3556 RegExpTree* result = ParseDisjunction(CHECK_OK); 3572 RegExpTree* result = ParseDisjunction(CHECK_FAILED);
3557 if (has_more()) { 3573 if (has_more()) {
3558 ReportError(CStrVector("Unmatched ')'"), CHECK_OK); 3574 ReportError(CStrVector("Unmatched ')'") CHECK_FAILED);
3559 } 3575 }
3560 return result; 3576 return result;
3561 } 3577 }
3562 3578
3563 3579
3564 bool RegExpParser::CaptureAvailable(int index) { 3580 bool RegExpParser::CaptureAvailable(int index) {
3565 if (captures_ == NULL) return false; 3581 if (captures_ == NULL) return false;
3566 if (index >= captures_->length()) return false; 3582 if (index >= captures_->length()) return false;
3567 RegExpCapture* capture = captures_->at(index); 3583 RegExpCapture* capture = captures_->at(index);
3568 return capture != NULL && capture->available() == CAPTURE_AVAILABLE; 3584 return capture != NULL && capture->available() == CAPTURE_AVAILABLE;
3569 } 3585 }
3570 3586
3571 3587
3572 // Disjunction :: 3588 // Disjunction ::
3573 // Alternative 3589 // Alternative
3574 // Alternative | Disjunction 3590 // Alternative | Disjunction
3575 // Alternative :: 3591 // Alternative ::
3576 // [empty] 3592 // [empty]
3577 // Term Alternative 3593 // Term Alternative
3578 // Term :: 3594 // Term ::
3579 // Assertion 3595 // Assertion
3580 // Atom 3596 // Atom
3581 // Atom Quantifier 3597 // Atom Quantifier
3582 RegExpTree* RegExpParser::ParseDisjunction(bool* ok) { 3598 RegExpTree* RegExpParser::ParseDisjunction() {
3583 RegExpBuilder builder; 3599 RegExpBuilder builder;
3584 int capture_start_index = captures_started(); 3600 int capture_start_index = captures_started();
3585 while (true) { 3601 while (true) {
3586 switch (current()) { 3602 switch (current()) {
3587 case kEndMarker: 3603 case kEndMarker:
3588 case ')': 3604 case ')':
3589 return builder.ToRegExp(); 3605 return builder.ToRegExp();
3590 case '|': { 3606 case '|': {
3591 Advance(); 3607 Advance();
3592 builder.NewAlternative(); 3608 builder.NewAlternative();
3593 int capture_new_alt_start_index = captures_started(); 3609 int capture_new_alt_start_index = captures_started();
3594 for (int i = capture_start_index; i < capture_new_alt_start_index; i++) { 3610 for (int i = capture_start_index; i < capture_new_alt_start_index; i++) {
3595 RegExpCapture* capture = captures_->at(i); 3611 RegExpCapture* capture = captures_->at(i);
3596 if (capture->available() == CAPTURE_AVAILABLE) { 3612 if (capture->available() == CAPTURE_AVAILABLE) {
3597 capture->set_available(CAPTURE_UNREACHABLE); 3613 capture->set_available(CAPTURE_UNREACHABLE);
3598 } 3614 }
3599 } 3615 }
3600 capture_start_index = capture_new_alt_start_index; 3616 capture_start_index = capture_new_alt_start_index;
3601 continue; 3617 continue;
3602 } 3618 }
3603 case '*': 3619 case '*':
3604 case '+': 3620 case '+':
3605 case '?': 3621 case '?':
3606 ReportError(CStrVector("Nothing to repeat"), CHECK_OK); 3622 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
3607 case '^': { 3623 case '^': {
3608 Advance(); 3624 Advance();
3609 RegExpAssertion::Type type = 3625 RegExpAssertion::Type type =
3610 multiline_ ? RegExpAssertion::START_OF_LINE : 3626 multiline_ ? RegExpAssertion::START_OF_LINE :
3611 RegExpAssertion::START_OF_INPUT; 3627 RegExpAssertion::START_OF_INPUT;
3612 builder.AddAssertion(new RegExpAssertion(type)); 3628 builder.AddAssertion(new RegExpAssertion(type));
3613 continue; 3629 continue;
3614 } 3630 }
3615 case '$': { 3631 case '$': {
3616 Advance(); 3632 Advance();
3617 RegExpAssertion::Type type = 3633 RegExpAssertion::Type type =
3618 multiline_ ? RegExpAssertion::END_OF_LINE : 3634 multiline_ ? RegExpAssertion::END_OF_LINE :
3619 RegExpAssertion::END_OF_INPUT; 3635 RegExpAssertion::END_OF_INPUT;
3620 builder.AddAssertion(new RegExpAssertion(type)); 3636 builder.AddAssertion(new RegExpAssertion(type));
3621 continue; 3637 continue;
3622 } 3638 }
3623 case '.': { 3639 case '.': {
3624 Advance(); 3640 Advance();
3625 // everything except \x0a, \x0d, \u2028 and \u2029 3641 // everything except \x0a, \x0d, \u2028 and \u2029
3626 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2); 3642 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
3627 CharacterRange::AddClassEscape('.', ranges); 3643 CharacterRange::AddClassEscape('.', ranges);
3628 RegExpTree* atom = new RegExpCharacterClass(ranges, false); 3644 RegExpTree* atom = new RegExpCharacterClass(ranges, false);
3629 builder.AddAtom(atom); 3645 builder.AddAtom(atom);
3630 break; 3646 break;
3631 } 3647 }
3632 case '(': { 3648 case '(': {
3633 RegExpTree* atom = ParseGroup(CHECK_OK); 3649 RegExpTree* atom = ParseGroup(CHECK_FAILED);
3634 builder.AddAtom(atom); 3650 builder.AddAtom(atom);
3635 break; 3651 break;
3636 } 3652 }
3637 case '[': { 3653 case '[': {
3638 RegExpTree* atom = ParseCharacterClass(CHECK_OK); 3654 RegExpTree* atom = ParseCharacterClass(CHECK_FAILED);
3639 builder.AddAtom(atom); 3655 builder.AddAtom(atom);
3640 break; 3656 break;
3641 } 3657 }
3642 // Atom :: 3658 // Atom ::
3643 // \ AtomEscape 3659 // \ AtomEscape
3644 case '\\': 3660 case '\\':
3645 switch (Next()) { 3661 switch (Next()) {
3646 case kEndMarker: 3662 case kEndMarker:
3647 ReportError(CStrVector("\\ at end of pattern"), CHECK_OK); 3663 ReportError(CStrVector("\\ at end of pattern") CHECK_FAILED);
3648 case 'b': 3664 case 'b':
3649 Advance(2); 3665 Advance(2);
3650 builder.AddAssertion( 3666 builder.AddAssertion(
3651 new RegExpAssertion(RegExpAssertion::BOUNDARY)); 3667 new RegExpAssertion(RegExpAssertion::BOUNDARY));
3652 continue; 3668 continue;
3653 case 'B': 3669 case 'B':
3654 Advance(2); 3670 Advance(2);
3655 builder.AddAssertion( 3671 builder.AddAssertion(
3656 new RegExpAssertion(RegExpAssertion::NON_BOUNDARY)); 3672 new RegExpAssertion(RegExpAssertion::NON_BOUNDARY));
3657 continue; 3673 continue;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3715 case 't': 3731 case 't':
3716 Advance(2); 3732 Advance(2);
3717 builder.AddCharacter('\t'); 3733 builder.AddCharacter('\t');
3718 break; 3734 break;
3719 case 'v': 3735 case 'v':
3720 Advance(2); 3736 Advance(2);
3721 builder.AddCharacter('\v'); 3737 builder.AddCharacter('\v');
3722 break; 3738 break;
3723 case 'c': { 3739 case 'c': {
3724 Advance(2); 3740 Advance(2);
3725 uc32 control = ParseControlLetterEscape(ok); 3741 uc32 control = ParseControlLetterEscape();
3726 builder.AddCharacter(control); 3742 builder.AddCharacter(control);
3727 break; 3743 break;
3728 } 3744 }
3729 case 'x': { 3745 case 'x': {
3730 Advance(2); 3746 Advance(2);
3731 uc32 value; 3747 uc32 value;
3732 if (ParseHexEscape(2, &value)) { 3748 if (ParseHexEscape(2, &value)) {
3733 builder.AddCharacter(value); 3749 builder.AddCharacter(value);
3734 } else { 3750 } else {
3735 builder.AddCharacter('x'); 3751 builder.AddCharacter('x');
(...skipping 14 matching lines...) Expand all
3750 // Identity escape. 3766 // Identity escape.
3751 builder.AddCharacter(Next()); 3767 builder.AddCharacter(Next());
3752 Advance(2); 3768 Advance(2);
3753 break; 3769 break;
3754 } 3770 }
3755 has_character_escapes_ = true; 3771 has_character_escapes_ = true;
3756 break; 3772 break;
3757 case '{': { 3773 case '{': {
3758 int dummy; 3774 int dummy;
3759 if (ParseIntervalQuantifier(&dummy, &dummy)) { 3775 if (ParseIntervalQuantifier(&dummy, &dummy)) {
3760 ReportError(CStrVector("Nothing to repeat"), CHECK_OK); 3776 ReportError(CStrVector("Nothing to repeat") CHECK_FAILED);
3761 } 3777 }
3762 // fallthrough 3778 // fallthrough
3763 } 3779 }
3764 default: 3780 default:
3765 builder.AddCharacter(current()); 3781 builder.AddCharacter(current());
3766 Advance(); 3782 Advance();
3767 break; 3783 break;
3768 } // end switch(current()) 3784 } // end switch(current())
3769 3785
3770 has_read_atom: 3786 has_read_atom:
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
3967 } 3983 }
3968 *min_out = min; 3984 *min_out = min;
3969 *max_out = max; 3985 *max_out = max;
3970 return true; 3986 return true;
3971 } 3987 }
3972 3988
3973 3989
3974 // Upper and lower case letters differ by one bit. 3990 // Upper and lower case letters differ by one bit.
3975 STATIC_CHECK(('a' ^ 'A') == 0x20); 3991 STATIC_CHECK(('a' ^ 'A') == 0x20);
3976 3992
3977 uc32 RegExpParser::ParseControlLetterEscape(bool* ok) { 3993 uc32 RegExpParser::ParseControlLetterEscape() {
3978 if (!has_more()) { 3994 if (!has_more()) {
3979 ReportError(CStrVector("\\c at end of pattern"), ok); 3995 ReportError(CStrVector("\\c at end of pattern"));
3980 return '\0'; 3996 return '\0';
3981 } 3997 }
3982 uc32 letter = current() & ~(0x20); // Collapse upper and lower case letters. 3998 uc32 letter = current() & ~(0x20); // Collapse upper and lower case letters.
3983 if (letter < 'A' || 'Z' < letter) { 3999 if (letter < 'A' || 'Z' < letter) {
3984 // Non-spec error-correction: "\c" followed by non-control letter is 4000 // Non-spec error-correction: "\c" followed by non-control letter is
3985 // interpreted as an IdentityEscape of 'c'. 4001 // interpreted as an IdentityEscape of 'c'.
3986 return 'c'; 4002 return 'c';
3987 } 4003 }
3988 Advance(); 4004 Advance();
3989 return letter & 0x1f; // Remainder modulo 32, per specification. 4005 return letter & 0x1f; // Remainder modulo 32, per specification.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4023 Advance(); 4039 Advance();
4024 if (i == length - 1) { 4040 if (i == length - 1) {
4025 done = true; 4041 done = true;
4026 } 4042 }
4027 } 4043 }
4028 *value = val; 4044 *value = val;
4029 return true; 4045 return true;
4030 } 4046 }
4031 4047
4032 4048
4033 uc32 RegExpParser::ParseClassCharacterEscape(bool* ok) { 4049 uc32 RegExpParser::ParseClassCharacterEscape() {
4034 ASSERT(current() == '\\'); 4050 ASSERT(current() == '\\');
4035 ASSERT(has_next() && !IsSpecialClassEscape(Next())); 4051 ASSERT(has_next() && !IsSpecialClassEscape(Next()));
4036 Advance(); 4052 Advance();
4037 switch (current()) { 4053 switch (current()) {
4038 case 'b': 4054 case 'b':
4039 Advance(); 4055 Advance();
4040 return '\b'; 4056 return '\b';
4041 // ControlEscape :: one of 4057 // ControlEscape :: one of
4042 // f n r t v 4058 // f n r t v
4043 case 'f': 4059 case 'f':
4044 Advance(); 4060 Advance();
4045 return '\f'; 4061 return '\f';
4046 case 'n': 4062 case 'n':
4047 Advance(); 4063 Advance();
4048 return '\n'; 4064 return '\n';
4049 case 'r': 4065 case 'r':
4050 Advance(); 4066 Advance();
4051 return '\r'; 4067 return '\r';
4052 case 't': 4068 case 't':
4053 Advance(); 4069 Advance();
4054 return '\t'; 4070 return '\t';
4055 case 'v': 4071 case 'v':
4056 Advance(); 4072 Advance();
4057 return '\v'; 4073 return '\v';
4058 case 'c': 4074 case 'c':
4059 return ParseControlLetterEscape(ok); 4075 return ParseControlLetterEscape();
4060 case '0': case '1': case '2': case '3': case '4': case '5': 4076 case '0': case '1': case '2': case '3': case '4': case '5':
4061 case '6': case '7': 4077 case '6': case '7':
4062 // For compatibility, we interpret a decimal escape that isn't 4078 // For compatibility, we interpret a decimal escape that isn't
4063 // a back reference (and therefore either \0 or not valid according 4079 // a back reference (and therefore either \0 or not valid according
4064 // to the specification) as a 1..3 digit octal character code. 4080 // to the specification) as a 1..3 digit octal character code.
4065 return ParseOctalLiteral(); 4081 return ParseOctalLiteral();
4066 case 'x': { 4082 case 'x': {
4067 Advance(); 4083 Advance();
4068 uc32 value; 4084 uc32 value;
4069 if (ParseHexEscape(2, &value)) { 4085 if (ParseHexEscape(2, &value)) {
(...skipping 19 matching lines...) Expand all
4089 // by the ECMAScript specification. 4105 // by the ECMAScript specification.
4090 uc32 result = current(); 4106 uc32 result = current();
4091 Advance(); 4107 Advance();
4092 return result; 4108 return result;
4093 } 4109 }
4094 } 4110 }
4095 return 0; 4111 return 0;
4096 } 4112 }
4097 4113
4098 4114
4099 RegExpTree* RegExpParser::ParseGroup(bool* ok) { 4115 RegExpTree* RegExpParser::ParseGroup() {
4100 ASSERT_EQ(current(), '('); 4116 ASSERT_EQ(current(), '(');
4101 char type = '('; 4117 char type = '(';
4102 Advance(); 4118 Advance();
4103 if (current() == '?') { 4119 if (current() == '?') {
4104 switch (Next()) { 4120 switch (Next()) {
4105 case ':': case '=': case '!': 4121 case ':': case '=': case '!':
4106 type = Next(); 4122 type = Next();
4107 Advance(2); 4123 Advance(2);
4108 break; 4124 break;
4109 default: 4125 default:
4110 ReportError(CStrVector("Invalid group"), CHECK_OK); 4126 ReportError(CStrVector("Invalid group") CHECK_FAILED);
4111 break; 4127 break;
4112 } 4128 }
4113 } else { 4129 } else {
4114 if (captures_ == NULL) { 4130 if (captures_ == NULL) {
4115 captures_ = new ZoneList<RegExpCapture*>(2); 4131 captures_ = new ZoneList<RegExpCapture*>(2);
4116 } 4132 }
4117 captures_->Add(NULL); 4133 captures_->Add(NULL);
4118 } 4134 }
4119 int capture_index = captures_started(); 4135 int capture_index = captures_started();
4120 RegExpTree* body = ParseDisjunction(CHECK_OK); 4136 RegExpTree* body = ParseDisjunction(CHECK_FAILED);
4121 if (current() != ')') { 4137 if (current() != ')') {
4122 ReportError(CStrVector("Unterminated group"), CHECK_OK); 4138 ReportError(CStrVector("Unterminated group") CHECK_FAILED);
4123 } 4139 }
4124 Advance(); 4140 Advance();
4125 4141
4126 int end_capture_index = captures_started(); 4142 int end_capture_index = captures_started();
4127 if (type == '!') { 4143 if (type == '!') {
4128 // Captures inside a negative lookahead are never available outside it. 4144 // Captures inside a negative lookahead are never available outside it.
4129 for (int i = capture_index; i < end_capture_index; i++) { 4145 for (int i = capture_index; i < end_capture_index; i++) {
4130 RegExpCapture* capture = captures_->at(i); 4146 RegExpCapture* capture = captures_->at(i);
4131 ASSERT(capture != NULL); 4147 ASSERT(capture != NULL);
4132 capture->set_available(CAPTURE_PERMANENTLY_UNREACHABLE); 4148 capture->set_available(CAPTURE_PERMANENTLY_UNREACHABLE);
(...skipping 17 matching lines...) Expand all
4150 } else if (type == ':') { 4166 } else if (type == ':') {
4151 return body; 4167 return body;
4152 } else { 4168 } else {
4153 ASSERT(type == '=' || type == '!'); 4169 ASSERT(type == '=' || type == '!');
4154 bool is_positive = (type == '='); 4170 bool is_positive = (type == '=');
4155 return new RegExpLookahead(body, is_positive); 4171 return new RegExpLookahead(body, is_positive);
4156 } 4172 }
4157 } 4173 }
4158 4174
4159 4175
4160 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class, bool* ok) { 4176 CharacterRange RegExpParser::ParseClassAtom(uc16* char_class) {
4161 ASSERT_EQ(0, *char_class); 4177 ASSERT_EQ(0, *char_class);
4162 uc32 first = current(); 4178 uc32 first = current();
4163 if (first == '\\') { 4179 if (first == '\\') {
4164 switch (Next()) { 4180 switch (Next()) {
4165 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': { 4181 case 'w': case 'W': case 'd': case 'D': case 's': case 'S': {
4166 *char_class = Next(); 4182 *char_class = Next();
4167 Advance(2); 4183 Advance(2);
4168 return CharacterRange::Singleton(0); // Return dummy value. 4184 return CharacterRange::Singleton(0); // Return dummy value.
4169 } 4185 }
4170 default: 4186 default:
4171 uc32 c = ParseClassCharacterEscape(CHECK_OK); 4187 uc32 c = ParseClassCharacterEscape(CHECK_FAILED);
4172 return CharacterRange::Singleton(c); 4188 return CharacterRange::Singleton(c);
4173 } 4189 }
4174 } else { 4190 } else {
4175 Advance(); 4191 Advance();
4176 return CharacterRange::Singleton(first); 4192 return CharacterRange::Singleton(first);
4177 } 4193 }
4178 } 4194 }
4179 4195
4180 4196
4181 RegExpTree* RegExpParser::ParseCharacterClass(bool* ok) { 4197 RegExpTree* RegExpParser::ParseCharacterClass() {
4182 static const char* kUnterminated = "Unterminated character class"; 4198 static const char* kUnterminated = "Unterminated character class";
4183 static const char* kRangeOutOfOrder = "Range out of order in character class"; 4199 static const char* kRangeOutOfOrder = "Range out of order in character class";
4184 4200
4185 ASSERT_EQ(current(), '['); 4201 ASSERT_EQ(current(), '[');
4186 Advance(); 4202 Advance();
4187 bool is_negated = false; 4203 bool is_negated = false;
4188 if (current() == '^') { 4204 if (current() == '^') {
4189 is_negated = true; 4205 is_negated = true;
4190 Advance(); 4206 Advance();
4191 } 4207 }
4192 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2); 4208 ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
4193 while (has_more() && current() != ']') { 4209 while (has_more() && current() != ']') {
4194 uc16 char_class = 0; 4210 uc16 char_class = 0;
4195 CharacterRange first = ParseClassAtom(&char_class, CHECK_OK); 4211 CharacterRange first = ParseClassAtom(&char_class CHECK_FAILED);
4196 if (char_class) { 4212 if (char_class) {
4197 CharacterRange::AddClassEscape(char_class, ranges); 4213 CharacterRange::AddClassEscape(char_class, ranges);
4198 continue; 4214 continue;
4199 } 4215 }
4200 if (current() == '-') { 4216 if (current() == '-') {
4201 Advance(); 4217 Advance();
4202 if (current() == kEndMarker) { 4218 if (current() == kEndMarker) {
4203 // If we reach the end we break out of the loop and let the 4219 // If we reach the end we break out of the loop and let the
4204 // following code report an error. 4220 // following code report an error.
4205 break; 4221 break;
4206 } else if (current() == ']') { 4222 } else if (current() == ']') {
4207 ranges->Add(first); 4223 ranges->Add(first);
4208 ranges->Add(CharacterRange::Singleton('-')); 4224 ranges->Add(CharacterRange::Singleton('-'));
4209 break; 4225 break;
4210 } 4226 }
4211 CharacterRange next = ParseClassAtom(&char_class, CHECK_OK); 4227 CharacterRange next = ParseClassAtom(&char_class CHECK_FAILED);
4212 if (char_class) { 4228 if (char_class) {
4213 ranges->Add(first); 4229 ranges->Add(first);
4214 ranges->Add(CharacterRange::Singleton('-')); 4230 ranges->Add(CharacterRange::Singleton('-'));
4215 CharacterRange::AddClassEscape(char_class, ranges); 4231 CharacterRange::AddClassEscape(char_class, ranges);
4216 continue; 4232 continue;
4217 } 4233 }
4218 if (first.from() > next.to()) { 4234 if (first.from() > next.to()) {
4219 return ReportError(CStrVector(kRangeOutOfOrder), CHECK_OK); 4235 return ReportError(CStrVector(kRangeOutOfOrder) CHECK_FAILED);
4220 } 4236 }
4221 ranges->Add(CharacterRange::Range(first.from(), next.to())); 4237 ranges->Add(CharacterRange::Range(first.from(), next.to()));
4222 } else { 4238 } else {
4223 ranges->Add(first); 4239 ranges->Add(first);
4224 } 4240 }
4225 } 4241 }
4226 if (!has_more()) { 4242 if (!has_more()) {
4227 return ReportError(CStrVector(kUnterminated), CHECK_OK); 4243 return ReportError(CStrVector(kUnterminated) CHECK_FAILED);
4228 } 4244 }
4229 Advance(); 4245 Advance();
4230 if (ranges->length() == 0) { 4246 if (ranges->length() == 0) {
4231 ranges->Add(CharacterRange::Everything()); 4247 ranges->Add(CharacterRange::Everything());
4232 is_negated = !is_negated; 4248 is_negated = !is_negated;
4233 } 4249 }
4234 return new RegExpCharacterClass(ranges, is_negated); 4250 return new RegExpCharacterClass(ranges, is_negated);
4235 } 4251 }
4236 4252
4237 4253
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
4280 // the expected 50% too large. 4296 // the expected 50% too large.
4281 Vector<unsigned> store = parser.recorder()->store()->ToVector().Clone(); 4297 Vector<unsigned> store = parser.recorder()->store()->ToVector().Clone();
4282 return new ScriptDataImpl(store); 4298 return new ScriptDataImpl(store);
4283 } 4299 }
4284 4300
4285 4301
4286 bool ParseRegExp(FlatStringReader* input, 4302 bool ParseRegExp(FlatStringReader* input,
4287 bool multiline, 4303 bool multiline,
4288 RegExpParseResult* result) { 4304 RegExpParseResult* result) {
4289 ASSERT(result != NULL); 4305 ASSERT(result != NULL);
4306 // Make sure we have a stack guard.
4307 StackGuard guard;
4290 RegExpParser parser(input, &result->error, multiline); 4308 RegExpParser parser(input, &result->error, multiline);
4291 bool ok = true; 4309 result->tree = parser.ParsePattern();
4292 result->tree = parser.ParsePattern(&ok); 4310 if (parser.failed()) {
4293 if (!ok) {
4294 ASSERT(result->tree == NULL); 4311 ASSERT(result->tree == NULL);
4295 ASSERT(!result->error.is_null()); 4312 ASSERT(!result->error.is_null());
4296 } else { 4313 } else {
4297 ASSERT(result->tree != NULL); 4314 ASSERT(result->tree != NULL);
4298 ASSERT(result->error.is_null()); 4315 ASSERT(result->error.is_null());
4299 }
4300 if (ok) {
4301 result->has_character_escapes = parser.HasCharacterEscapes(); 4316 result->has_character_escapes = parser.HasCharacterEscapes();
4302 result->capture_count = parser.captures_started(); 4317 result->capture_count = parser.captures_started();
4303 } 4318 }
4304 return ok; 4319 return !parser.failed();
4305 } 4320 }
4306 4321
4307 4322
4308 FunctionLiteral* MakeAST(bool compile_in_global_context, 4323 FunctionLiteral* MakeAST(bool compile_in_global_context,
4309 Handle<Script> script, 4324 Handle<Script> script,
4310 v8::Extension* extension, 4325 v8::Extension* extension,
4311 ScriptDataImpl* pre_data) { 4326 ScriptDataImpl* pre_data) {
4312 bool allow_natives_syntax = 4327 bool allow_natives_syntax =
4313 always_allow_natives_syntax || 4328 always_allow_natives_syntax ||
4314 FLAG_allow_natives_syntax || 4329 FLAG_allow_natives_syntax ||
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4350 start_position, 4365 start_position,
4351 is_expression); 4366 is_expression);
4352 return result; 4367 return result;
4353 } 4368 }
4354 4369
4355 4370
4356 #undef NEW 4371 #undef NEW
4357 4372
4358 4373
4359 } } // namespace v8::internal 4374 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/top.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698