// #nullable enable #pragma warning disable namespace StgSharp { partial class TestRegexAnalyse { /// /// Pattern:
/// a*.[abc]*(abcd|a(bc)c)+(?<name>abc)
/// Explanation:
/// /// ○ Match 'a' greedily any number of times.
/// ○ Match any character other than '\n'.
/// ○ Match a character in the set [a-c] greedily any number of times.
/// ○ Loop greedily at least once.
/// ○ 1st capture group.
/// ○ Match 'a'.
/// ○ Match with 2 alternative expressions.
/// ○ Match the string "bcd".
/// ○ Match a sequence of expressions.
/// ○ 2nd capture group.
/// ○ Match the string "bc".
/// ○ Match 'c'.
/// ○ "name" capture group.
/// ○ Match the string "abc".
///
///
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "10.0.14.27113")] internal static partial global::System.Text.RegularExpressions.Regex GetRegex() => global::System.Text.RegularExpressions.Generated.GetRegex_0.Instance; } } namespace System.Text.RegularExpressions.Generated { using System; using System.Buffers; using System.CodeDom.Compiler; using System.Collections; using System.ComponentModel; using System.Globalization; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Threading; /// Custom -derived type for the GetRegex method. [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "10.0.14.27113")] file sealed class GetRegex_0 : Regex { /// Cached, thread-safe singleton instance. internal static readonly GetRegex_0 Instance = new(); /// Initializes the instance. private GetRegex_0() { base.pattern = "a*.[abc]*(abcd|a(bc)c)+(?abc)"; base.roptions = RegexOptions.None; ValidateMatchTimeout(Utilities.s_defaultTimeout); base.internalMatchTimeout = Utilities.s_defaultTimeout; base.factory = new RunnerFactory(); base.CapNames = new Hashtable { { "0", 0 } , { "1", 1 } , { "2", 2 } , { "name", 3 } }; base.capslist = new string[] {"0", "1", "2", "name" }; base.capsize = 4; } /// Provides a factory for creating instances to be used by methods on . private sealed class RunnerFactory : RegexRunnerFactory { /// Creates an instance of a used by methods on . protected override RegexRunner CreateInstance() => new Runner(); /// Provides the runner that contains the custom logic implementing the specified regular expression. private sealed class Runner : RegexRunner { /// Scan the starting from base.runtextstart for the next match. /// The text being scanned by the regular expression. protected override void Scan(ReadOnlySpan inputSpan) { // Search until we can't find a valid starting position, we find a match, or we reach the end of the input. while (TryFindNextPossibleStartingPosition(inputSpan) && !TryMatchAtCurrentPosition(inputSpan) && base.runtextpos != inputSpan.Length) { base.runtextpos++; if (Utilities.s_hasTimeout) { base.CheckTimeout(); } } } /// Search starting from base.runtextpos for the next location a match could possibly start. /// The text being scanned by the regular expression. /// true if a possible match was found; false if no more matches are possible. private bool TryFindNextPossibleStartingPosition(ReadOnlySpan inputSpan) { int pos = base.runtextpos; // Any possible match is at least 8 characters. if (pos <= inputSpan.Length - 8) { // The pattern begins with a character in the set [^\n]. // Find the next occurrence. If it can't be found, there's no match. ReadOnlySpan span = inputSpan.Slice(pos); for (int i = 0; i < span.Length; i++) { if ((span[i] != '\n')) { base.runtextpos = pos + i; return true; } } } // No match found. base.runtextpos = inputSpan.Length; return false; } /// Determine whether at base.runtextpos is a match for the regular expression. /// The text being scanned by the regular expression. /// true if the regular expression matches at the current position; otherwise, false. private bool TryMatchAtCurrentPosition(ReadOnlySpan inputSpan) { int pos = base.runtextpos; int matchStart = pos; int capture_starting_pos2 = 0; int charloop_capture_pos = 0; int charloop_capture_pos1 = 0; int charloop_starting_pos = 0, charloop_ending_pos = 0; int charloop_starting_pos1 = 0, charloop_ending_pos1 = 0; int loop_iteration = 0; int stackpos = 0; ReadOnlySpan slice = inputSpan.Slice(pos); // Match 'a' greedily any number of times. //{ charloop_starting_pos = pos; int iteration = slice.IndexOfAnyExcept('a'); if (iteration < 0) { iteration = slice.Length; } slice = slice.Slice(iteration); pos += iteration; charloop_ending_pos = pos; goto CharLoopEnd; CharLoopBacktrack: UncaptureUntil(charloop_capture_pos); if (Utilities.s_hasTimeout) { base.CheckTimeout(); } if (charloop_starting_pos >= charloop_ending_pos || (charloop_ending_pos = inputSpan.Slice(charloop_starting_pos, charloop_ending_pos - charloop_starting_pos).LastIndexOfAnyExcept('\n')) < 0) { UncaptureUntil(0); return false; // The input didn't match. } charloop_ending_pos += charloop_starting_pos; pos = charloop_ending_pos; slice = inputSpan.Slice(pos); CharLoopEnd: charloop_capture_pos = base.Crawlpos(); //} // Advance the next matching position. if (base.runtextpos < pos) { base.runtextpos = pos; } // Match any character other than '\n'. if (slice.IsEmpty || slice[0] == '\n') { goto CharLoopBacktrack; } // Match a character in the set [a-c] greedily any number of times. //{ pos++; slice = inputSpan.Slice(pos); charloop_starting_pos1 = pos; int iteration1 = slice.IndexOfAnyExceptInRange('a', 'c'); if (iteration1 < 0) { iteration1 = slice.Length; } slice = slice.Slice(iteration1); pos += iteration1; charloop_ending_pos1 = pos; goto CharLoopEnd1; CharLoopBacktrack1: UncaptureUntil(charloop_capture_pos1); if (Utilities.s_hasTimeout) { base.CheckTimeout(); } if (charloop_starting_pos1 >= charloop_ending_pos1 || (charloop_ending_pos1 = inputSpan.Slice(charloop_starting_pos1, charloop_ending_pos1 - charloop_starting_pos1).LastIndexOf('a')) < 0) { goto CharLoopBacktrack; } charloop_ending_pos1 += charloop_starting_pos1; pos = charloop_ending_pos1; slice = inputSpan.Slice(pos); CharLoopEnd1: charloop_capture_pos1 = base.Crawlpos(); //} // Loop greedily at least once. //{ loop_iteration = 0; LoopBody: Utilities.StackPush(ref base.runstack!, ref stackpos, base.Crawlpos(), pos); loop_iteration++; // 1st capture group. //{ int capture_starting_pos = pos; // Match 'a'. if (slice.IsEmpty || slice[0] != 'a') { goto LoopIterationNoMatch; } // Match with 2 alternative expressions. //{ int alternation_starting_pos = pos; int alternation_starting_capturepos = base.Crawlpos(); // Branch 0 //{ // Match the string "bcd". if (!slice.Slice(1).StartsWith("bcd")) { goto AlternationBranch; } Utilities.StackPush(ref base.runstack!, ref stackpos, 0, alternation_starting_pos, alternation_starting_capturepos); pos += 4; slice = inputSpan.Slice(pos); goto AlternationMatch; AlternationBranch: pos = alternation_starting_pos; slice = inputSpan.Slice(pos); UncaptureUntil(alternation_starting_capturepos); //} // Branch 1 //{ // 2nd capture group. { pos++; slice = inputSpan.Slice(pos); int capture_starting_pos1 = pos; // Match the string "bc". if (!slice.StartsWith("bc")) { goto LoopIterationNoMatch; } pos += 2; slice = inputSpan.Slice(pos); base.Capture(2, capture_starting_pos1, pos); } // Match 'c'. if (slice.IsEmpty || slice[0] != 'c') { goto LoopIterationNoMatch; } Utilities.StackPush(ref base.runstack!, ref stackpos, 1, alternation_starting_pos, alternation_starting_capturepos); pos++; slice = inputSpan.Slice(pos); goto AlternationMatch; //} AlternationBacktrack: if (Utilities.s_hasTimeout) { base.CheckTimeout(); } Utilities.StackPop(base.runstack!, ref stackpos, out alternation_starting_capturepos, out alternation_starting_pos); switch (base.runstack![--stackpos]) { case 0: goto AlternationBranch; case 1: goto LoopIterationNoMatch; } AlternationMatch:; //} base.Capture(1, capture_starting_pos, pos); Utilities.StackPush(ref base.runstack!, ref stackpos, capture_starting_pos); goto CaptureSkipBacktrack; CaptureBacktrack: capture_starting_pos = base.runstack![--stackpos]; goto AlternationBacktrack; CaptureSkipBacktrack:; //} // 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. goto CharLoopBacktrack1; } 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. goto CharLoopBacktrack1; } goto LoopEnd; LoopBacktrack: if (Utilities.s_hasTimeout) { base.CheckTimeout(); } if (loop_iteration == 0) { // No iterations of the loop remain to backtrack into. Fail the loop. goto CharLoopBacktrack1; } goto CaptureBacktrack; LoopEnd:; //} // "name" capture group. { capture_starting_pos2 = pos; // Match the string "abc". if (!slice.StartsWith("abc")) { goto LoopBacktrack; } pos += 3; slice = inputSpan.Slice(pos); base.Capture(3, capture_starting_pos2, pos); } // The input matched. base.runtextpos = pos; base.Capture(0, matchStart, pos); return true; // Undo captures until it reaches the specified capture position. [MethodImpl(MethodImplOptions.AggressiveInlining)] void UncaptureUntil(int capturePosition) { while (base.Crawlpos() > capturePosition) { base.Uncapture(); } } } } } } /// Helper methods used by generated -derived implementations. [GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "10.0.14.27113")] file static class Utilities { /// Default timeout value set in , or if none was set. internal static readonly TimeSpan s_defaultTimeout = AppContext.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") is TimeSpan timeout ? timeout : Regex.InfiniteMatchTimeout; /// Whether is non-infinite. internal static readonly bool s_hasTimeout = s_defaultTimeout != Regex.InfiniteMatchTimeout; /// Pops 2 values from the backtracking stack. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void StackPop(int[] stack, ref int pos, out int arg0, out int arg1) { arg0 = stack[--pos]; arg1 = stack[--pos]; } /// Pushes 1 value onto the backtracking stack. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void StackPush(ref int[] stack, ref int pos, int arg0) { // If there's space available for the value, store it. int[] s = stack; int p = pos; if ((uint)p < (uint)s.Length) { s[p] = arg0; pos++; return; } // Otherwise, resize the stack to make room and try again. WithResize(ref stack, ref pos, arg0); // Resize the backtracking stack array and push 1 value onto the stack. [MethodImpl(MethodImplOptions.NoInlining)] static void WithResize(ref int[] stack, ref int pos, int arg0) { Array.Resize(ref stack, (pos + 0) * 2); StackPush(ref stack, ref pos, arg0); } } /// Pushes 2 values onto the backtracking stack. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void StackPush(ref int[] stack, ref int pos, int arg0, int arg1) { // If there's space available for all 2 values, store them. int[] s = stack; int p = pos; if ((uint)(p + 1) < (uint)s.Length) { s[p] = arg0; s[p + 1] = arg1; pos += 2; return; } // Otherwise, resize the stack to make room and try again. WithResize(ref stack, ref pos, arg0, arg1); // Resize the backtracking stack array and push 2 values onto the stack. [MethodImpl(MethodImplOptions.NoInlining)] static void WithResize(ref int[] stack, ref int pos, int arg0, int arg1) { Array.Resize(ref stack, (pos + 1) * 2); StackPush(ref stack, ref pos, arg0, arg1); } } /// Pushes 3 values onto the backtracking stack. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void StackPush(ref int[] stack, ref int pos, int arg0, int arg1, int arg2) { // If there's space available for all 3 values, store them. int[] s = stack; int p = pos; if ((uint)(p + 2) < (uint)s.Length) { s[p] = arg0; s[p + 1] = arg1; s[p + 2] = arg2; pos += 3; return; } // Otherwise, resize the stack to make room and try again. WithResize(ref stack, ref pos, arg0, arg1, arg2); // Resize the backtracking stack array and push 3 values onto the stack. [MethodImpl(MethodImplOptions.NoInlining)] static void WithResize(ref int[] stack, ref int pos, int arg0, int arg1, int arg2) { Array.Resize(ref stack, (pos + 2) * 2); StackPush(ref stack, ref pos, arg0, arg1, arg2); } } } }