/// <summary>Performs additional optimizations on an entire tree prior to being used.</summary> internal RegexNode FinalOptimize() { RegexNode rootNode = this; // If we find backtracking construct at the end of the regex, we can instead make it non-backtracking, // since nothing would ever backtrack into it anyway. Doing this then makes the construct available // to implementations that don't support backtracking. if ((Options & RegexOptions.RightToLeft) == 0 && // only apply optimization when LTR to avoid needing additional code for the rarer RTL case (Options & RegexOptions.Compiled) != 0) // only apply when we're compiling, as that's the only time it would make a meaningful difference { RegexNode node = rootNode; while (true) { switch (node.Type) { case Oneloop: node.Type = Oneloopatomic; break; case Notoneloop: node.Type = Notoneloopatomic; break; case Setloop: node.Type = Setloopatomic; break; case Capture: case Concatenate: RegexNode existingChild = node.Child(node.ChildCount() - 1); switch (existingChild.Type) { default: node = existingChild; break; case Alternate: case Loop: case Lazyloop: var atomic = new RegexNode(Atomic, Options); atomic.AddChild(existingChild); node.ReplaceChild(node.ChildCount() - 1, atomic); break; } continue; case Atomic: node = node.Child(0); continue; } break; } } // Done optimizing. Return the final tree. return(rootNode); }