internal void GenerateOneCode() {
#if DBG
if ((_options & RegexOptions.Debug) != 0) {
Mvlocfld(_textposV, _textposF);
Mvlocfld(_trackposV, _trackposF);
Mvlocfld(_stackposV, _stackposF);
Ldthis();
Callvirt(_dumpstateM);
StringBuilder sb = new StringBuilder();
if (_backpos > 0)
sb.AppendFormat("{0:D6} ", _backpos);
else
sb.Append(" ");
sb.Append(_code.OpcodeDescription(_codepos));
if (IsBack())
sb.Append(" Back");
if (IsBack2())
sb.Append(" Back2");
Message(sb.ToString());
}
#endif
switch (_regexopcode) {
case RegexCode.Stop:
//: return;
Mvlocfld(_textposV, _textposF); // update _textpos
Ret();
break;
case RegexCode.Nothing:
//: break Backward;
Back();
break;
case RegexCode.Goto:
//: Goto(Operand(0));
Goto(Operand(0));
break;
case RegexCode.Testref:
//: if (!_match.IsMatched(Operand(0)))
//: break Backward;
Ldthis();
Ldc(Operand(0));
Callvirt(_ismatchedM);
BrfalseFar(_backtrack);
break;
case RegexCode.Lazybranch:
//: Track(Textpos());
PushTrack(_textposV);
Track();
break;
case RegexCode.Lazybranch | RegexCode.Back:
//: Trackframe(1);
//: Textto(Tracked(0));
//: Goto(Operand(0));
PopTrack();
Stloc(_textposV);
Goto(Operand(0));
break;
case RegexCode.Nullmark:
//: Stack(-1);
//: Track();
ReadyPushStack();
Ldc(-1);
DoPush();
TrackUnique(stackpop);
break;
case RegexCode.Setmark:
//: Stack(Textpos());
//: Track();
PushStack(_textposV);
TrackUnique(stackpop);
break;
case RegexCode.Nullmark | RegexCode.Back:
case RegexCode.Setmark | RegexCode.Back:
//: Stackframe(1);
//: break Backward;
PopDiscardStack();
Back();
break;
case RegexCode.Getmark:
//: Stackframe(1);
//: Track(Stacked(0));
//: Textto(Stacked(0));
ReadyPushTrack();
PopStack();
Dup();
Stloc(_textposV);
DoPush();
Track();
break;
case RegexCode.Getmark | RegexCode.Back:
//: Trackframe(1);
//: Stack(Tracked(0));
//: break Backward;
ReadyPushStack();
PopTrack();
DoPush();
Back();
break;
case RegexCode.Capturemark:
//: if (!IsMatched(Operand(1)))
//: break Backward;
//: Stackframe(1);
//: if (Operand(1) != -1)
//: TransferCapture(Operand(0), Operand(1), Stacked(0), Textpos());
//: else
//: Capture(Operand(0), Stacked(0), Textpos());
//: Track(Stacked(0));
//: Stackframe(1);
//: Capture(Operand(0), Stacked(0), Textpos());
//: Track(Stacked(0));
if (Operand(1) != -1) {
Ldthis();
Ldc(Operand(1));
Callvirt(_ismatchedM);
BrfalseFar(_backtrack);
}
PopStack();
Stloc(_tempV);
if (Operand(1) != -1) {
Ldthis();
Ldc(Operand(0));
Ldc(Operand(1));
Ldloc(_tempV);
Ldloc(_textposV);
Callvirt(_transferM);
}
else {
Ldthis();
Ldc(Operand(0));
Ldloc(_tempV);
Ldloc(_textposV);
Callvirt(_captureM);
}
PushTrack(_tempV);
if (Operand(0) != -1 && Operand(1) != -1)
TrackUnique(capback2);
else
TrackUnique(capback);
break;
case RegexCode.Capturemark | RegexCode.Back:
//: Trackframe(1);
//: Stack(Tracked(0));
//: Uncapture();
//: if (Operand(0) != -1 && Operand(1) != -1)
//: Uncapture();
//: break Backward;
ReadyPushStack();
PopTrack();
DoPush();
Ldthis();
Callvirt(_uncaptureM);
if (Operand(0) != -1 && Operand(1) != -1) {
Ldthis();
Callvirt(_uncaptureM);
}
Back();
break;
case RegexCode.Branchmark:
//: Stackframe(1);
//:
//: if (Textpos() != Stacked(0))
//: { // Nonempty match -> loop now
//: Track(Stacked(0), Textpos()); // Save old mark, textpos
//: Stack(Textpos()); // Make new mark
//: Goto(Operand(0)); // Loop
//: }
//: else
//: { // Empty match -> straight now
//: Track2(Stacked(0)); // Save old mark
//: Advance(1); // Straight
//: }
//: continue Forward;
{
LocalBuilder mark = _tempV;
Label l1 = DefineLabel();
PopStack();
Dup();
Stloc(mark); // Stacked(0) -> temp
PushTrack(mark);
Ldloc(_textposV);
Beq(l1); // mark == textpos -> branch
// (matched != 0)
PushTrack(_textposV);
PushStack(_textposV);
Track();
Goto(Operand(0)); // Goto(Operand(0))
// else
MarkLabel(l1);
TrackUnique2(branchmarkback2);
break;
}
case RegexCode.Branchmark | RegexCode.Back:
//: Trackframe(2);
//: Stackframe(1);
//: Textto(Tracked(1)); // Recall position
//: Track2(Tracked(0)); // Save old mark
//: Advance(1);
PopTrack();
Stloc(_textposV);
PopStack();
Pop();
// track spot 0 is already in place
TrackUnique2(branchmarkback2);
Advance();
break;
case RegexCode.Branchmark | RegexCode.Back2:
//: Trackframe(1);
//: Stack(Tracked(0)); // Recall old mark
//: break Backward; // Backtrack
ReadyPushStack();
PopTrack();
DoPush();
Back();
break;
case RegexCode.Lazybranchmark:
//: StackPop();
//: int oldMarkPos = StackPeek();
//:
//: if (Textpos() != oldMarkPos) { // Nonempty match -> next loop
//: { // Nonempty match -> next loop
//: if (oldMarkPos != -1)
//: Track(Stacked(0), Textpos()); // Save old mark, textpos
//: else
//: TrackPush(Textpos(), Textpos());
//: }
//: else
//: { // Empty match -> no loop
//: Track2(Stacked(0)); // Save old mark
//: }
//: Advance(1);
//: continue Forward;
{
LocalBuilder mark = _tempV;
Label l1 = DefineLabel();
Label l2 = DefineLabel();
Label l3 = DefineLabel();
PopStack();
Dup();
Stloc(mark); // Stacked(0) -> temp
// if (oldMarkPos != -1)
Ldloc(mark);
Ldc(-1);
Beq(l2); // mark == -1 -> branch
PushTrack(mark);
Br(l3);
// else
MarkLabel(l2);
PushTrack(_textposV);
MarkLabel(l3);
// if (Textpos() != mark)
Ldloc(_textposV);
Beq(l1); // mark == textpos -> branch
PushTrack(_textposV);
Track();
Br(AdvanceLabel()); // Advance (near)
// else
MarkLabel(l1);
ReadyPushStack(); // push the current textPos on the stack.
// May be ignored by 'back2' or used by a true empty match.
Ldloc(mark);
DoPush();
TrackUnique2(lazybranchmarkback2);
break;
}
case RegexCode.Lazybranchmark | RegexCode.Back:
//: Trackframe(2);
//: Track2(Tracked(0)); // Save old mark
//: Stack(Textpos()); // Make new mark
//: Textto(Tracked(1)); // Recall position
//: Goto(Operand(0)); // Loop
PopTrack();
Stloc(_textposV);
PushStack(_textposV);
TrackUnique2(lazybranchmarkback2);
Goto(Operand(0));
break;
case RegexCode.Lazybranchmark | RegexCode.Back2:
//: Stackframe(1);
//: Trackframe(1);
//: Stack(Tracked(0)); // Recall old mark
//: break Backward;
ReadyReplaceStack(0);
PopTrack();
DoReplace();
Back();
break;
case RegexCode.Nullcount:
//: Stack(-1, Operand(0));
//: Track();
ReadyPushStack();
Ldc(-1);
DoPush();
ReadyPushStack();
Ldc(Operand(0));
DoPush();
TrackUnique(stackpop2);
break;
case RegexCode.Setcount:
//: Stack(Textpos(), Operand(0));
//: Track();
PushStack(_textposV);
ReadyPushStack();
Ldc(Operand(0));
DoPush();
TrackUnique(stackpop2);
break;
case RegexCode.Nullcount | RegexCode.Back:
case RegexCode.Setcount | RegexCode.Back:
//: Stackframe(2);
//: break Backward;
PopDiscardStack(2);
Back();
break;
case RegexCode.Branchcount:
//: Stackframe(2);
//: int mark = Stacked(0);
//: int count = Stacked(1);
//:
//: if (count >= Operand(1) || Textpos() == mark && count >= 0)
//: { // Max loops or empty match -> straight now
//: Track2(mark, count); // Save old mark, count
//: Advance(2); // Straight
//: }
//: else
//: { // Nonempty match -> count+loop now
//: Track(mark); // remember mark
//: Stack(Textpos(), count + 1); // Make new mark, incr count
//: Goto(Operand(0)); // Loop
//: }
//: continue Forward;
{
LocalBuilder count = _tempV;
LocalBuilder mark = _temp2V;
Label l1 = DefineLabel();
Label l2 = DefineLabel();
PopStack();
Stloc(count); // count -> temp
PopStack();
Dup();
Stloc(mark); // mark -> temp2
PushTrack(mark);
Ldloc(_textposV);
Bne(l1); // mark != textpos -> l1
Ldloc(count);
Ldc(0);
Bge(l2); // count >= 0 && mark == textpos -> l2
MarkLabel(l1);
Ldloc(count);
Ldc(Operand(1));
Bge(l2); // count >= Operand(1) -> l2
// else
PushStack(_textposV);
ReadyPushStack();
Ldloc(count); // mark already on track
Ldc(1);
Add();
DoPush();
Track();
Goto(Operand(0));
// if (count >= Operand(1) || Textpos() == mark)
MarkLabel(l2);
PushTrack(count); // mark already on track
TrackUnique2(branchcountback2);
break;
}
case RegexCode.Branchcount | RegexCode.Back:
//: Trackframe(1);
//: Stackframe(2);
//: if (Stacked(1) > 0) // Positive -> can go straight
//: {
//: Textto(Stacked(0)); // Zap to mark
//: Track2(Tracked(0), Stacked(1) - 1); // Save old mark, old count
//: Advance(2); // Straight
//: continue Forward;
//: }
//: Stack(Tracked(0), Stacked(1) - 1); // recall old mark, old count
//: break Backward;
{
LocalBuilder count = _tempV;
Label l1 = DefineLabel();
PopStack();
Ldc(1);
Sub();
Dup();
Stloc(count);
Ldc(0);
Blt(l1);
// if (count >= 0)
PopStack();
Stloc(_textposV);
PushTrack(count); // Tracked(0) is alredy on the track
TrackUnique2(branchcountback2);
Advance();
// else
MarkLabel(l1);
ReadyReplaceStack(0);
PopTrack();
DoReplace();
PushStack(count);
Back();
break;
}
case RegexCode.Branchcount | RegexCode.Back2:
//: Trackframe(2);
//: Stack(Tracked(0), Tracked(1)); // Recall old mark, old count
//: break Backward; // Backtrack
PopTrack();
Stloc(_tempV);
ReadyPushStack();
PopTrack();
DoPush();
PushStack(_tempV);
Back();
break;
case RegexCode.Lazybranchcount:
//: Stackframe(2);
//: int mark = Stacked(0);
//: int count = Stacked(1);
//:
//: if (count < 0)
//: { // Negative count -> loop now
//: Track2(mark); // Save old mark
//: Stack(Textpos(), count + 1); // Make new mark, incr count
//: Goto(Operand(0)); // Loop
//: }
//: else
//: { // Nonneg count or empty match -> straight now
//: Track(mark, count, Textpos()); // Save mark, count, position
//: }
{
LocalBuilder count = _tempV;
LocalBuilder mark = _temp2V;
Label l1 = DefineLabel();
Label l2 = DefineLabel();
Label l3 = _labels[NextCodepos()];
PopStack();
Stloc(count); // count -> temp
PopStack();
Stloc(mark); // mark -> temp2
Ldloc(count);
Ldc(0);
Bge(l1); // count >= 0 -> l1
// if (count < 0)
PushTrack(mark);
PushStack(_textposV);
ReadyPushStack();
Ldloc(count);
Ldc(1);
Add();
DoPush();
TrackUnique2(lazybranchcountback2);
Goto(Operand(0));
// else
MarkLabel(l1);
PushTrack(mark);
PushTrack(count);
PushTrack(_textposV);
Track();
break;
}
case RegexCode.Lazybranchcount | RegexCode.Back:
//: Trackframe(3);
//: int mark = Tracked(0);
//: int textpos = Tracked(2);
//: if (Tracked(1) <= Operand(1) && textpos != mark)
//: {
//: Textto(Tracked(2)); // Recall position
//: Stack(Textpos(), Tracked(1) + 1); // Make new mark, incr count
//: Track2(Tracked(0)); // Save old mark
//: Goto(Operand(0)); // Loop
//: continue Forward;
//: }
//: else
//: {
//: Stack(Tracked(0), Tracked(1)); // Recall old mark, count
//: break Backward; // backtrack
//: }
{
Label l1 = DefineLabel();
LocalBuilder cV = _tempV;
PopTrack();
Stloc(_textposV);
PopTrack();
Dup();
Stloc(cV);
Ldc(Operand(1));
Bgt(l1); // Tracked(1) > Operand(1) -> l1
Ldloc(_textposV);
TopTrack();
Beq(l1); // textpos == mark -> l1
PushStack(_textposV);
ReadyPushStack();
Ldloc(cV);
Ldc(1);
Add();
DoPush();
TrackUnique2(lazybranchcountback2);
Goto(Operand(0));
MarkLabel(l1);
ReadyPushStack();
PopTrack();
DoPush();
PushStack(cV);
Back();
break;
}
case RegexCode.Lazybranchcount | RegexCode.Back2:
ReadyReplaceStack(1);
PopTrack();
DoReplace();
ReadyReplaceStack(0);
TopStack();
Ldc(1);
Sub();
DoReplace();
Back();
break;
case RegexCode.Setjump:
//: Stack(Trackpos(), Crawlpos());
//: Track();
ReadyPushStack();
Ldthisfld(_trackF);
Ldlen();
Ldloc(_trackposV);
Sub();
DoPush();
ReadyPushStack();
Ldthis();
Callvirt(_crawlposM);
DoPush();
TrackUnique(stackpop2);
break;
case RegexCode.Setjump | RegexCode.Back:
//: Stackframe(2);
PopDiscardStack(2);
Back();
break;
case RegexCode.Backjump:
//: Stackframe(2);
//: Trackto(Stacked(0));
//: while (Crawlpos() != Stacked(1))
//: Uncapture();
//: break Backward;
{
Label l1 = DefineLabel();
Label l2 = DefineLabel();
PopStack();
Ldthisfld(_trackF);
Ldlen();
PopStack();
Sub();
Stloc(_trackposV);
Dup();
Ldthis();
Callvirt(_crawlposM);
Beq(l2);
MarkLabel(l1);
Ldthis();
Callvirt(_uncaptureM);
Dup();
Ldthis();
Callvirt(_crawlposM);
Bne(l1);
MarkLabel(l2);
Pop();
Back();
break;
}
case RegexCode.Forejump:
//: Stackframe(2);
//: Trackto(Stacked(0));
//: Track(Stacked(1));
PopStack();
Stloc(_tempV);
Ldthisfld(_trackF);
Ldlen();
PopStack();
Sub();
Stloc(_trackposV);
PushTrack(_tempV);
TrackUnique(forejumpback);
break;
case RegexCode.Forejump | RegexCode.Back:
//: Trackframe(1);
//: while (Crawlpos() != Tracked(0))
//: Uncapture();
//: break Backward;
{
Label l1 = DefineLabel();
Label l2 = DefineLabel();
PopTrack();
Dup();
Ldthis();
Callvirt(_crawlposM);
Beq(l2);
MarkLabel(l1);
Ldthis();
Callvirt(_uncaptureM);
Dup();
Ldthis();
Callvirt(_crawlposM);
Bne(l1);
MarkLabel(l2);
Pop();
Back();
break;
}
case RegexCode.Bol:
//: if (Leftchars() > 0 && CharAt(Textpos() - 1) != '\n')
//: break Backward;
{
Label l1 = _labels[NextCodepos()];
Ldloc(_textposV);
Ldloc(_textbegV);
Ble(l1);
Leftchar();
Ldc((int)'\n');
BneFar(_backtrack);
break;
}
case RegexCode.Eol:
//: if (Rightchars() > 0 && CharAt(Textpos()) != '\n')
//: break Backward;
{
Label l1 = _labels[NextCodepos()];
Ldloc(_textposV);
Ldloc(_textendV);
Bge(l1);
Rightchar();
Ldc((int)'\n');
BneFar(_backtrack);
break;
}
case RegexCode.Boundary:
case RegexCode.Nonboundary:
//: if (!IsBoundary(Textpos(), _textbeg, _textend))
//: break Backward;
Ldthis();
Ldloc(_textposV);
Ldloc(_textbegV);
Ldloc(_textendV);
Callvirt(_isboundaryM);
if (Code() == RegexCode.Boundary)
BrfalseFar(_backtrack);
else
BrtrueFar(_backtrack);
break;
case RegexCode.ECMABoundary:
case RegexCode.NonECMABoundary:
//: if (!IsECMABoundary(Textpos(), _textbeg, _textend))
//: break Backward;
Ldthis();
Ldloc(_textposV);
Ldloc(_textbegV);
Ldloc(_textendV);
Callvirt(_isECMABoundaryM);
if (Code() == RegexCode.ECMABoundary)
BrfalseFar(_backtrack);
else
BrtrueFar(_backtrack);
break;
case RegexCode.Beginning:
//: if (Leftchars() > 0)
//: break Backward;
Ldloc(_textposV);
Ldloc(_textbegV);
BgtFar(_backtrack);
break;
case RegexCode.Start:
//: if (Textpos() != Textstart())
//: break Backward;
Ldloc(_textposV);
Ldthisfld(_textstartF);
BneFar(_backtrack);
break;
case RegexCode.EndZ:
//: if (Rightchars() > 1 || Rightchars() == 1 && CharAt(Textpos()) != '\n')
//: break Backward;
Ldloc(_textposV);
Ldloc(_textendV);
Ldc(1);
Sub();
BltFar(_backtrack);
Ldloc(_textposV);
Ldloc(_textendV);
Bge(_labels[NextCodepos()]);
Rightchar();
Ldc((int)'\n');
BneFar(_backtrack);
break;
case RegexCode.End:
//: if (Rightchars() > 0)
//: break Backward;
Ldloc(_textposV);
Ldloc(_textendV);
BltFar(_backtrack);
break;
case RegexCode.One:
case RegexCode.Notone:
case RegexCode.Set:
case RegexCode.One | RegexCode.Rtl:
case RegexCode.Notone | RegexCode.Rtl:
case RegexCode.Set | RegexCode.Rtl:
case RegexCode.One | RegexCode.Ci:
case RegexCode.Notone | RegexCode.Ci:
case RegexCode.Set | RegexCode.Ci:
case RegexCode.One | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Notone | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Set | RegexCode.Ci | RegexCode.Rtl:
//: if (Rightchars() < 1 || Rightcharnext() != (char)Operand(0))
//: break Backward;
Ldloc(_textposV);
if (!IsRtl()) {
Ldloc(_textendV);
BgeFar(_backtrack);
Rightcharnext();
}
else {
Ldloc(_textbegV);
BleFar(_backtrack);
Leftcharnext();
}
if (IsCi())
CallToLower();
if (Code() == RegexCode.Set) {
Ldstr(_strings[Operand(0)]);
Call(_charInSetM);
BrfalseFar(_backtrack);
}
else {
Ldc(Operand(0));
if (Code() == RegexCode.One)
BneFar(_backtrack);
else
BeqFar(_backtrack);
}
break;
case RegexCode.Multi:
case RegexCode.Multi | RegexCode.Ci:
//
{
int i;
String str;
str = _strings[Operand(0)];
Ldc(str.Length);
Ldloc(_textendV);
Ldloc(_textposV);
Sub();
BgtFar(_backtrack);
// unroll the string
for (i = 0; i < str.Length; i++) {
Ldloc(_textV);
Ldloc(_textposV);
if (i != 0) {
Ldc(i);
Add();
}
Callvirt(_getcharM);
if (IsCi())
CallToLower();
Ldc((int)str[i]);
BneFar(_backtrack);
}
Ldloc(_textposV);
Ldc(str.Length);
Add();
Stloc(_textposV);
break;
}
case RegexCode.Multi | RegexCode.Rtl:
case RegexCode.Multi | RegexCode.Ci | RegexCode.Rtl:
//: String Str = _strings[Operand(0)];
//: int c;
//: if (Leftchars() < (c = Str.Length))
//: break Backward;
//: while (c > 0)
//: if (Str[--c] != Leftcharnext())
//: break Backward;
{
int i;
String str;
str = _strings[Operand(0)];
Ldc(str.Length);
Ldloc(_textposV);
Ldloc(_textbegV);
Sub();
BgtFar(_backtrack);
// unroll the string
for (i = str.Length; i > 0;) {
i--;
Ldloc(_textV);
Ldloc(_textposV);
Ldc(str.Length - i);
Sub();
Callvirt(_getcharM);
if (IsCi())
{
CallToLower();
}
Ldc((int)str[i]);
BneFar(_backtrack);
}
Ldloc(_textposV);
Ldc(str.Length);
Sub();
Stloc(_textposV);
break;
}
case RegexCode.Ref:
case RegexCode.Ref | RegexCode.Rtl:
case RegexCode.Ref | RegexCode.Ci:
case RegexCode.Ref | RegexCode.Ci | RegexCode.Rtl:
//: int capnum = Operand(0);
//: int j, c;
//: if (!_match.IsMatched(capnum)) {
//: if (!RegexOptions.ECMAScript)
//: break Backward;
//: } else {
//: if (Rightchars() < (c = _match.MatchLength(capnum)))
//: break Backward;
//: for (j = _match.MatchIndex(capnum); c > 0; j++, c--)
//: if (CharAt(j) != Rightcharnext())
//: break Backward;
//: }
{
LocalBuilder lenV = _tempV;
LocalBuilder indexV = _temp2V;
Label l1 = DefineLabel();
Ldthis();
Ldc(Operand(0));
Callvirt(_ismatchedM);
if ((_options & RegexOptions.ECMAScript) != 0)
Brfalse(AdvanceLabel());
else
BrfalseFar(_backtrack); // !IsMatched() -> back
Ldthis();
Ldc(Operand(0));
Callvirt(_matchlengthM);
Dup();
Stloc(lenV);
if (!IsRtl()) {
Ldloc(_textendV);
Ldloc(_textposV);
}
else {
Ldloc(_textposV);
Ldloc(_textbegV);
}
Sub();
BgtFar(_backtrack); // Matchlength() > Rightchars() -> back
Ldthis();
Ldc(Operand(0));
Callvirt(_matchindexM);
if (!IsRtl()) {
Ldloc(lenV);
Add(IsRtl());
}
Stloc(indexV); // index += len
Ldloc(_textposV);
Ldloc(lenV);
Add(IsRtl());
Stloc(_textposV); // texpos += len
MarkLabel(l1);
Ldloc(lenV);
Ldc(0);
Ble(AdvanceLabel());
Ldloc(_textV);
Ldloc(indexV);
Ldloc(lenV);
if (IsRtl()) {
Ldc(1);
Sub();
Dup();
Stloc(lenV);
}
Sub(IsRtl());
Callvirt(_getcharM);
if (IsCi())
CallToLower();
Ldloc(_textV);
Ldloc(_textposV);
Ldloc(lenV);
if (!IsRtl()) {
Dup();
Ldc(1);
Sub();
Stloc(lenV);
}
Sub(IsRtl());
Callvirt(_getcharM);
if (IsCi())
CallToLower();
Beq(l1);
Back();
break;
}
case RegexCode.Onerep:
case RegexCode.Notonerep:
case RegexCode.Setrep:
case RegexCode.Onerep | RegexCode.Rtl:
case RegexCode.Notonerep | RegexCode.Rtl:
case RegexCode.Setrep | RegexCode.Rtl:
case RegexCode.Onerep | RegexCode.Ci:
case RegexCode.Notonerep | RegexCode.Ci:
case RegexCode.Setrep | RegexCode.Ci:
case RegexCode.Onerep | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Notonerep | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Setrep | RegexCode.Ci | RegexCode.Rtl:
//: int c = Operand(1);
//: if (Rightchars() < c)
//: break Backward;
//: char ch = (char)Operand(0);
//: while (c-- > 0)
//: if (Rightcharnext() != ch)
//: break Backward;
{
LocalBuilder lenV = _tempV;
Label l1 = DefineLabel();
int c = Operand(1);
if (c == 0)
break;
Ldc(c);
if (!IsRtl()) {
Ldloc(_textendV);
Ldloc(_textposV);
}
else {
Ldloc(_textposV);
Ldloc(_textbegV);
}
Sub();
BgtFar(_backtrack); // Matchlength() > Rightchars() -> back
Ldloc(_textposV);
Ldc(c);
Add(IsRtl());
Stloc(_textposV); // texpos += len
Ldc(c);
Stloc(lenV);
MarkLabel(l1);
Ldloc(_textV);
Ldloc(_textposV);
Ldloc(lenV);
if (IsRtl()) {
Ldc(1);
Sub();
Dup();
Stloc(lenV);
Add();
}
else {
Dup();
Ldc(1);
Sub();
Stloc(lenV);
Sub();
}
Callvirt(_getcharM);
if (IsCi())
CallToLower();
if (Code() == RegexCode.Setrep) {
Ldstr(_strings[Operand(0)]);
Call(_charInSetM);
BrfalseFar(_backtrack);
}
else {
Ldc(Operand(0));
if (Code() == RegexCode.Onerep)
BneFar(_backtrack);
else
BeqFar(_backtrack);
}
Ldloc(lenV);
Ldc(0);
if (Code() == RegexCode.Setrep)
BgtFar(l1);
else
Bgt(l1);
break;
}
case RegexCode.Oneloop:
case RegexCode.Notoneloop:
case RegexCode.Setloop:
case RegexCode.Oneloop | RegexCode.Rtl:
case RegexCode.Notoneloop | RegexCode.Rtl:
case RegexCode.Setloop | RegexCode.Rtl:
case RegexCode.Oneloop | RegexCode.Ci:
case RegexCode.Notoneloop | RegexCode.Ci:
case RegexCode.Setloop | RegexCode.Ci:
case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl:
//: int c = Operand(1);
//: if (c > Rightchars())
//: c = Rightchars();
//: char ch = (char)Operand(0);
//: int i;
//: for (i = c; i > 0; i--)
//: {
//: if (Rightcharnext() != ch)
//: {
//: Leftnext();
//: break;
//: }
//: }
//: if (c > i)
//: Track(c - i - 1, Textpos() - 1);
{
LocalBuilder cV = _tempV;
LocalBuilder lenV = _temp2V;
Label l1 = DefineLabel();
Label l2 = DefineLabel();
int c = Operand(1);
if (c == 0)
break;
if (!IsRtl()) {
Ldloc(_textendV);
Ldloc(_textposV);
}
else {
Ldloc(_textposV);
Ldloc(_textbegV);
}
Sub();
if (c != Int32.MaxValue) {
Label l4 = DefineLabel();
Dup();
Ldc(c);
Blt(l4);
Pop();
Ldc(c);
MarkLabel(l4);
}
Dup();
Stloc(lenV);
Ldc(1);
Add();
Stloc(cV);
MarkLabel(l1);
Ldloc(cV);
Ldc(1);
Sub();
Dup();
Stloc(cV);
Ldc(0);
if (Code() == RegexCode.Setloop)
BleFar(l2);
else
Ble(l2);
if (IsRtl())
Leftcharnext();
else
Rightcharnext();
if (IsCi())
CallToLower();
if (Code() == RegexCode.Setloop) {
Ldstr(_strings[Operand(0)]);
Call(_charInSetM);
BrtrueFar(l1);
}
else {
Ldc(Operand(0));
if (Code() == RegexCode.Oneloop)
Beq(l1);
else
Bne(l1);
}
Ldloc(_textposV);
Ldc(1);
Sub(IsRtl());
Stloc(_textposV);
MarkLabel(l2);
Ldloc(lenV);
Ldloc(cV);
Ble(AdvanceLabel());
ReadyPushTrack();
Ldloc(lenV);
Ldloc(cV);
Sub();
Ldc(1);
Sub();
DoPush();
ReadyPushTrack();
Ldloc(_textposV);
Ldc(1);
Sub(IsRtl());
DoPush();
Track();
break;
}
case RegexCode.Oneloop | RegexCode.Back:
case RegexCode.Notoneloop | RegexCode.Back:
case RegexCode.Setloop | RegexCode.Back:
case RegexCode.Oneloop | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Notoneloop | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Setloop | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Back:
case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Back:
case RegexCode.Setloop | RegexCode.Ci | RegexCode.Back:
case RegexCode.Oneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Notoneloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Setloop | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
//: Trackframe(2);
//: int i = Tracked(0);
//: int pos = Tracked(1);
//: Textto(pos);
//: if (i > 0)
//: Track(i - 1, pos - 1);
//: Advance(2);
PopTrack();
Stloc(_textposV);
PopTrack();
Stloc(_tempV);
Ldloc(_tempV);
Ldc(0);
BleFar(AdvanceLabel());
ReadyPushTrack();
Ldloc(_tempV);
Ldc(1);
Sub();
DoPush();
ReadyPushTrack();
Ldloc(_textposV);
Ldc(1);
Sub(IsRtl());
DoPush();
Trackagain();
Advance();
break;
case RegexCode.Onelazy:
case RegexCode.Notonelazy:
case RegexCode.Setlazy:
case RegexCode.Onelazy | RegexCode.Rtl:
case RegexCode.Notonelazy | RegexCode.Rtl:
case RegexCode.Setlazy | RegexCode.Rtl:
case RegexCode.Onelazy | RegexCode.Ci:
case RegexCode.Notonelazy | RegexCode.Ci:
case RegexCode.Setlazy | RegexCode.Ci:
case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl:
case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl:
//: int c = Operand(1);
//: if (c > Rightchars())
//: c = Rightchars();
//: if (c > 0)
//: Track(c - 1, Textpos());
{
LocalBuilder cV = _tempV;
int c = Operand(1);
if (c == 0)
break;
if (!IsRtl()) {
Ldloc(_textendV);
Ldloc(_textposV);
}
else {
Ldloc(_textposV);
Ldloc(_textbegV);
}
Sub();
if (c != Int32.MaxValue) {
Label l4 = DefineLabel();
Dup();
Ldc(c);
Blt(l4);
Pop();
Ldc(c);
MarkLabel(l4);
}
Dup();
Stloc(cV);
Ldc(0);
Ble(AdvanceLabel());
ReadyPushTrack();
Ldloc(cV);
Ldc(1);
Sub();
DoPush();
PushTrack(_textposV);
Track();
break;
}
case RegexCode.Onelazy | RegexCode.Back:
case RegexCode.Notonelazy | RegexCode.Back:
case RegexCode.Setlazy | RegexCode.Back:
case RegexCode.Onelazy | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Notonelazy | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Setlazy | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Back:
case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Back:
case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Back:
case RegexCode.Onelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Notonelazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
case RegexCode.Setlazy | RegexCode.Ci | RegexCode.Rtl | RegexCode.Back:
//: Trackframe(2);
//: int pos = Tracked(1);
//: Textto(pos);
//: if (Rightcharnext() != (char)Operand(0))
//: break Backward;
//: int i = Tracked(0);
//: if (i > 0)
//: Track(i - 1, pos + 1);
PopTrack();
Stloc(_textposV);
PopTrack();
Stloc(_temp2V);
if (!IsRtl())
Rightcharnext();
else
Leftcharnext();
if (IsCi())
CallToLower();
if (Code() == RegexCode.Setlazy) {
Ldstr(_strings[Operand(0)]);
Call(_charInSetM);
BrfalseFar(_backtrack);
}
else {
Ldc(Operand(0));
if (Code() == RegexCode.Onelazy)
BneFar(_backtrack);
else
BeqFar(_backtrack);
}
Ldloc(_temp2V);
Ldc(0);
BleFar(AdvanceLabel());
ReadyPushTrack();
Ldloc(_temp2V);
Ldc(1);
Sub();
DoPush();
PushTrack(_textposV);
Trackagain();
Advance();
break;
default:
throw new NotImplementedException(SR.GetString(SR.UnimplementedState));
}
}
}