public MFTestResults RegExpTest_0_PrecompiledMatch() { bool testResult = false; try { Log.Comment("Pre-compiled regular expression \"a*b\""); char[] re1instructions = { (char)0x007c, (char)0x0000, (char)0x001a, (char)0x007c, (char)0x0000, (char)0x000d, (char)0x0041, (char)0x0001, (char)0x0004, (char)0x0061, (char)0x007c, (char)0x0000, (char)0x0003, (char)0x0047, (char)0x0000, (char)0xfff6, (char)0x007c, (char)0x0000, (char)0x0003, (char)0x004e, (char)0x0000, (char)0x0003, (char)0x0041, (char)0x0001, (char)0x0004, (char)0x0062, (char)0x0045, (char)0x0000, (char)0x0000, }; //need to make internals visible to RegexProgram re1 = new RegexProgram(re1instructions); // Simple test of pre-compiled regular expressions Regex r = new Regex(re1); Log.Comment("Matching Precompiled Expression a*b"); testResult = r.IsMatch("aaab"); Log.Comment("aaab = " + testResult); TestTestsHelper.ShowParens(ref r); if (!testResult) { Log.Comment("\"aaab\" doesn't match to precompiled \"a*b\""); } testResult = r.IsMatch("b"); Log.Comment("b = " + testResult); TestTestsHelper.ShowParens(ref r); if (!testResult) { Log.Comment("\"b\" doesn't match to precompiled \"a*b\""); } testResult = r.IsMatch("c"); Log.Comment("c = " + testResult); TestTestsHelper.ShowParens(ref r); if (testResult) { Log.Comment("\"c\" matches to precompiled \"a*b\""); testResult = false; } testResult = r.IsMatch("ccccaaaaab"); Log.Comment("ccccaaaaab = " + testResult); TestTestsHelper.ShowParens(ref r); if (!testResult) { Log.Comment("\"ccccaaaaab\" doesn't match to precompiled \"a*b\""); } } catch (Exception ex) { Log.Exception("Unexpected Exception", ex); testResult = false; } return (testResult ? MFTestResults.Pass : MFTestResults.Fail); }
/// <summary> /// Compiles a regular expression pattern into a program runnable by the pattern matcher class 'RE'. /// </summary> /// <param name="pattern">Regular expression pattern to compile</param> /// <returns></returns> internal RegexProgram Compile(String pattern) { //Check if the pattersn is already compiled if (Regex.CacheSize > 0 && Regex.Cache.Contains(pattern)) { foreach (RegexProgram regexProgram in Regex.Cache.ToArray()) if (regexProgram.Pattern.Equals(pattern)) return regexProgram; throw new Exception("Cache Error RegexCompiler.cs Compile Method"); } else { //Maintain CacheSize Requirement if (Regex.CacheSize > 0 && Regex.Cache.Count >= Regex.CacheSize) Regex.Cache.Pop(); // Initialize variables for compilation this.pattern = pattern; // Save pattern in instance variable len = pattern.Length; // Precompute pattern Length for speed idx = 0; // Set parsing index to the first character lenInstruction = 0; // Set emitted instruction count to zero parens = 1; // Set paren level to 1 (the implicit outer parens) // Initialize pass by reference flags value int[] flags = { NODE_TOPLEVEL }; // Parse expression Expression(flags); // Should be at end of input if (idx != len) { if (pattern[idx] == OpCode.Close) SyntaxError("Unmatched close paren"); SyntaxError("Unexpected input remains"); } //Compile the result char[] ins = new char[lenInstruction]; System.Array.Copy(instruction, 0, ins, 0, lenInstruction); //ins.CopyTo(instruction, 0); RegexProgram result = new RegexProgram(parens, ins, pattern); //If caching is enabled add the pattern to the cache //Should probably check for the Compiled Flag before putting it in if (Regex.CacheSize > 0 && ! Regex.Cache.Contains(pattern)) { Regex.Cache.Push(result); } return result; } }
/// <summary> /// Internal use only. /// Construct a matcher for a pre-compiled regular expression from program /// (bytecode) data. Internal use only /// </summary> /// <param name="program">Compiled regular expression program</param> internal Regex(RegexProgram program) : this(program, RegexOptions.None) { }
/// <summary> /// Main application entrypoint. /// Might make this have methods and be a class rathern the a program... /// Then the class can Serialise and Deserialiaze the Regexps /// </summary> /// <param name="arg">Command line arguments</param> static public void Main(String[] arg) { // Create a compiler object RegexCompiler r = new RegexCompiler(); // Print usage if arguments are incorrect if (arg.Length <= 0 || arg.Length % 2 != 0) { Debug.Print("Usage: recompile <patternname> <pattern>"); return; } // Loop through arguments, compiling each for (int i = 0, end = arg.Length; i < end; i += 2) { try { // Compile regular expression String name = arg[i]; String pattern = arg[i + 1]; String instructions = name + "Instructions"; // Output program as a nice, formatted char array Debug.Print("\n // Pre-compiled regular expression '" + pattern + "'\n" + " private static char[] " + instructions + " = \n {"); // Compile program for pattern RegexProgram program = r.Compile(pattern); // Number of columns in output int numColumns = 7; // Loop through program char[] p = program.Instructions; for (int j = 0; j < p.Length; j++) { // End of column? if ((j % numColumns) == 0) { Debug.Print("\n "); } // Print char as padded hex number String hex = (0).ToHexString(); while (hex.Length < 4) { hex = "0" + hex; } Debug.Print("0x" + hex + ", "); } // End of program block Debug.Print("\n };"); Debug.Print("\n private static REProgram " + name + " = new REProgram(" + instructions + ");"); } catch (RegexpSyntaxException e) { Debug.Print("Syntax error in expression \"" + arg[i] + "\": " + e.ToString()); } catch (Exception e) { Debug.Print("Unexpected exception: " + e.ToString()); } } }
/// <summary> /// Internal use only. /// Construct a matcher for a pre-compiled regular expression from program /// bytecode) data. Permits special flags to be passed in to modify matching /// behaviour. /// RegexOptions.Normal // Normal (case-sensitive) matching /// RegexOptions.CaseIndependant // Case folded comparisons /// RegexOptions.Multiline // Newline matches as BOL/EOL /// </summary> /// <param name="program">Compiled regular expression program (see RECompiler)</param> /// <param name="matchFlags">One or more of the MatchOptions</param> internal Regex(RegexProgram program, RegexOptions matchFlags) { Program = program; Options = matchFlags; }