示例#1
0
 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
                }
                }
            }
        }
示例#6
0
 /// <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();
            }
        }
示例#10
0
 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 _);
示例#11
0
 internal MatchingState(SymbolicRegexNode <TSet> node, uint prevCharKind)
 {
     Node         = node;
     PrevCharKind = prevCharKind;
 }
示例#12
0
        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;
        }
示例#13
0
        /// <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());
                }
            }
        }
示例#14
0
 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));
 }
示例#15
0
        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);
        }
示例#16
0
 /// <summary>
 /// Make end of sequence marker
 /// </summary>
 internal SymbolicRegexNode <S> MkWatchDog(int length)
 {
     return(SymbolicRegexNode <S> .MkWatchDog(this, length));
 }
示例#17
0
        /// <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;
            }
        }
示例#18
0
 public ConditionalDerivative(Sequence <CounterOperation> condition, SymbolicRegexNode <S> derivative)
     : base(condition, derivative)
 {
 }