/// <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);
}