internal RegexInterpreter(RegexCode code, CultureInfo culture) { runcode = code; runcodes = code._codes; runstrings = code._strings; runfcPrefix = code._fcPrefix; runbmPrefix = code._bmPrefix; runanchors = code._anchors; runculture = culture; }
internal RegexInterpreter(RegexCode code, CultureInfo culture) { _runcode = code; _runcodes = code._codes; _runstrings = code._strings; _runfcPrefix = code._fcPrefix; _runbmPrefix = code._bmPrefix; _runanchors = code._anchors; _runculture = culture; }
internal RegexCode(int[] codes, List <string> stringlist, int trackcount, Hashtable caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, int anchors, bool rightToLeft) { this._codes = codes; this._strings = new string[stringlist.Count]; this._trackcount = trackcount; this._caps = caps; this._capsize = capsize; this._bmPrefix = bmPrefix; this._fcPrefix = fcPrefix; this._anchors = anchors; this._rightToLeft = rightToLeft; stringlist.CopyTo(0, this._strings, 0, stringlist.Count); }
internal RegexCode(int[] codes, ArrayList stringlist, int trackcount, System.Collections.Generic.Dictionary <object, object> caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, RegexPrefix scPrefix, int anchors, bool rightToLeft) { this._codes = codes; this._strings = new string[stringlist.Count]; this._trackcount = trackcount; this._caps = caps; this._capsize = capsize; this._bmPrefix = bmPrefix; this._fcPrefix = fcPrefix; this._scPrefix = scPrefix; this._anchors = anchors; this._rightToLeft = rightToLeft; stringlist.CopyTo(0, this._strings, 0, stringlist.Count); }
internal RegexCode(int[] codes, ArrayList stringlist, int trackcount, System.Collections.Generic.Dictionary<object,object> caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, RegexPrefix scPrefix, int anchors, bool rightToLeft) { this._codes = codes; this._strings = new string[stringlist.Count]; this._trackcount = trackcount; this._caps = caps; this._capsize = capsize; this._bmPrefix = bmPrefix; this._fcPrefix = fcPrefix; this._scPrefix = scPrefix; this._anchors = anchors; this._rightToLeft = rightToLeft; stringlist.CopyTo(0, this._strings, 0, stringlist.Count); }
internal bool _rightToLeft; // true if right to left // optimizations // constructor internal RegexCode(int [] codes, ArrayList stringlist, int trackcount, Hashtable caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, int anchors, bool rightToLeft) { _codes = codes; _strings = new String[stringlist.Count]; _trackcount = trackcount; _caps = caps; _capsize = capsize; _bmPrefix = bmPrefix; _fcPrefix = fcPrefix; _anchors = anchors; _rightToLeft = rightToLeft; stringlist.CopyTo(0, _strings, 0, stringlist.Count); }
internal bool _rightToLeft; // true if right to left // optimizations // constructor internal RegexCode(int[] codes, List <String> stringlist, int trackcount, Dictionary <Int32, Int32> caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, int anchors, bool rightToLeft) { _codes = codes; _strings = new String[stringlist.Count]; _trackcount = trackcount; _caps = caps; _capsize = capsize; _bmPrefix = bmPrefix; _fcPrefix = fcPrefix; _anchors = anchors; _rightToLeft = rightToLeft; stringlist.CopyTo(0, _strings, 0, stringlist.Count); }
internal readonly bool _rightToLeft; // true if right to left internal RegexCode(int[] codes, List <string> stringlist, int trackcount, Hashtable caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, int anchors, bool rightToLeft) { Debug.Assert(codes != null, "codes cannot be null."); Debug.Assert(stringlist != null, "stringlist cannot be null."); _codes = codes; _strings = stringlist.ToArray(); _trackcount = trackcount; _caps = caps; _capsize = capsize; _bmPrefix = bmPrefix; _fcPrefix = fcPrefix; _anchors = anchors; _rightToLeft = rightToLeft; }
public readonly bool RightToLeft; // true if right to left public RegexCode(int[] codes, List <string> stringlist, int trackcount, Hashtable caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, int anchors, bool rightToLeft) { Debug.Assert(codes != null, "codes cannot be null."); Debug.Assert(stringlist != null, "stringlist cannot be null."); Codes = codes; Strings = stringlist.ToArray(); TrackCount = trackcount; Caps = caps; CapSize = capsize; BMPrefix = bmPrefix; FCPrefix = fcPrefix; Anchors = anchors; RightToLeft = rightToLeft; }
internal RegexCode RegexCodeFromRegexTree(RegexTree tree) { int length; RegexBoyerMoore moore; if ((tree._capnumlist == null) || (tree._captop == tree._capnumlist.Length)) { length = tree._captop; this._caps = null; } else { length = tree._capnumlist.Length; this._caps = tree._caps; for (int i = 0; i < tree._capnumlist.Length; i++) { this._caps[tree._capnumlist[i]] = i; } } this._counting = true; Label_0076: if (!this._counting) { this._emitted = new int[this._count]; } RegexNode node = tree._root; int curIndex = 0; this.Emit(0x17, 0); Label_00A1: if (node._children == null) { this.EmitFragment(node._type, node, 0); } else if (curIndex < node._children.Count) { this.EmitFragment(node._type | 0x40, node, curIndex); node = (RegexNode)node._children[curIndex]; this.PushInt(curIndex); curIndex = 0; goto Label_00A1; } if (!this.EmptyStack()) { curIndex = this.PopInt(); node = node._next; this.EmitFragment(node._type | 0x80, node, curIndex); curIndex++; goto Label_00A1; } this.PatchJump(0, this.CurPos()); this.Emit(40); if (this._counting) { this._counting = false; goto Label_0076; } RegexPrefix fcPrefix = RegexFCD.FirstChars(tree); if ((fcPrefix != null) && (RegexCharClass.SetSize(fcPrefix.Prefix) > 0)) { fcPrefix = null; } RegexPrefix scPrefix = null; RegexPrefix prefix3 = RegexFCD.Prefix(tree); bool rightToLeft = (tree._options & RegexOptions.RightToLeft) != RegexOptions.None; CultureInfo culture = ((tree._options & RegexOptions.CultureInvariant) != RegexOptions.None) ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture; if ((prefix3 != null) && (prefix3.Prefix.Length > 0)) { moore = new RegexBoyerMoore(prefix3.Prefix, prefix3.CaseInsensitive, rightToLeft, culture); } else { moore = null; } return(new RegexCode(this._emitted, this._stringtable, this._trackcount, this._caps, length, moore, fcPrefix, scPrefix, RegexFCD.Anchors(tree), rightToLeft)); }
/// <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) { // construct sparse capnum mapping if some numbers are unused int capsize; 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; } } RegexNode?curNode = tree.Root; int curChild = 0; Emit(RegexCode.Lazybranch, 0); while (true) { if (curNode.Children == null) { EmitFragment(curNode.NType, curNode, 0); } else if (curChild < curNode.Children.Count) { EmitFragment(curNode.NType | BeforeChild, curNode, curChild); curNode = curNode.Children[curChild]; _intStack.Append(curChild); curChild = 0; continue; } if (_intStack.Length == 0) { break; } curChild = _intStack.Pop(); curNode = curNode.Next; EmitFragment(curNode !.NType | AfterChild, curNode, curChild); curChild++; } PatchJump(0, _emitted.Length); 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.Prefix.Length > 0) { bmPrefix = new RegexBoyerMoore(prefix.Prefix, prefix.CaseInsensitive, rtl, culture); } else { bmPrefix = null; } int anchors = RegexFCD.Anchors(tree); int[] emitted = _emitted.AsSpan().ToArray(); return(new RegexCode(emitted, _stringTable, _trackCount, _caps, capsize, bmPrefix, fcPrefix, anchors, rtl)); }
// The top-level driver. Initializes everything then calls the Generate* methods. internal Type FactoryFromCode(RegexCode code, RegexOptions options, String typeprefix) { String runnertypename; String runnerfactoryname; Type runnertype; Type factory; _code = code; _codes = code._codes; _strings = code._strings; _fcPrefix = code._fcPrefix; _scPrefix = code._scPrefix; _bmPrefix = code._bmPrefix; _anchors = code._anchors; _trackcount = code._trackcount; _options = options; // pick a name for the class lock (_syncObject) { // Note: Class names must be unique within assemblies, not just // within modules. We append the modulename to the runner name // to make our name unique across the assembly runnertypename = typeprefix + "Runner" + _typeCount.ToString(); runnerfactoryname = typeprefix + "Factory" + _typeCount.ToString(); _typeCount++; } // Generate a RegexRunner class // (blocks are simply illustrative) DefineType(runnertypename, false, typeof(RegexRunner)); { DefineMethod("Go", null); { GenerateGo(); BakeMethod(); } DefineMethod("FindFirstChar", typeof(bool)); { GenerateFindFirstChar(); BakeMethod(); } DefineMethod("InitTrackCount", null); { GenerateInitTrackCount(); BakeMethod(); } runnertype = BakeType(); } // Generate a RegexRunnerFactory class DefineType(runnerfactoryname, false, typeof(RegexRunnerFactory)); { DefineMethod("CreateInstance", typeof(RegexRunner)); { GenerateCreateInstance(runnertype); BakeMethod(); } factory = BakeType(); } return factory; }
internal readonly bool _rightToLeft; // true if right to left internal RegexCode(int[] codes, List<String> stringlist, int trackcount, Dictionary<Int32, Int32> caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, int anchors, bool rightToLeft) { Debug.Assert(codes != null, "codes cannot be null."); Debug.Assert(stringlist != null, "stringlist cannot be null."); _codes = codes; _strings = new String[stringlist.Count]; _trackcount = trackcount; _caps = caps; _capsize = capsize; _bmPrefix = bmPrefix; _fcPrefix = fcPrefix; _anchors = anchors; _rightToLeft = rightToLeft; stringlist.CopyTo(0, _strings, 0, stringlist.Count); }
internal readonly int _trackcount; // how many instructions use backtracking #endregion Fields #region Constructors internal RegexCode(int[] codes, List<string> stringlist, int trackcount, Hashtable caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, int anchors, bool rightToLeft) { Debug.Assert(codes != null, "codes cannot be null."); Debug.Assert(stringlist != null, "stringlist cannot be null."); _codes = codes; _strings = stringlist.ToArray(); _trackcount = trackcount; _caps = caps; _capsize = capsize; _bmPrefix = bmPrefix; _fcPrefix = fcPrefix; _anchors = anchors; _rightToLeft = rightToLeft; }
/// <summary> /// The top level RegexCode generator. It does a depth-first walk /// through the tree and calls EmitFragment to emit code before /// and after each child of an interior node and at each leaf. /// It also computes various information about the tree, such as /// prefix data to help with optimizations. /// </summary> public RegexCode RegexCodeFromRegexTree(RegexTree tree) { // Construct sparse capnum mapping if some numbers are unused. int capsize; 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; } } // Every written code begins with a lazy branch. This will be back-patched // to point to the ending Stop after the whole expression has been written. Emit(RegexCode.Lazybranch, 0); // Emit every node. RegexNode curNode = tree.Root; int curChild = 0; while (true) { int curNodeChildCount = curNode.ChildCount(); if (curNodeChildCount == 0) { EmitFragment(curNode.Type, curNode, 0); } else if (curChild < curNodeChildCount) { EmitFragment(curNode.Type | BeforeChild, curNode, curChild); curNode = curNode.Child(curChild); _intStack.Append(curChild); curChild = 0; continue; } if (_intStack.Length == 0) { break; } curChild = _intStack.Pop(); curNode = curNode.Next !; EmitFragment(curNode.Type | AfterChild, curNode, curChild); curChild++; } // Patch the starting Lazybranch, emit the final Stop, and get the resulting code array. PatchJump(0, _emitted.Length); Emit(RegexCode.Stop); int[] emitted = _emitted.AsSpan().ToArray(); bool rtl = (tree.Options & RegexOptions.RightToLeft) != 0; // Compute prefixes to help optimize FindFirstChar. RegexBoyerMoore?bmPrefix = null; RegexPrefix? fcPrefix = null; RegexPrefix prefix = RegexFCD.Prefix(tree); if (prefix.Prefix.Length > 1 && prefix.Prefix.Length <= RegexBoyerMoore.MaxLimit) // if it's <= 1 || > MaxLimit, perf is better using fcPrefix { // Compute a Boyer-Moore prefix if we find a single string of sufficient length that always begins the expression. CultureInfo culture = (tree.Options & RegexOptions.CultureInvariant) != 0 ? CultureInfo.InvariantCulture : CultureInfo.CurrentCulture; bmPrefix = new RegexBoyerMoore(prefix.Prefix, prefix.CaseInsensitive, rtl, culture); } else { // If we didn't find such a string, try to compute the characters set that might begin the string. fcPrefix = RegexFCD.FirstChars(tree); } // Compute any anchors starting the expression. int anchors = RegexFCD.Anchors(tree); // Convert the string table into an ordered string array/ var strings = new string[_stringTable.Count]; foreach (KeyValuePair <string, int> stringEntry in _stringTable) { strings[stringEntry.Value] = stringEntry.Key; } // Return all that in a RegexCode object. return(new RegexCode(tree, emitted, strings, _trackCount, _caps, capsize, bmPrefix, fcPrefix, anchors, rtl)); }
/// <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)); }
internal bool _rightToLeft; // true if right to left // optimizations // constructor internal RegexCode(int [] codes, ArrayList stringlist, int trackcount, Hashtable caps, int capsize, RegexBoyerMoore bmPrefix, RegexPrefix fcPrefix, RegexPrefix scPrefix, int anchors, bool rightToLeft) { _codes = codes; _strings = new String[stringlist.Count]; _trackcount = trackcount; _caps = caps; _capsize = capsize; _bmPrefix = bmPrefix; _fcPrefix = fcPrefix; _scPrefix = scPrefix; _anchors = anchors; _rightToLeft = rightToLeft; stringlist.CopyTo(0, _strings, 0, stringlist.Count); }