/// <summary> /// Generates a string based on the given regular expression /// if any nodes are prepended with \i, then one of these nodes will be chosen /// at random to be invalidated /// </summary> /// <param name="random">Random object to use for generation</param> /// <param name="regex">Regular expression used to generate the string</param> /// <returns>generated string</returns> public static string NextString(Random random, string regex) { //reset the static variables RECompiler.IsInvalidSection = false; RECompiler.InvalidNode = null; RECompiler.InvalidableNodes.Clear(); //construct the RegEx tree RECompiler compiler = new RECompiler(); RENode node = compiler.Compile(regex); //search for a signal to invalidate a node if (regex.IndexOf("\\i", StringComparison.Ordinal) != -1) { //something should have been invalidated //select a node to invalidate if (RECompiler.InvalidableNodes.Count == 0) { throw new ArgumentException("Asked to generate invalid: Impossible to invalidate"); } RECompiler.InvalidNode = RECompiler.InvalidableNodes[random.Next(RECompiler.InvalidableNodes.Count)]; //Mark REOrNodes and RERepeatNodes to ensure that the invalid node will be part of the string RECompiler.InvalidNode.ReservePath(null); } //generate and return the string string result = node.Generate(random); if (RECompiler.InvalidNode != null) { //confirm that the generated string is invalid (e.g. [a-z]|[^a-z] will always fail) Regex compare = new Regex("^" + regex.Replace("\\i", "") + "$"); if (compare.IsMatch(result)) { throw new ArgumentException(regex + ": Did not generate invalid string: " + result); } } return result; }
//Compile [:alpha:] [:punct:] etc internal RENode CompileMacro(int index, int len) { AssertParse(len >= 0, "Cannot parse macro."); string substr = mRegex.ToString().Substring(index, len); string expanded = null; switch (substr) { case "alnum": expanded = "[a-zA-Z0-9]"; break; case "alpha": expanded = "[a-zA-Z]"; break; case "upper": expanded = "[A-Z]"; break; case "lower": expanded = "[a-z]"; break; case "digit": expanded = "[0-9]"; break; case "xdigit": expanded = "[A-F0-9a-f]"; break; case "space": expanded = "[ \t]"; break; case "print": expanded = "[\\x20-\\x7F]"; break; case "punct": expanded = "[,;.!'\"]"; break; case "graph": expanded = "[\\x80-\\xFF]"; break; case "cntrl": expanded = "[]"; break; case "blank": expanded = "[ \t\r\n\f]"; break; case "guid": expanded = "[A-F0-9]{8}(-[A-F0-9]{4}){3}-[A-F0-9]{12}"; break; default: AssertParse(false, "Cannot parse macro."); break; } RECompiler subcompiler = new RECompiler(); return subcompiler.Compile(expanded); }