479 {
480
482 0,
nullptr, top_level_flags_,
Z);
483 RegExpParserState* stored_state = &initial_state;
484
485 RegExpBuilder*
builder = initial_state.builder();
486 while (true) {
487 switch (current()) {
489 if (stored_state->IsSubexpression()) {
490
493 }
494 ASSERT(INITIAL == stored_state->group_type());
495
497 case ')': {
498 if (!stored_state->IsSubexpression()) {
501 }
502 ASSERT(INITIAL != stored_state->group_type());
503
505
506
507 RegExpTree* body =
builder->ToRegExp();
508
510
511 intptr_t capture_index = stored_state->capture_index();
512 SubexpressionType group_type = stored_state->group_type();
513
514
515 if (group_type == CAPTURE) {
516 if (stored_state->IsNamedCapture()) {
517 CreateNamedCaptureAtIndex(stored_state->capture_name(),
518 capture_index);
519 }
520 RegExpCapture* capture = GetCapture(capture_index);
521 capture->set_body(body);
522 body = capture;
523 } else if (group_type != GROUPING) {
524 ASSERT(group_type == POSITIVE_LOOKAROUND ||
525 group_type == NEGATIVE_LOOKAROUND);
526 bool is_positive = (group_type == POSITIVE_LOOKAROUND);
527 body =
new (
Z) RegExpLookaround(
528 body, is_positive, end_capture_index - capture_index,
529 capture_index, stored_state->lookaround_type());
530 }
531
532
533 stored_state = stored_state->previous_state();
534 builder = stored_state->builder();
535
537
538
539 break;
540 }
541 case '|': {
544 continue;
545 }
546 case '*':
547 case '+':
548 case '?':
551 case '^': {
553 if (
builder->is_multi_line()) {
554 builder->AddAssertion(
new (
Z) RegExpAssertion(
556 } else {
557 builder->AddAssertion(
new (
Z) RegExpAssertion(
560 }
561 continue;
562 }
563 case '$': {
569 new (
Z) RegExpAssertion(assertion_type,
builder->flags()));
570 continue;
571 }
572 case '.': {
574 auto ranges =
new (
Z) ZoneGrowableArray<CharacterRange>(2);
576
578 '*', ranges,
579 false);
580 } else {
581
583 '.', ranges,
584 false);
585 }
586 RegExpCharacterClass*
cc =
587 new (
Z) RegExpCharacterClass(ranges,
builder->flags());
589 break;
590 }
591 case '(': {
592 stored_state = ParseOpenParenthesis(stored_state);
593 builder = stored_state->builder();
594 continue;
595 }
596 case '[': {
598 builder->AddCharacterClass(atom->AsCharacterClass());
599 break;
600 }
601
602
603 case '\\':
604 switch (Next()) {
608 case 'b':
610 builder->AddAssertion(
new (
Z) RegExpAssertion(
612 continue;
613 case 'B':
615 builder->AddAssertion(
new (
Z) RegExpAssertion(
617 continue;
618
619
620
621
622
623 case 'd':
624 case 'D':
625 case 's':
626 case 'S':
627 case 'w':
628 case 'W': {
629 uint32_t c = Next();
631 auto ranges =
new (
Z) ZoneGrowableArray<CharacterRange>(2);
634 RegExpCharacterClass*
cc =
635 new (
Z) RegExpCharacterClass(ranges,
builder->flags());
637 break;
638 }
639 case 'p':
640 case 'P': {
643
645 auto name_1 =
new (
Z) ZoneGrowableArray<char>();
646 auto name_2 =
new (
Z) ZoneGrowableArray<char>();
647 auto ranges =
new (
Z) ZoneGrowableArray<CharacterRange>(2);
650 RegExpCharacterClass*
cc =
651 new (
Z) RegExpCharacterClass(ranges,
builder->flags());
653 break;
654 }
655 }
658 } else {
660 }
661 break;
662 }
663 case '1':
664 case '2':
665 case '3':
666 case '4':
667 case '5':
668 case '6':
669 case '7':
670 case '8':
671 case '9': {
672 intptr_t index = 0;
674 if (stored_state->IsInsideCaptureGroup(index)) {
675
676
677
678
679
681 } else {
682 RegExpCapture* capture = GetCapture(index);
683 RegExpTree* atom =
684 new (
Z) RegExpBackReference(capture,
builder->flags());
686 }
687 break;
688 }
689
690
694 }
695 uint32_t first_digit = Next();
696 if (first_digit == '8' || first_digit == '9') {
697 builder->AddCharacter(first_digit);
699 break;
700 }
701 }
703 case '0': {
705 if (
is_unicode() && Next() >=
'0' && Next() <=
'9') {
706
709 }
712 break;
713 }
714
715
716 case 'f':
719 break;
720 case 'n':
723 break;
724 case 'r':
727 break;
728 case 't':
731 break;
732 case 'v':
735 break;
736 case 'c': {
738 uint32_t controlLetter = Next();
739
740
741 uint32_t letter = controlLetter & ~('a' ^ 'A');
742 if (letter < 'A' || 'Z' < letter) {
743
744
745
746
748
751 }
753 } else {
755 builder->AddCharacter(controlLetter & 0x1f);
756 }
757 break;
758 }
759 case 'x': {
766 } else {
767
770 }
771 break;
772 }
773 case 'u': {
780 } else {
781
784 }
785 break;
786 }
787 case 'k':
788
789
790
791
792
795 ParseNamedBackReference(
builder, stored_state);
796 break;
797 }
799 default:
801
802
803
805 builder->AddCharacter(current());
807 } else {
810 }
811 break;
812 }
813 break;
814 case '{': {
815 intptr_t dummy;
819 }
820 }
822 case '}':
823 case ']':
827 }
829 default:
830 builder->AddUnicodeCharacter(current());
832 break;
833 }
834
837 switch (current()) {
838
839
840
841
842
843 case '*':
847 break;
848 case '+':
852 break;
853 case '?':
857 break;
858 case '{':
861 ReportError(
"numbers out of order in {} quantifier.");
863 }
864 break;
865 } else {
866 continue;
867 }
868 default:
869 continue;
870 }
872 if (current() == '?') {
876
879 }
880 if (!
builder->AddQuantifierToAtom(
min,
max, quantifier_type)) {
883 }
884 }
885}
void set_contains_anchor()
bool ParseIntervalQuantifier(intptr_t *min_out, intptr_t *max_out)
bool ParseBackReferenceIndex(intptr_t *index_out)
RegExpTree * ParseCharacterClass(const RegExpBuilder *builder)
static constexpr intptr_t kInfinity
static float max(float r, float g, float b)
static float min(float r, float g, float b)
static constexpr bool FLAG_regexp_possessive_quantifier