/* * The main 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. */ internal void EmitFragment(int nodetype, RegexNode node, int CurIndex) { int bits = 0; if (nodetype <= RegexNode.Ref) { if (node.UseOptionR()) { bits |= RegexCode.Rtl; } if ((node._options & RegexOptions.IgnoreCase) != 0) { bits |= RegexCode.Ci; } } switch (nodetype) { case RegexNode.Concatenate | BeforeChild: case RegexNode.Concatenate | AfterChild: case RegexNode.Empty: break; case RegexNode.Alternate | BeforeChild: if (CurIndex < node._children.Count - 1) { PushInt(CurPos()); Emit(RegexCode.Lazybranch, 0); } break; case RegexNode.Alternate | AfterChild: { if (CurIndex < node._children.Count - 1) { int LBPos = PopInt(); PushInt(CurPos()); Emit(RegexCode.Goto, 0); PatchJump(LBPos, CurPos()); } else { int I; for (I = 0; I < CurIndex; I++) { PatchJump(PopInt(), CurPos()); } } break; } case RegexNode.Testref | BeforeChild: switch (CurIndex) { case 0: Emit(RegexCode.Setjump); PushInt(CurPos()); Emit(RegexCode.Lazybranch, 0); Emit(RegexCode.Testref, MapCapnum(node._m)); Emit(RegexCode.Forejump); break; } break; case RegexNode.Testref | AfterChild: switch (CurIndex) { case 0: { int Branchpos = PopInt(); PushInt(CurPos()); Emit(RegexCode.Goto, 0); PatchJump(Branchpos, CurPos()); Emit(RegexCode.Forejump); if (node._children.Count > 1) { break; } // else fallthrough goto case 1; } case 1: PatchJump(PopInt(), CurPos()); break; } break; case RegexNode.Testgroup | BeforeChild: switch (CurIndex) { case 0: Emit(RegexCode.Setjump); Emit(RegexCode.Setmark); PushInt(CurPos()); Emit(RegexCode.Lazybranch, 0); break; } break; case RegexNode.Testgroup | AfterChild: switch (CurIndex) { case 0: Emit(RegexCode.Getmark); Emit(RegexCode.Forejump); break; case 1: int Branchpos = PopInt(); PushInt(CurPos()); Emit(RegexCode.Goto, 0); PatchJump(Branchpos, CurPos()); Emit(RegexCode.Getmark); Emit(RegexCode.Forejump); if (node._children.Count > 2) { break; } // else fallthrough goto case 2; case 2: PatchJump(PopInt(), CurPos()); break; } break; case RegexNode.Loop | BeforeChild: case RegexNode.Lazyloop | BeforeChild: if (node._n < Int32.MaxValue || node._m > 1) { Emit(node._m == 0 ? RegexCode.Nullcount : RegexCode.Setcount, node._m == 0 ? 0 : 1 - node._m); } else { Emit(node._m == 0 ? RegexCode.Nullmark : RegexCode.Setmark); } if (node._m == 0) { PushInt(CurPos()); Emit(RegexCode.Goto, 0); } PushInt(CurPos()); break; case RegexNode.Loop | AfterChild: case RegexNode.Lazyloop | AfterChild: { int StartJumpPos = CurPos(); int Lazy = (nodetype - (RegexNode.Loop | AfterChild)); if (node._n < Int32.MaxValue || node._m > 1) { Emit(RegexCode.Branchcount + Lazy, PopInt(), node._n == Int32.MaxValue ? Int32.MaxValue : node._n - node._m); } else { Emit(RegexCode.Branchmark + Lazy, PopInt()); } if (node._m == 0) { PatchJump(PopInt(), StartJumpPos); } } break; case RegexNode.Group | BeforeChild: case RegexNode.Group | AfterChild: break; case RegexNode.Capture | BeforeChild: Emit(RegexCode.Setmark); break; case RegexNode.Capture | AfterChild: Emit(RegexCode.Capturemark, MapCapnum(node._m), MapCapnum(node._n)); break; case RegexNode.Require | BeforeChild: // NOTE: the following line causes lookahead/lookbehind to be // NON-BACKTRACKING. It can be commented out with (*) Emit(RegexCode.Setjump); Emit(RegexCode.Setmark); break; case RegexNode.Require | AfterChild: Emit(RegexCode.Getmark); // NOTE: the following line causes lookahead/lookbehind to be // NON-BACKTRACKING. It can be commented out with (*) Emit(RegexCode.Forejump); break; case RegexNode.Prevent | BeforeChild: Emit(RegexCode.Setjump); PushInt(CurPos()); Emit(RegexCode.Lazybranch, 0); break; case RegexNode.Prevent | AfterChild: Emit(RegexCode.Backjump); PatchJump(PopInt(), CurPos()); Emit(RegexCode.Forejump); break; case RegexNode.Greedy | BeforeChild: Emit(RegexCode.Setjump); break; case RegexNode.Greedy | AfterChild: Emit(RegexCode.Forejump); break; case RegexNode.One: case RegexNode.Notone: Emit(node._type | bits, (int)node._ch); break; case RegexNode.Notoneloop: case RegexNode.Notonelazy: case RegexNode.Oneloop: case RegexNode.Onelazy: if (node._m > 0) { Emit(((node._type == RegexNode.Oneloop || node._type == RegexNode.Onelazy) ? RegexCode.Onerep : RegexCode.Notonerep) | bits, (int)node._ch, node._m); } if (node._n > node._m) { Emit(node._type | bits, (int)node._ch, node._n == Int32.MaxValue ? Int32.MaxValue : node._n - node._m); } break; case RegexNode.Setloop: case RegexNode.Setlazy: if (node._m > 0) { Emit(RegexCode.Setrep | bits, StringCode(node._str), node._m); } if (node._n > node._m) { Emit(node._type | bits, StringCode(node._str), (node._n == Int32.MaxValue) ? Int32.MaxValue : node._n - node._m); } break; case RegexNode.Multi: Emit(node._type | bits, StringCode(node._str)); break; case RegexNode.Set: Emit(node._type | bits, StringCode(node._str)); break; case RegexNode.Ref: Emit(node._type | bits, MapCapnum(node._m)); break; case RegexNode.Nothing: case RegexNode.Bol: case RegexNode.Eol: case RegexNode.Boundary: case RegexNode.Nonboundary: case RegexNode.ECMABoundary: case RegexNode.NonECMABoundary: case RegexNode.Beginning: case RegexNode.Start: case RegexNode.EndZ: case RegexNode.End: Emit(node._type); break; default: throw MakeException(SR.GetString(SR.UnexpectedOpcode, nodetype.ToString(CultureInfo.CurrentCulture))); } }
internal RegexReplacement(String rep, RegexNode concat, Hashtable _caps) { #endif StringBuilder sb; List <String> strings; List <Int32> rules; int slot; _rep = rep; if (concat.Type() != RegexNode.Concatenate) { throw new ArgumentException(SR.GetString(SR.ReplacementError)); } sb = new StringBuilder(); strings = new List <String>(); rules = new List <Int32>(); for (int i = 0; i < concat.ChildCount(); i++) { RegexNode child = concat.Child(i); switch (child.Type()) { case RegexNode.Multi: sb.Append(child._str); break; case RegexNode.One: sb.Append(child._ch); break; case RegexNode.Ref: if (sb.Length > 0) { rules.Add(strings.Count); strings.Add(sb.ToString()); sb.Length = 0; } slot = child._m; if (_caps != null && slot >= 0) { slot = (int)_caps[slot]; } rules.Add(-Specials - 1 - slot); break; default: throw new ArgumentException(SR.GetString(SR.ReplacementError)); } } if (sb.Length > 0) { rules.Add(strings.Count); strings.Add(sb.ToString()); } _strings = strings; _rules = rules; }
internal void EmitFragment(int nodetype, RegexNode node, int CurIndex) { int num = 0; if (nodetype <= 13) { if (node.UseOptionR()) { num |= 0x40; } if ((node._options & RegexOptions.IgnoreCase) != RegexOptions.None) { num |= 0x200; } } switch (nodetype) { case 3: case 4: case 6: case 7: if (node._m > 0) { this.Emit((((node._type == 3) || (node._type == 6)) ? 0 : 1) | num, node._ch, node._m); } if (node._n > node._m) { this.Emit(node._type | num, node._ch, (node._n == 0x7fffffff) ? 0x7fffffff : (node._n - node._m)); } return; case 5: case 8: if (node._m > 0) { this.Emit(2 | num, this.StringCode(node._str), node._m); } if (node._n > node._m) { this.Emit(node._type | num, this.StringCode(node._str), (node._n == 0x7fffffff) ? 0x7fffffff : (node._n - node._m)); } return; case 9: case 10: this.Emit(node._type | num, node._ch); return; case 11: this.Emit(node._type | num, this.StringCode(node._str)); return; case 12: this.Emit(node._type | num, this.StringCode(node._str)); return; case 13: this.Emit(node._type | num, this.MapCapnum(node._m)); return; case 14: case 15: case 0x10: case 0x11: case 0x12: case 0x13: case 20: case 0x15: case 0x16: case 0x29: case 0x2a: this.Emit(node._type); return; case 0x17: case 0x59: case 0x5d: case 0x99: case 0x9d: return; case 0x58: if (CurIndex < (node._children.Count - 1)) { this.PushInt(this.CurPos()); this.Emit(0x17, 0); } return; case 90: case 0x5b: if ((node._n >= 0x7fffffff) && (node._m <= 1)) { this.Emit((node._m == 0) ? 30 : 0x1f); } else { this.Emit((node._m == 0) ? 0x1a : 0x1b, (node._m == 0) ? 0 : (1 - node._m)); } if (node._m == 0) { this.PushInt(this.CurPos()); this.Emit(0x26, 0); } this.PushInt(this.CurPos()); return; case 0x5c: this.Emit(0x1f); return; case 0x5e: this.Emit(0x22); this.Emit(0x1f); return; case 0x5f: this.Emit(0x22); this.PushInt(this.CurPos()); this.Emit(0x17, 0); return; case 0x60: this.Emit(0x22); return; case 0x61: if (CurIndex == 0) { this.Emit(0x22); this.PushInt(this.CurPos()); this.Emit(0x17, 0); this.Emit(0x25, this.MapCapnum(node._m)); this.Emit(0x24); return; } return; case 0x62: if (CurIndex == 0) { this.Emit(0x22); this.Emit(0x1f); this.PushInt(this.CurPos()); this.Emit(0x17, 0); return; } return; case 0x98: { if (CurIndex >= (node._children.Count - 1)) { for (int i = 0; i < CurIndex; i++) { this.PatchJump(this.PopInt(), this.CurPos()); } return; } int offset = this.PopInt(); this.PushInt(this.CurPos()); this.Emit(0x26, 0); this.PatchJump(offset, this.CurPos()); return; } case 0x9a: case 0x9b: { int jumpDest = this.CurPos(); int num7 = nodetype - 0x9a; if ((node._n >= 0x7fffffff) && (node._m <= 1)) { this.Emit(0x18 + num7, this.PopInt()); } else { this.Emit(0x1c + num7, this.PopInt(), (node._n == 0x7fffffff) ? 0x7fffffff : (node._n - node._m)); } if (node._m == 0) { this.PatchJump(this.PopInt(), jumpDest); } return; } case 0x9c: this.Emit(0x20, this.MapCapnum(node._m), this.MapCapnum(node._n)); return; case 0x9e: this.Emit(0x21); this.Emit(0x24); return; case 0x9f: this.Emit(0x23); this.PatchJump(this.PopInt(), this.CurPos()); this.Emit(0x24); return; case 160: this.Emit(0x24); return; case 0xa1: switch (CurIndex) { case 0: { int num4 = this.PopInt(); this.PushInt(this.CurPos()); this.Emit(0x26, 0); this.PatchJump(num4, this.CurPos()); this.Emit(0x24); if (node._children.Count > 1) { return; } goto Label_025E; } } return; case 0xa2: switch (CurIndex) { case 0: this.Emit(0x21); this.Emit(0x24); return; case 1: { int num5 = this.PopInt(); this.PushInt(this.CurPos()); this.Emit(0x26, 0); this.PatchJump(num5, this.CurPos()); this.Emit(0x21); this.Emit(0x24); if (node._children.Count > 2) { return; } goto Label_0312; } case 2: goto Label_0312; } return; default: throw this.MakeException(SR.GetString("UnexpectedOpcode", new object[] { nodetype.ToString(CultureInfo.CurrentCulture) })); } Label_025E: this.PatchJump(this.PopInt(), this.CurPos()); return; Label_0312: this.PatchJump(this.PopInt(), this.CurPos()); }