/// ○ 2nd capture group.<br/>
/// ○ Match a character in the set [\-\w] atomically at least once.<br/>
/// ○ 3rd capture group.<br/>
- /// ○ Loop greedily at least once.<br/>
+ /// ○ Loop greedily and atomically at least once.<br/>
/// ○ 4th capture group.<br/>
/// ○ Match '.'.<br/>
/// ○ Loop greedily at least 2 and at most 3 times.<br/>
int loop_iteration1 = 0;
int stackpos = 0;
int startingStackpos = 0;
+ int startingStackpos1 = 0;
ReadOnlySpan<char> slice = inputSpan.Slice(pos);
// Match if at the beginning of the string.
}
// 3rd capture group.
- //{
+ {
capture_starting_pos2 = pos;
- // Loop greedily at least once.
- //{
- loop_iteration = 0;
+ // Atomic group.
+ {
+ int atomic_stackpos = stackpos;
- LoopBody:
- Utilities.StackPush(ref base.runstack!, ref stackpos, base.Crawlpos(), pos);
-
- loop_iteration++;
-
- // 4th capture group.
+ // Loop greedily and atomically at least once.
//{
- int capture_starting_pos3 = pos;
+ startingStackpos = stackpos;
+ loop_iteration = 0;
- // Match '.'.
- if (slice.IsEmpty || slice[0] != '.')
- {
- goto LoopIterationNoMatch;
- }
+ LoopBody:
+ Utilities.StackPush(ref base.runstack!, ref stackpos, base.Crawlpos(), pos);
- // Loop greedily at least 2 and at most 3 times.
+ loop_iteration++;
+
+ // 4th capture group.
//{
- pos++;
- slice = inputSpan.Slice(pos);
- startingStackpos = stackpos;
- loop_iteration1 = 0;
+ int capture_starting_pos3 = pos;
- LoopBody1:
- Utilities.StackPush(ref base.runstack!, ref stackpos, base.Crawlpos(), pos);
-
- loop_iteration1++;
-
- // 5th capture group.
+ // Match '.'.
+ if (slice.IsEmpty || slice[0] != '.')
{
- int capture_starting_pos4 = pos;
-
- // Match a word character.
- if (slice.IsEmpty || !Utilities.IsWordChar(slice[0]))
- {
- goto LoopIterationNoMatch1;
- }
-
+ goto LoopIterationNoMatch;
+ }
+
+ // Loop greedily at least 2 and at most 3 times.
+ //{
pos++;
slice = inputSpan.Slice(pos);
- base.Capture(5, capture_starting_pos4, pos);
- }
-
-
- // The loop has an upper bound of 3. Continue iterating greedily if it hasn't yet been reached.
- if (loop_iteration1 < 3)
- {
- goto LoopBody1;
- }
- goto LoopEnd1;
-
- // The loop iteration failed. Put state back to the way it was before the iteration.
- LoopIterationNoMatch1:
- if (--loop_iteration1 < 0)
- {
- // Unable to match the remainder of the expression after exhausting the loop.
- goto LoopIterationNoMatch;
- }
- pos = base.runstack![--stackpos];
- UncaptureUntil(base.runstack![--stackpos]);
- slice = inputSpan.Slice(pos);
- if (loop_iteration1 < 2)
- {
- // All possible iterations have matched, but it's below the required minimum of 2. Fail the loop.
- if (loop_iteration1 != 0)
+ startingStackpos1 = stackpos;
+ loop_iteration1 = 0;
+
+ LoopBody1:
+ Utilities.StackPush(ref base.runstack!, ref stackpos, base.Crawlpos(), pos);
+
+ loop_iteration1++;
+
+ // 5th capture group.
{
- // Ensure any stale backtracking state is removed.
- stackpos = startingStackpos;
+ int capture_starting_pos4 = pos;
+
+ // Match a word character.
+ if (slice.IsEmpty || !Utilities.IsWordChar(slice[0]))
+ {
+ goto LoopIterationNoMatch1;
+ }
+
+ pos++;
+ slice = inputSpan.Slice(pos);
+ base.Capture(5, capture_starting_pos4, pos);
}
- goto LoopIterationNoMatch;
- }
+
+
+ // The loop has an upper bound of 3. Continue iterating greedily if it hasn't yet been reached.
+ if (loop_iteration1 < 3)
+ {
+ goto LoopBody1;
+ }
+ goto LoopEnd1;
+
+ // The loop iteration failed. Put state back to the way it was before the iteration.
+ LoopIterationNoMatch1:
+ if (--loop_iteration1 < 0)
+ {
+ // Unable to match the remainder of the expression after exhausting the loop.
+ goto LoopIterationNoMatch;
+ }
+ pos = base.runstack![--stackpos];
+ UncaptureUntil(base.runstack![--stackpos]);
+ slice = inputSpan.Slice(pos);
+ if (loop_iteration1 < 2)
+ {
+ // All possible iterations have matched, but it's below the required minimum of 2. Fail the loop.
+ if (loop_iteration1 != 0)
+ {
+ // Ensure any stale backtracking state is removed.
+ stackpos = startingStackpos1;
+ }
+ goto LoopIterationNoMatch;
+ }
+
+ LoopEnd1:
+
+ Utilities.StackPush(ref base.runstack!, ref stackpos, startingStackpos1, loop_iteration1);
+ goto LoopSkipBacktrack;
+
+ LoopBacktrack:
+ Utilities.StackPop(base.runstack!, ref stackpos, out loop_iteration1, out startingStackpos1);
+ if (Utilities.s_hasTimeout)
+ {
+ base.CheckTimeout();
+ }
+
+ goto LoopIterationNoMatch1;
+
+ LoopSkipBacktrack:;
+ //}
- LoopEnd1:
+ base.Capture(4, capture_starting_pos3, pos);
- Utilities.StackPush(ref base.runstack!, ref stackpos, startingStackpos, loop_iteration1);
- goto LoopSkipBacktrack;
+ Utilities.StackPush(ref base.runstack!, ref stackpos, capture_starting_pos3);
+ goto CaptureSkipBacktrack;
- LoopBacktrack:
- Utilities.StackPop(base.runstack!, ref stackpos, out loop_iteration1, out startingStackpos);
- if (Utilities.s_hasTimeout)
- {
- base.CheckTimeout();
- }
+ CaptureBacktrack:
+ capture_starting_pos3 = base.runstack![--stackpos];
+ goto LoopBacktrack;
- goto LoopIterationNoMatch1;
-
- LoopSkipBacktrack:;
+ CaptureSkipBacktrack:;
//}
- base.Capture(4, capture_starting_pos3, pos);
- Utilities.StackPush(ref base.runstack!, ref stackpos, capture_starting_pos3);
- goto CaptureSkipBacktrack;
+ // The loop has no upper bound. Continue iterating greedily.
+ goto LoopBody;
- CaptureBacktrack:
- capture_starting_pos3 = base.runstack![--stackpos];
- goto LoopBacktrack;
+ // The loop iteration failed. Put state back to the way it was before the iteration.
+ LoopIterationNoMatch:
+ if (--loop_iteration < 0)
+ {
+ // Unable to match the remainder of the expression after exhausting the loop.
+ UncaptureUntil(0);
+ return false; // The input didn't match.
+ }
+ pos = base.runstack![--stackpos];
+ UncaptureUntil(base.runstack![--stackpos]);
+ slice = inputSpan.Slice(pos);
+ if (loop_iteration == 0)
+ {
+ // No iterations have been matched to backtrack into. Fail the loop.
+ UncaptureUntil(0);
+ return false; // The input didn't match.
+ }
- CaptureSkipBacktrack:;
+ LoopEnd:
+ stackpos = startingStackpos; // Ensure any remaining backtracking state is removed.
//}
-
- // The loop has no upper bound. Continue iterating greedily.
- goto LoopBody;
-
- // The loop iteration failed. Put state back to the way it was before the iteration.
- LoopIterationNoMatch:
- if (--loop_iteration < 0)
- {
- // Unable to match the remainder of the expression after exhausting the loop.
- UncaptureUntil(0);
- return false; // The input didn't match.
- }
- pos = base.runstack![--stackpos];
- UncaptureUntil(base.runstack![--stackpos]);
- slice = inputSpan.Slice(pos);
- if (loop_iteration == 0)
- {
- // No iterations have been matched to backtrack into. Fail the loop.
- UncaptureUntil(0);
- return false; // The input didn't match.
- }
-
- goto LoopEnd;
-
- LoopBacktrack1:
- if (Utilities.s_hasTimeout)
- {
- base.CheckTimeout();
- }
-
- if (loop_iteration == 0)
- {
- // No iterations of the loop remain to backtrack into. Fail the loop.
- UncaptureUntil(0);
- return false; // The input didn't match.
- }
- goto CaptureBacktrack;
- LoopEnd:;
- //}
+ stackpos = atomic_stackpos;
+ }
base.Capture(3, capture_starting_pos2, pos);
-
- goto CaptureSkipBacktrack1;
-
- CaptureBacktrack1:
- goto LoopBacktrack1;
-
- CaptureSkipBacktrack1:;
- //}
+ }
// Match if at the end of the string or if before an ending newline.
if (pos < inputSpan.Length - 1 || ((uint)pos < (uint)inputSpan.Length && inputSpan[pos] != '\n'))
{
- goto CaptureBacktrack1;
+ UncaptureUntil(0);
+ return false; // The input didn't match.
}
// The input matched.
Job completed in 19 minutes 13 seconds (remote runner delay: 1 minute 21 seconds).
dotnet/runtime#117943
Using arguments:
regexdiff60 out of 18857 patterns have generated source code changes.
Examples of GeneratedRegex source diffs
"^-+ *BEGIN (?<keyName>\\w+( \\w+)*) PRIVATE ..." (1964 uses)
"^([\\w\\.\\-]+)@([\\w\\-]+)((\\.(\\w){2,3})+)$" (550 uses)
"^-+ *BEGIN (?<keyName>\\w+( \\w+)*) PRIVATE ..." (524 uses)
"(<br>)+$" (119 uses)
"\\s*(<\\s*A\\s*>)+\\s*(<\\s*/\\s*A\\s*>)+\\s*" (118 uses)
For more diff examples, see https://gist.github.com/MihuBot/df46ebc7056909eecf97b280d9aade04
For a list of JIT diff regressions, see Regressions.md
For a list of JIT diff improvements, see Improvements.md
Sample source code for further analysis
Artifacts: