/// <summary> /// Compiles this regex and possibly other regexes into a common symbolic regex representing their intersection /// </summary> /// <param name="regex">this regex</param> /// <param name="regexes">more regexes to intersect with</param> /// <param name="keepAnchors">if false missing anchors are replaced by .* else just omitted</param> /// <param name="unwindLowerBounds">if true then lower bounds of loops are unwound</param> /// <returns></returns> public static RegexMatcher Compile(this Regex regex, bool keepAnchors, bool unwindLowerBounds, params Regex[] regexes) { if (context == null) { context = new CharSetSolver(); } var first = context.RegexConverter.ConvertToSymbolicRegex(regex, keepAnchors, unwindLowerBounds); var others = Array.ConvertAll(regexes, r => context.RegexConverter.ConvertToSymbolicRegex(r, keepAnchors, unwindLowerBounds)); var all = new SymbolicRegexNode <BDD> [1 + regexes.Length]; all[0] = first; for (int i = 1; i <= others.Length; i++) { all[i] = others[i - 1]; } var srBuilder = context.RegexConverter.srBuilder; var conj = srBuilder.MkAnd(all); var partition = conj.ComputeMinterms(); RegexMatcher matcher; if (partition.Length > 64) { //more than 64 bits needed to represent a set matcher = new SymbolicRegexBV(conj, context, partition); } else { //enough to use 64 bits matcher = new SymbolicRegexUInt64(conj, context, partition); } return(matcher); }
/// <summary> /// Compiles this regex and possibly other regexes into a common symbolic regex representing their intersection /// </summary> /// <param name="regex">this regex</param> /// <param name="regexes">more regexes to intersect with</param> /// <param name="keepAnchors">if false missing anchors are replaced by .* else just omitted</param> /// <param name="unwindLowerBounds">if true then lower bounds of loops are unwound</param> /// <returns></returns> public static RegexMatcher Compile(this Regex regex, bool keepAnchors, bool unwindLowerBounds, bool isMatchOnly = false, params Regex[] regexes) { //first test if this regex is a simple string, i.e., a toplevel multi-node RegexTree rt = RegexParser.Parse(regex.ToString(), regex.Options); if (regexes.Length == 0) { if (rt._root._type == RegexNode.Capture && rt._root.Child(0)._type == RegexNode.Multi) { //this is an explicit string var pattern = rt._root.Child(0)._str; return(new FixedStringMatcher(pattern, (regex.Options & RegexOptions.IgnoreCase) == RegexOptions.IgnoreCase)); } } if (context == null) { context = new CharSetSolver(); } var first = context.RegexConverter.ConvertToSymbolicRegex(rt._root, keepAnchors, unwindLowerBounds); if (!isMatchOnly && first.CheckIfContainsLazyLoop() && !first.CheckIfAllLoopsAreLazy()) { throw new AutomataException("Match generation with mixed lazy and eager loops currently not supported."); } var others = Array.ConvertAll(regexes, r => context.RegexConverter.ConvertToSymbolicRegex(r, keepAnchors, unwindLowerBounds)); var all = new SymbolicRegexNode <BDD> [1 + regexes.Length]; all[0] = first; for (int i = 1; i <= others.Length; i++) { all[i] = others[i - 1]; } var srBuilder = context.RegexConverter.srBuilder; var conj = srBuilder.MkAnd(all); var partition = conj.ComputeMinterms(); RegexMatcher matcher; if (partition.Length > 64) { //more than 64 bits needed to represent a set matcher = new SymbolicRegexBV(conj, context, partition); } else { //enough to use 64 bits matcher = new SymbolicRegexUInt64(conj, context, partition); } return(matcher); }