/// <summary>
/// The top level RegexCode generator. It does a depth-first walk
/// through the tree and calls EmitFragment to emits code before
/// and after each child of an interior node, and at each leaf.
/// </summary>
public RegexCode RegexCodeFromRegexTree(RegexTree tree)
{
Span <int> emittedSpan = stackalloc int[EmittedSize];
Span <int> intStackSpan = stackalloc int[IntStackSize];
RegexWriter writer = new RegexWriter(emittedSpan, intStackSpan);
// construct sparse capnum mapping if some numbers are unused
int capsize;
if (tree._capnumlist == null || tree._captop == tree._capnumlist.Length)
{
capsize = tree._captop;
writer._caps = null;
}
else
{
capsize = tree._capnumlist.Length;
writer._caps = tree._caps;
for (int i = 0; i < tree._capnumlist.Length; i++)
{
writer._caps[tree._capnumlist[i]] = i;
}
}
RegexNode curNode = tree._root;
int curChild = 0;
writer.Emit(RegexCode.Lazybranch, 0);
for (; ;)
{
if (curNode._children == null)
{
writer.EmitFragment(curNode._type, curNode, 0);
}
else if (curChild < curNode._children.Count)
{
writer.EmitFragment(curNode._type | BeforeChild, curNode, curChild);
curNode = curNode._children[curChild];
writer._intStack.Append(curChild);
curChild = 0;
continue;
}
if (writer._intStack.Length == 0)
{
break;
}
curChild = writer._intStack.Pop();
curNode = curNode._next;
writer.EmitFragment(curNode._type | AfterChild, curNode, curChild);
curChild++;
}
writer.PatchJump(0, writer._emitted.Length);
writer.Emit(RegexCode.Stop);
RegexPrefix fcPrefix = RegexFCD.FirstChars(tree);
RegexPrefix prefix = RegexFCD.Prefix(tree);
bool rtl = ((tree._options & RegexOptions.RightToLeft) != 0);
CultureInfo culture = (tree._options & RegexOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture;
RegexBoyerMoore bmPrefix;
if (prefix != null && prefix.Prefix.Length > 0)
{
bmPrefix = new RegexBoyerMoore(prefix.Prefix, prefix.CaseInsensitive, rtl, culture);
}
else
{
bmPrefix = null;
}
int anchors = RegexFCD.Anchors(tree);
int[] emitted = writer._emitted.AsReadOnlySpan().ToArray();
// Cleaning up and returning the borrowed arrays
writer._emitted.Dispose();
writer._intStack.Dispose();
return(new RegexCode(emitted, writer._stringTable, writer._trackCount, writer._caps, capsize, bmPrefix, fcPrefix, anchors, rtl));
}