internal Transition(TransitionRegexKind kind, int leaf = 0, S?test = default(S), SymbolicRegexNode <S>?look = null, Transition?first = null, Transition?second = null) { _kind = kind; _leaf = leaf; _test = test; _look = look; _first = first; _second = second; }
internal SymbolicRegexNode <S> MkDerivative_StartOfLine(SymbolicRegexNode <S> sr) { if (sr.IsStartOfLineAnchor) { return(this.epsilon); } else if (sr.IsAnchor) { return(this.nothing); } else if (!sr.containsAnchors) { return(sr); } else { switch (sr.kind) { case SymbolicRegexKind.Concat: { #region d(a, AB) = d(a,A)B | (if A nullable then d(a,B)) var deriv = this.MkDerivative_StartOfLine(sr.left); if (deriv == sr.left && !deriv.isNullable) { return(sr); } else { var first = this.MkConcat(deriv, sr.right); if (sr.left.IsNullable) { var second = this.MkDerivative_StartOfLine(sr.right); var or = this.MkOr2(first, second); return(or); } else { return(first); } } #endregion } case SymbolicRegexKind.Loop: { //TBD:... #region d(a, R*) = d(a,R)R* var step = MkDerivative_StartOfLine(sr.left); if (step == sr.left) { return(sr); } else if (step == this.nothing) { if (sr.isNullable) { return(this.epsilon); } else { return(this.nothing); } } else { int newupper = (sr.upper == int.MaxValue ? int.MaxValue : sr.upper - 1); int newlower = (sr.lower == 0 ? 0 : sr.lower - 1); var rest = this.MkLoop(sr.left, sr.isLazyLoop, newlower, newupper); var deriv = this.MkConcat(step, rest); return(deriv); } #endregion } case SymbolicRegexKind.Or: { #region d(a,A|B) = d(a,A)|d(a,B) var alts_deriv = sr.alts.MkDerivative_StartOfLine(); return(this.MkOr(alts_deriv)); #endregion } case SymbolicRegexKind.And: { #region d(a,A & B) = d(a,A) & d(a,B) var derivs = sr.alts.MkDerivative_StartOfLine(); return(this.MkAnd(derivs)); #endregion } default: //ITE { #region d(a,Ite(A,B,C)) = Ite(d(a,A),d(a,B),d(a,C)) var condD = this.MkDerivative_StartOfLine(sr.iteCond); if (condD == this.nothing) { var rightD = this.MkDerivative_StartOfLine(sr.right); return(rightD); } else if (condD == this.dotStar) { var leftD = this.MkDerivative_StartOfLine(sr.left); return(leftD); } else { var leftD = this.MkDerivative_StartOfLine(sr.left); var rightD = this.MkDerivative_StartOfLine(sr.right); var ite = this.MkIfThenElse(condD, leftD, rightD); return(ite); } #endregion } } } }
internal SymbolicRegexNode <S> NormalizeGeneralLoops(SymbolicRegexNode <S> sr) { switch (sr.kind) { case SymbolicRegexKind.StartAnchor: case SymbolicRegexKind.EndAnchor: case SymbolicRegexKind.Epsilon: case SymbolicRegexKind.Singleton: case SymbolicRegexKind.WatchDog: //case SymbolicRegexKind.Sequence: return(sr); case SymbolicRegexKind.Loop: { if (sr.IsStar) { return(sr); } else if (sr.IsMaybe) { return(MkOr2(sr.left, this.epsilon)); } else if (sr.IsPlus) { var star = this.MkLoop(sr.left, sr.isLazyLoop); var plus = this.MkConcat(sr.left, star); return(plus); } else if (sr.upper == int.MaxValue) { var fixed_loop = this.MkLoop(sr.left, false, sr.lower, sr.lower); var star = this.MkLoop(sr.left, sr.isLazyLoop); var concat = this.MkConcat(fixed_loop, star); return(concat); } else { return(sr); } } case SymbolicRegexKind.Concat: { var left = NormalizeGeneralLoops(sr.left); var right = NormalizeGeneralLoops(sr.right); var concat = this.MkConcat(left, right); return(concat); } case SymbolicRegexKind.Or: { var alts = new List <SymbolicRegexNode <S> >(); foreach (var elem in sr.alts) { alts.Add(NormalizeGeneralLoops(elem)); } var or = this.MkOr(alts.ToArray()); return(or); } default: throw new NotSupportedException("Normalize not supported for " + sr.kind); } }
/// <summary> /// Goes over the symbolic regex, removes anchors, adds .* if anchors were not present. /// Creates an equivalent regex with implicit start and end anchors. /// </summary> internal SymbolicRegexNode <S> RemoveAnchors(SymbolicRegexNode <S> sr, bool isBeg, bool isEnd) { switch (sr.Kind) { case SymbolicRegexKind.Concat: { #region concat var left = RemoveAnchors(sr.Left, isBeg, false); var right = RemoveAnchors(sr.Right, false, isEnd); //empty language concatenated with anything else reduces to empty language if (left == this.nothing) { return(left); } else if (right == this.nothing) { return(right); } else if (left == this.dotStar && right == this.dotStar) { //.*.* simplifies to .* return(left); } else if (left.Kind == SymbolicRegexKind.Epsilon) { //()r simplifies to r return(right); } else if (right.Kind == SymbolicRegexKind.Epsilon) { //l() simplifies to l return(left); } else if (left == sr.Left && right == sr.Right) { //there was no change return(sr); } else { return(this.MkConcat(left, right)); } #endregion } case SymbolicRegexKind.Epsilon: { #region epsilon if (isBeg || isEnd) { //this is the start or the end but there is no anchor so return .* return(this.dotStar); } else { //just return () return(sr); } #endregion } case SymbolicRegexKind.IfThenElse: { #region ite var left = RemoveAnchors(sr.Left, isBeg, isEnd); var right = RemoveAnchors(sr.Right, isBeg, isEnd); var cond = RemoveAnchors(sr.IteCond, isBeg, isEnd); if (left == sr.Left && right == sr.Right && sr.IteCond == cond) { return(sr); } else { return(this.MkIfThenElse(cond, left, right)); } #endregion } case SymbolicRegexKind.Loop: { #region loop //this call only verifies absense of start and end anchors inside the loop body (Left) //because any anchor causes an exception RemoveAnchors(sr.Left, false, false); var loop = sr; if (loop == this.dotStar) { return(loop); } if (isEnd) { loop = MkConcat(loop, this.dotStar); } if (isBeg) { loop = MkConcat(this.dotStar, loop); } return(loop); #endregion } case SymbolicRegexKind.Or: { #region or var choices = sr.alts.RemoveAnchors(isBeg, isEnd); return(this.MkOr(choices)); #endregion } case SymbolicRegexKind.And: { #region and var conjuncts = sr.alts.RemoveAnchors(isBeg, isEnd); return(this.MkAnd(conjuncts)); #endregion } case SymbolicRegexKind.StartAnchor: { #region anchor ^ if (isBeg) //^ at the beginning { if (isEnd) //^ also at the end { return(this.dotStar); } else { if (sr.IsStartOfLineAnchor) { return(this.newLine); } else { return(this.epsilon); } } } else { //treat the anchor as a regex that accepts nothing return(this.nothing); } #endregion } case SymbolicRegexKind.EndAnchor: { #region anchor $ if (isEnd) //$ at the end { if (isBeg) //$ also at the beginning { return(this.dotStar); } else { if (sr.IsEndOfLineAnchor) { return(this.newLine); } else { return(this.epsilon); } } } else { //treat the anchor as regex that accepts nothing return(this.nothing); } #endregion } case SymbolicRegexKind.Singleton: { #region singleton var res = sr; if (isEnd) { //add .* at the end res = this.MkConcat(res, this.dotStar); } if (isBeg) { //add .* at the beginning res = this.MkConcat(this.dotStar, res); } return(res); #endregion } case SymbolicRegexKind.WatchDog: { return(sr); } default: { throw new AutomataException(AutomataExceptionKind.UnrecognizedRegex); } } }
internal SymbolicRegexNode <S> MkDerivative(S elem, SymbolicRegexNode <S> sr) { if (sr == this.dotStar) { return(this.dotStar); } else if (sr == this.nothing) { return(this.nothing); } else { switch (sr.kind) { case SymbolicRegexKind.StartAnchor: case SymbolicRegexKind.EndAnchor: case SymbolicRegexKind.Epsilon: case SymbolicRegexKind.WatchDog: { return(this.nothing); } case SymbolicRegexKind.Singleton: { #region d(a,R) = epsilon if (a in R) else nothing if (this.solver.IsSatisfiable(this.solver.MkAnd(elem, sr.set))) { return(this.epsilon); } else { return(this.nothing); } #endregion } case SymbolicRegexKind.Loop: { #region d(a, R*) = d(a,R)R* var step = MkDerivative(elem, sr.left); if (step == this.nothing) { return(this.nothing); } if (sr.IsStar) { var deriv = this.MkConcat(step, sr); return(deriv); } else if (sr.IsPlus) { var star = this.MkLoop(sr.left, sr.isLazyLoop); var deriv = this.MkConcat(step, star); return(deriv); } else if (sr.IsMaybe) { return(step); } else { //also decrement the upper bound if it was not maximum int //there cannot be a case when upper == lower == 1 //such a loop is never created by MkLoop it will just return the first argument //and case upper == 1, lower == 0 is the previous case //so upper > 1 holds here int newupper = (sr.upper == int.MaxValue ? int.MaxValue : sr.upper - 1); int newlower = (sr.lower == 0 ? 0 : sr.lower - 1); var rest = this.MkLoop(sr.left, sr.isLazyLoop, newlower, newupper); var deriv = this.MkConcat(step, rest); return(deriv); } #endregion } case SymbolicRegexKind.Concat: { #region d(a, AB) = d(a,A)B | (if A nullable then d(a,B)) var first = this.MkConcat(this.MkDerivative(elem, sr.left), sr.right); if (sr.left.IsNullable) { var second = this.MkDerivative(elem, sr.right); var deriv = this.MkOr2(first, second); return(deriv); } else { return(first); } #endregion } case SymbolicRegexKind.Or: { #region d(a,A|B) = d(a,A)|d(a,B) var alts_deriv = sr.alts.MkDerivative(elem); return(this.MkOr(alts_deriv)); #endregion } case SymbolicRegexKind.And: { #region d(a,A & B) = d(a,A) & d(a,B) var derivs = sr.alts.MkDerivative(elem); return(this.MkAnd(derivs)); #endregion } default: //ITE { #region d(a,Ite(A,B,C)) = Ite(d(a,A),d(a,B),d(a,C)) var condD = this.MkDerivative(elem, sr.iteCond); if (condD == this.nothing) { var rightD = this.MkDerivative(elem, sr.right); return(rightD); } else if (condD == this.dotStar) { var leftD = this.MkDerivative(elem, sr.left); return(leftD); } else { var leftD = this.MkDerivative(elem, sr.left); var rightD = this.MkDerivative(elem, sr.right); var ite = this.MkIfThenElse(condD, leftD, rightD); return(ite); } #endregion } } } }
/// <summary> /// Make an if-then-else regex (?(cond)left|right) /// </summary> /// <param name="cond">condition</param> /// <param name="left">true case</param> /// <param name="right">false case</param> /// <returns></returns> public SymbolicRegexNode <S> MkIfThenElse(SymbolicRegexNode <S> cond, SymbolicRegexNode <S> left, SymbolicRegexNode <S> right) { return(this.srBuilder.MkIfThenElse(cond, left, right)); }
/// <summary> /// Make an if-then-else regex (?(cond)left|right), /// or create it as conjuction if right is false /// </summary> /// <param name="cond">condition</param> /// <param name="left">true case</param> /// <param name="right">false case</param> /// <returns></returns> public SymbolicRegexNode <S> MkIfThenElse(SymbolicRegexNode <S> cond, SymbolicRegexNode <S> left, SymbolicRegexNode <S> right) { return(SymbolicRegexNode <S> .MkIfThenElse(this, cond, left, right)); }
bool IsCountingLoop(SymbolicRegexNode <S> node) { return(!node.IsMaybe && !node.IsStar && !node.IsPlus); }
internal SymbolicRegexNode <S> Parse(string s, int i, out int i_next) { switch (s[i]) { case '.': { #region . i_next = i + 1; return(this.dot); #endregion } case '[': { #region parse singleton int j = s.IndexOf(']', i); var p = solver.DeserializePredicate(s.Substring(i + 1, j - (i + 1))); var node = this.MkSingleton(p); //SymbolicRegexNode<S> node; //var seq_str = s.Substring(i + 1, j - (i + 1)); //var preds_str = seq_str.Split(';'); //var preds = Array.ConvertAll(preds_str, solver.DeserializePredicate); //node = this.MkSequence(preds); i_next = j + 1; return(node); #endregion } case 'E': { #region Epsilon i_next = i + 1; return(this.epsilon); #endregion } case 'L': //L(l,u,body) for body{l,u} u may be * { #region Loop int j = s.IndexOf(',', i + 2); int lower = int.Parse(s.Substring(i + 2, j - (i + 2))); int upper = int.MaxValue; if (s[j + 1] == '*') { j = j + 3; } else { int k = s.IndexOf(',', j + 1); upper = int.Parse(s.Substring(j + 1, k - (j + 1))); j = k + 1; } int n; var body = Parse(s, j, out n); var node = SymbolicRegexNode <S> .MkLoop(this, body, lower, upper, false); i_next = n + 1; return(node); #endregion } case 'Z': //Z(l,u,body) for body{l,u}? u may be * { #region Loop int j = s.IndexOf(',', i + 2); int lower = int.Parse(s.Substring(i + 2, j - (i + 2))); int upper = int.MaxValue; if (s[j + 1] == '*') { j = j + 3; } else { int k = s.IndexOf(',', j + 1); upper = int.Parse(s.Substring(j + 1, k - (j + 1))); j = k + 1; } int n; var body = Parse(s, j, out n); var node = SymbolicRegexNode <S> .MkLoop(this, body, lower, upper, true); i_next = n + 1; return(node); #endregion } case 'S': { #region concatenation int n; SymbolicRegexNode <S>[] nodes = ParseSequence(s, i + 2, out n); var concat = this.MkConcat(nodes, false); i_next = n; return(concat); #endregion } case 'C': //conjunction C(R1,R2,...,Rk) { #region conjunction int n; SymbolicRegexNode <S>[] nodes = ParseSequence(s, i + 2, out n); var conj = SymbolicRegexNode <S> .MkAnd(this, nodes); i_next = n; return(conj); #endregion } case 'D': //Disjunction D(R1,R2,...,Rk) { #region disjunction int n; SymbolicRegexNode <S>[] nodes = ParseSequence(s, i + 2, out n); var disj = SymbolicRegexNode <S> .MkOr(this, nodes); i_next = n; return(disj); #endregion } case 'I': //if then else I(x,y,z) { #region ITE int n; var cond = Parse(s, i + 2, out n); int m; var first = Parse(s, n + 1, out m); int k; var second = Parse(s, m + 1, out k); var ite = SymbolicRegexNode <S> .MkIfThenElse(this, cond, first, second); i_next = k + 1; return(ite); #endregion } case '^': { #region start anchor i_next = i + 1; return(this.startAnchor); #endregion } case '$': { #region end anchor i_next = i + 1; return(this.endAnchor); #endregion } case '#': { #region end of sequence anchor int j = s.IndexOf(')', i + 2); int length = int.Parse(s.Substring(i + 2, j - (i + 2))); i_next = j + 1; return(SymbolicRegexNode <S> .MkWatchDog(this, length)); #endregion } default: throw new NotImplementedException(); } }
private static TransitionRegex <S> GetOrCreate(SymbolicRegexBuilder <S> builder, TransitionRegexKind kind, S?test, TransitionRegex <S>?one, TransitionRegex <S>?two, SymbolicRegexNode <S>?node, DerivativeEffect?effect = null) { // Keep transition regexes internalized using the builder ref TransitionRegex <S>?tr = ref CollectionsMarshal.GetValueRefOrAddDefault(builder._trCache, (kind, test, one, two, node, effect), out _);
internal MatchingState(SymbolicRegexNode <TSet> node, uint prevCharKind) { Node = node; PrevCharKind = prevCharKind; }
private TransitionRegex(SymbolicRegexBuilder <S> builder, TransitionRegexKind kind, S?test, TransitionRegex <S>?first, TransitionRegex <S>?second, SymbolicRegexNode <S>?node, DerivativeEffect?effect) { Debug.Assert(builder is not null); Debug.Assert( kind is TransitionRegexKind.Leaf && node is not null && Equals(test, default(S)) && first is null && second is null && effect is null || kind is TransitionRegexKind.Conditional && test is not null && first is not null && second is not null && node is null && effect is null || kind is TransitionRegexKind.Union && Equals(test, default(S)) && first is not null && second is not null && node is null && effect is null || kind is TransitionRegexKind.Lookaround && Equals(test, default(S)) && first is not null && second is not null && node is not null && effect is null || kind is TransitionRegexKind.Effect && Equals(test, default(S)) && first is not null && second is null && node is null && effect is not null); _builder = builder; _kind = kind; _test = test; _first = first; _second = second; _node = node; _effect = effect; }
/// <summary>Generates up to k random strings accepted by the regex</summary> public IEnumerable <string> GenerateRandomMembers(int k) { ICharAlgebra <BDD> bddSolver = SymbolicRegexRunner.s_unicode._solver; for (int i = 0; i < k; i++) { // Holds the generated input so far StringBuilder input_so_far = new(); // Initially there is no previous character // Here one could also consider previous characters for example for \b, \B, and ^ anchors // and initialize input_so_far accordingly uint prevCharKind = CharKind.StartStop; // This flag is set to false in the unlikely situation that generation ends up in a dead-end bool generationSucceeded = true; // Current set of states reached initially contains just the root List <SymbolicRegexNode <S> > states = new(); states.Add(_root); // Used for end suffixes List <string> possible_endings = new(); List <SymbolicRegexNode <S> > nextStates = new(); while (true) { Debug.Assert(states.Count > 0); if (CanBeFinal(states)) { // Unconditionally final state or end of the input due to \Z anchor for example if (IsFinal(states) || IsFinal(states, CharKind.Context(prevCharKind, CharKind.StartStop))) { possible_endings.Add(""); } // End of line due to end-of-line anchor if (IsFinal(states, CharKind.Context(prevCharKind, CharKind.Newline))) { possible_endings.Add("\n"); } // Related to wordborder due to \b or \B if (IsFinal(states, CharKind.Context(prevCharKind, CharKind.WordLetter))) { possible_endings.Add(ChooseChar(_asciiWordCharacters).ToString()); } // Related to wordborder due to \b or \B if (IsFinal(states, CharKind.Context(prevCharKind, CharKind.General))) { possible_endings.Add(ChooseChar(_asciiNonWordCharacters).ToString()); } } // Choose to stop here based on a coin-toss if (possible_endings.Count > 0 && ChooseRandomlyTrueOrFalse()) { //Choose some suffix that allows some anchor (if any) to be nullable input_so_far.Append(Choose(possible_endings)); break; } SymbolicRegexNode <S> state = Choose(states); char c = '\0'; uint cKind = 0; // Observe that state.MkDerivative() can be a deadend List <(S, SymbolicRegexNode <S>?, SymbolicRegexNode <S>)> paths = new(state.MkDerivative().EnumeratePaths(_solver.True)); if (paths.Count > 0) { (S, SymbolicRegexNode <S>?, SymbolicRegexNode <S>)path = Choose(paths); // Consider a random path from some random state in states and // select a random member of the predicate on that path c = ChooseChar(ToBDD(path.Item1)); // Map the character back into the corresponding character constraint of the solver S c_pred = _solver.CharConstraint(c); // Determine the character kind of c cKind = IsNewline(c_pred) ? CharKind.Newline : (IsWordchar(c_pred) ? CharKind.WordLetter : CharKind.General); // Construct the combined context of previous and c kind uint context = CharKind.Context(prevCharKind, cKind); // Step into the next set of states nextStates.AddRange(Step(states, c_pred, context)); } // In the case that there are no next states: stop here if (nextStates.Count == 0) { if (possible_endings.Count > 0) { input_so_far.Append(Choose(possible_endings)); } else { // Ending up here is unlikely but possible for example for infeasible patterns such as @"no\bway" // or due to poor choice of c -- no anchor is enabled -- so this is a deadend generationSucceeded = false; } break; } input_so_far.Append(c); states.Clear(); possible_endings.Clear(); List <SymbolicRegexNode <S> > tmp = states; states = nextStates; nextStates = tmp; prevCharKind = cKind; } if (generationSucceeded) { yield return(input_so_far.ToString()); } } }
public SymbolicRegexNode <S> MkLoop(SymbolicRegexNode <S> regex, int lower = 0, int upper = int.MaxValue, bool isLazy = false) { return(this.srBuilder.MkLoop(regex, isLazy, lower, upper)); }
string GenerateRandomMember(SymbolicRegexBuilder <S> builder, SymbolicRegexNode <S> root) { // TODO: ITE, And: are currently not supported. string sample = ""; Stack <SymbolicRegexNode <S> > nodeQueue = new Stack <SymbolicRegexNode <S> >(); SymbolicRegexNode <S> curNode = null; nodeQueue.Push(UnrollRE(root)); while (nodeQueue.Count > 0 || curNode != null) { if (curNode == null) { curNode = nodeQueue.Pop(); } switch (curNode.Kind) { case SymbolicRegexKind.Singleton: if (!builder.solver.IsSatisfiable(curNode.Set)) { throw new AutomataException(AutomataExceptionKind.SetIsEmpty); } sample += builder.solver.ChooseUniformly(curNode.Set); curNode = null; break; case SymbolicRegexKind.Loop: curNode = curNode.Left; break; case SymbolicRegexKind.Epsilon: curNode = null; break; case SymbolicRegexKind.Concat: nodeQueue.Push(curNode.Right); curNode = curNode.Left; break; case SymbolicRegexKind.Or: int choice = rand.Next(curNode.OrCount); int i = 0; foreach (var elem in curNode.alts) { if (i == choice) { curNode = elem; break; } else { i += 1; } } break; case SymbolicRegexKind.EndAnchor: case SymbolicRegexKind.StartAnchor: curNode = null; break; default: throw new NotImplementedException(curNode.Kind.ToString()); } } return(sample); }
/// <summary> /// Make end of sequence marker /// </summary> internal SymbolicRegexNode <S> MkWatchDog(int length) { return(SymbolicRegexNode <S> .MkWatchDog(this, length)); }
/// <summary>Constructs matcher for given symbolic regex.</summary> internal SymbolicRegexMatcher(SymbolicRegexNode <TSetType> sr, RegexCode code, CharSetSolver css, BDD[] minterms, TimeSpan matchTimeout, CultureInfo culture) { Debug.Assert(sr._builder._solver is BV64Algebra or BVAlgebra or CharSetSolver, $"Unsupported algebra: {sr._builder._solver}"); _pattern = sr; _builder = sr._builder; _checkTimeout = Regex.InfiniteMatchTimeout != matchTimeout; _timeout = (int)(matchTimeout.TotalMilliseconds + 0.5); // Round up, so it will be at least 1ms _partitions = _builder._solver switch { BV64Algebra bv64 => bv64._classifier, BVAlgebra bv => bv._classifier, _ => new MintermClassifier((CharSetSolver)(object)_builder._solver, minterms), }; if (code.FindOptimizations.FindMode != FindNextStartingPositionMode.NoSearch && code.FindOptimizations.LeadingAnchor == 0) // If there are any anchors, we're better off letting the DFA quickly do its job of determining whether there's a match. { _findOpts = code.FindOptimizations; } // Determine the number of initial states. If there's no anchor, only the default previous // character kind 0 is ever going to be used for all initial states. int statesCount = _pattern._info.ContainsSomeAnchor ? CharKind.CharKindCount : 1; // Create the initial states for the original pattern. var initialStates = new DfaMatchingState <TSetType> [statesCount]; for (uint i = 0; i < initialStates.Length; i++) { initialStates[i] = _builder.MkState(_pattern, i); } _initialStates = initialStates; // Create the dot-star pattern (a concatenation of any* with the original pattern) // and all of its initial states. _dotStarredPattern = _builder.MkConcat(_builder._anyStar, _pattern); var dotstarredInitialStates = new DfaMatchingState <TSetType> [statesCount]; for (uint i = 0; i < dotstarredInitialStates.Length; i++) { // Used to detect if initial state was reentered, // but observe that the behavior from the state may ultimately depend on the previous // input char e.g. possibly causing nullability of \b or \B or of a start-of-line anchor, // in that sense there can be several "versions" (not more than StateCount) of the initial state. DfaMatchingState <TSetType> state = _builder.MkState(_dotStarredPattern, i); state.IsInitialState = true; dotstarredInitialStates[i] = state; } _dotstarredInitialStates = dotstarredInitialStates; // Create the reverse pattern (the original pattern in reverse order) and all of its // initial states. _reversePattern = _pattern.Reverse(); var reverseInitialStates = new DfaMatchingState <TSetType> [statesCount]; for (uint i = 0; i < reverseInitialStates.Length; i++) { reverseInitialStates[i] = _builder.MkState(_reversePattern, i); } _reverseInitialStates = reverseInitialStates; // Initialize our fast-lookup for determining the character kind of ASCII characters. // This is only required when the pattern contains anchors, as otherwise there's only // ever a single kind used. if (_pattern._info.ContainsSomeAnchor) { var asciiCharKinds = new uint[128]; for (int i = 0; i < asciiCharKinds.Length; i++) { TSetType predicate2; uint charKind; if (i == '\n') { predicate2 = _builder._newLinePredicate; charKind = CharKind.Newline; } else { predicate2 = _builder._wordLetterPredicateForAnchors; charKind = CharKind.WordLetter; } asciiCharKinds[i] = _builder._solver.And(GetMinterm(i), predicate2).Equals(_builder._solver.False) ? 0 : charKind; } _asciiCharKinds = asciiCharKinds; } }
public ConditionalDerivative(Sequence <CounterOperation> condition, SymbolicRegexNode <S> derivative) : base(condition, derivative) { }