Преглед изворни кода

LibRegex: Don't treat ForkReplace* as new forks

Ali Mohammad Pur пре 2 година
родитељ
комит
00326a63ed
2 измењених фајлова са 15 додато и 4 уклоњено
  1. 6 0
      Tests/LibRegex/Regex.cpp
  2. 9 4
      Userland/Libraries/LibRegex/RegexByteCode.cpp

+ 6 - 0
Tests/LibRegex/Regex.cpp

@@ -1067,6 +1067,12 @@ TEST_CASE(negative_lookahead)
         EXPECT_EQ(re.match(":1"sv).success, false);
         EXPECT_EQ(re.match(":foobar"sv).success, true);
     }
+    {
+        // Correctly count forks with nested groups and optimised loops
+        Regex<ECMA262> re("^((?:[^\\n]|\\n(?! *\\n))+)(?:\\n *)+\\n");
+        EXPECT_EQ(re.match("foo\n\n"sv).success, true);
+        EXPECT_EQ(re.match("foo\n"sv).success, false);
+    }
 }
 
 TEST_CASE(single_match_flag)

+ 9 - 4
Userland/Libraries/LibRegex/RegexByteCode.cpp

@@ -267,7 +267,6 @@ ALWAYS_INLINE ExecutionResult OpCode_ForkReplaceStay::execute(MatchInput const&
 {
     state.fork_at_position = state.instruction_position + size() + offset();
     input.fork_to_replace = state.instruction_position;
-    state.forks_since_last_save++;
     return ExecutionResult::Fork_PrioLow;
 }
 
@@ -384,8 +383,10 @@ ALWAYS_INLINE ExecutionResult OpCode_SaveRightCaptureGroup::execute(MatchInput c
 {
     auto& match = state.capture_group_matches.at(input.match_index).at(id());
     auto start_position = match.left_column;
-    if (state.string_position < start_position)
+    if (state.string_position < start_position) {
+        dbgln("Right capture group {} is before left capture group {}!", state.string_position, start_position);
         return ExecutionResult::Failed_ExecuteLowPrioForks;
+    }
 
     auto length = state.string_position - start_position;
 
@@ -1071,11 +1072,15 @@ ALWAYS_INLINE ExecutionResult OpCode_JumpNonEmpty::execute(MatchInput const& inp
 
         state.fork_at_position = state.instruction_position + size() + offset();
 
-        if (form == OpCodeId::ForkJump)
+        if (form == OpCodeId::ForkJump) {
+            state.forks_since_last_save++;
             return ExecutionResult::Fork_PrioHigh;
+        }
 
-        if (form == OpCodeId::ForkStay)
+        if (form == OpCodeId::ForkStay) {
+            state.forks_since_last_save++;
             return ExecutionResult::Fork_PrioLow;
+        }
 
         if (form == OpCodeId::ForkReplaceStay) {
             input.fork_to_replace = state.instruction_position;