/*
* 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.
*
* It runs two passes, first to count the size of the generated
* code, and second to generate the code.
*
* CONSIDER: we need to time it against the alternative, which is
* to just generate the code and grow the array as we go.
*/
internal RegexCode RegexCodeFromRegexTree(RegexTree tree)
{
RegexNode curNode;
int curChild;
int capsize;
RegexPrefix fcPrefix;
RegexPrefix scPrefix;
RegexPrefix prefix;
int anchors;
RegexBoyerMoore bmPrefix;
bool rtl;
// construct sparse capnum mapping if some numbers are unused
if (tree._capnumlist == null || tree._captop == tree._capnumlist.Length)
{
capsize = tree._captop;
_caps = null;
}
else
{
capsize = tree._capnumlist.Length;
_caps = tree._caps;
for (int i = 0; i < tree._capnumlist.Length; i++)
{
_caps[tree._capnumlist[i]] = i;
}
}
_counting = true;
for (;;)
{
if (!_counting)
{
_emitted = new int[_count];
}
curNode = tree._root;
curChild = 0;
Emit(RegexCode.Lazybranch, 0);
for (;;)
{
if (curNode._children == null)
{
EmitFragment(curNode._type, curNode, 0);
}
else if (curChild < curNode._children.Count)
{
EmitFragment(curNode._type | BeforeChild, curNode, curChild);
curNode = (RegexNode)curNode._children[curChild];
PushInt(curChild);
curChild = 0;
continue;
}
if (EmptyStack())
{
break;
}
curChild = PopInt();
curNode = curNode._next;
EmitFragment(curNode._type | AfterChild, curNode, curChild);
curChild++;
}
PatchJump(0, CurPos());
Emit(RegexCode.Stop);
if (!_counting)
{
break;
}
_counting = false;
}
// if the set of possible first chars is very large,
// don't bother scanning for it (common case: . == [^\n])
fcPrefix = RegexFCD.FirstChars(tree);
// REVIEW : ChrisAn/DavidGut, 11/21/2000 - Huh... this code used to
// : read "> 0XFFF", note the CAPITAL X... everything is golden,
// : except that this really evaluates to 0 in the C# compiler.
// :
// : However! begining in CSC 9055 0XFFF will attempted to be
// : evaluated as a float, causing a compiler error. So switching
// : the constant to "0xFFF", note the lowercase x, causes
// : everything to fail.
// :
// : What is this code really supposed to do???!
//
if (fcPrefix != null && RegexCharClass.SetSize(fcPrefix.Prefix) > 0)
{
fcPrefix = null;
}
// REVIEW: is this even used anywhere? Can we use it somehow?
scPrefix = null; //RegexFCD.ScanChars(tree);
prefix = RegexFCD.Prefix(tree);
rtl = ((tree._options & RegexOptions.RightToLeft) != 0);
CultureInfo culture = (tree._options & RegexOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture;
if (prefix != null && prefix.Prefix.Length > 0)
{
bmPrefix = new RegexBoyerMoore(prefix.Prefix, prefix.CaseInsensitive, rtl, culture);
}
else
{
bmPrefix = null;
}
anchors = RegexFCD.Anchors(tree);
return(new RegexCode(_emitted, _stringtable, _trackcount, _caps, capsize, bmPrefix, fcPrefix, scPrefix, anchors, rtl));
}