vgritsenko 2003/12/20 09:21:44 Modified: . build.xml docs RETest.txt src/java/org/apache/regexp RETest.java xdocs RETest.txt Log: Apply patch from Oleg Sukhodolsky: improvements to the RETest, and to the RETest.txt file format. Make RETest less chatty if result is success. Revision Changes Path 1.6 +3 -2 jakarta-regexp/build.xml Index: build.xml =================================================================== RCS file: /home/cvs/jakarta-regexp/build.xml,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- build.xml 6 Sep 2003 01:45:51 -0000 1.5 +++ build.xml 20 Dec 2003 17:21:44 -0000 1.6 @@ -32,7 +32,7 @@ <property name="javadoc.destdir" value="docs/api/"/> <property name="final.name" value="${project}-${version}"/> <property name="final.dir" value="${final.name}/"/> - <property name="debug" value="off"/> + <property name="debug" value="on"/> <property name="optimize" value="on"/> <property name="deprecation" value="off"/> <property name="RETest.txt" value="docs/RETest.txt"/> @@ -185,7 +185,8 @@ <!-- Run RE Test Suite --> <!-- ================================================================== --> <target name="test" depends="jar"> - <java classname="org.apache.regexp.RETest" fork="yes"> + <java classname="org.apache.regexp.RETest" fork="yes" + failonerror="yes"> <arg value="${RETest.txt}"/> <classpath> <fileset dir="${build.dir}"> 1.12 +153 -2 jakarta-regexp/docs/RETest.txt Index: RETest.txt =================================================================== RCS file: /home/cvs/jakarta-regexp/docs/RETest.txt,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- RETest.txt 1 Sep 2003 18:31:53 -0000 1.11 +++ RETest.txt 20 Dec 2003 17:21:44 -0000 1.12 @@ -2,6 +2,7 @@ abc abc YES +1 abc #2 @@ -23,42 +24,49 @@ abc xabcy YES +1 abc #6 abc ababc YES +1 abc #7 ab*c abc YES +1 abc #8 ab*bc abc YES +1 abc #9 ab*bc abbc YES +1 abbc #10 ab*bc abbbbc YES +1 abbbbc #11 ab+bc abbc YES +1 abbc #12 @@ -75,18 +83,21 @@ ab+bc abbbbc YES +1 abbbbc #15 ab?bc abbc YES +1 abbc #16 ab?bc abc YES +1 abc #17 @@ -98,24 +109,28 @@ ab?c abc YES +1 abc #19 a.c abc YES +1 abc #20 a.c axc YES +1 axc #21 a.*c axyzc YES +1 axyzc #22 @@ -132,6 +147,7 @@ a[bc]d abd YES +1 abd #25 @@ -143,12 +159,14 @@ a[b-d]e ace YES +1 ace #27 a[b-d] aac YES +1 ac #28 @@ -159,12 +177,14 @@ a[-b] aa YES +1 aa #30 a[b-] ac YES +1 ac #31 @@ -187,6 +207,7 @@ a[^bc]d aed YES +1 aed #36 @@ -198,18 +219,21 @@ ab|cd abc YES +1 ab #38 ab|cd abcd YES +1 ab #39 ab|cd bcda YES +1 cd #40 @@ -220,6 +244,7 @@ ()ef ef YES +2 ef @@ -243,24 +268,28 @@ a\(b a(b YES +1 a(b #47 a\(*b ab YES +1 ab #48 a\(*b a((b YES +1 a((b #49 a\\b a\b YES +1 a\b #50 @@ -275,6 +304,7 @@ ((a)) abc YES +3 a a a @@ -283,6 +313,7 @@ (a)b(c) abc YES +3 abc a c @@ -291,6 +322,7 @@ a+b+c aabbabc YES +1 abc #55 @@ -305,12 +337,14 @@ a* aaaa YES +1 aaaa #58 a* baaaa YES +1 #59 @@ -329,6 +363,7 @@ (ab|cd)e abcde YES +2 cde cd @@ -336,30 +371,35 @@ [abhgefdc]ij hij YES +1 hij #64 ab* xabyabbbz YES +1 ab #65 ab* xayabbbz YES +1 a #66 abcd*efg abcdefg YES +1 abcdefg #67 (ab|ab*)bc abc YES +2 abc a @@ -368,6 +408,7 @@ (a|b|c|d|e)f ef YES +2 ef e @@ -375,12 +416,14 @@ a|b|c|d|e e YES +1 e #70 (.*)c(.*) abcde YES +3 abcde ab de @@ -389,6 +432,7 @@ \((.*), (.*)\) (a, b) YES +3 (a, b) a b @@ -397,6 +441,7 @@ a(bc)d abcd YES +2 abcd bc @@ -404,12 +449,14 @@ a* x YES +1 #74 ([abc])*d abbbcd YES +2 abbbcd c @@ -417,12 +464,14 @@ a* YES +1 #76 ([abc])*bcd abcd YES +2 abcd a @@ -430,6 +479,7 @@ (a|b)c*d abcd YES +2 bcd b @@ -437,6 +487,7 @@ a([bc]*)c* abc YES +2 abc bc @@ -444,12 +495,14 @@ [a-zA-Z_][a-zA-Z0-9_]* alpha YES +1 alpha #80 ((a)(b)c)(d) abcd YES +5 abcd abc a @@ -460,6 +513,7 @@ (ab|a)b*c abc YES +2 abc ab @@ -476,6 +530,7 @@ (((((((((a))))))))) a YES +10 a a a @@ -496,12 +551,14 @@ abcd abcd YES +1 abcd #87 a[-]?c abc YES +1 abc #88 @@ -513,18 +570,21 @@ multiple words multiple words, yeah YES +1 multiple words #90 a[bcd]*dcdcde adcdcde YES +1 adcdcde #91 a([bc]*)(c*d) abcd YES +3 abcd bc d @@ -533,6 +593,7 @@ a([bc]+)(c*d) abcd YES +3 abcd bc d @@ -541,6 +602,7 @@ a([bc]*)(c+d) abcd YES +3 abcd b cd @@ -562,6 +624,7 @@ ^abc$ abc YES +1 abc #98 @@ -573,6 +636,7 @@ ^abc abcc YES +1 abc #100 @@ -584,18 +648,21 @@ abc$ aabc YES +1 abc #102 ^ abc YES +1 #103 $ abc YES +1 #104 $b @@ -606,6 +673,7 @@ (a+|b)* ab YES +2 ab b @@ -613,6 +681,7 @@ (a+|b)+ ab YES +2 ab b @@ -620,6 +689,7 @@ (a+|b)? ab YES +2 a a @@ -635,6 +705,7 @@ [^ab]* cde YES +1 cde #111 @@ -646,6 +717,7 @@ ^a(bc+|b[eh])g|.h$ abh YES +1 bh @@ -653,6 +725,7 @@ (bc+d$|ef*g.|h?i(j|k)) effgz YES +2 effgz effgz @@ -661,6 +734,7 @@ (bc+d$|ef*g.|h?i(j|k)) ij YES +3 ij ij j @@ -680,6 +754,7 @@ (bc+d$|ef*g.|h?i(j|k)) reffgz YES +2 effgz effgz @@ -687,6 +762,7 @@ a*b\s+c aaaab c YES +1 aaaab c #119 @@ -698,6 +774,7 @@ a*(b*c*) aabbcc YES +2 aabbcc bbcc @@ -705,18 +782,21 @@ a?b+c* b YES +1 b #122 \d+ 99 YES +1 99 #123 ^[:javastart:]+[:javapart:]+$ javaIdentifier0 YES +1 javaIdentifier0 #124 @@ -728,12 +808,14 @@ [a-e]?d\\e yyzabecd\eyyz YES +1 cd\e #126 ((\w+)/)*(\w+) foo/bar/baz YES +4 foo/bar/baz bar/ bar @@ -743,6 +825,7 @@ i am a green (giant|man|martian) i am a green man YES +2 i am a green man man @@ -750,6 +833,7 @@ ([a-c]+?)c abcabcabc YES +2 abc ab @@ -757,6 +841,7 @@ ([ab]*?)b aaaaabaaaababab YES +2 aaaaab aaaaa @@ -764,6 +849,7 @@ ([ab]*)b aaaaabaaaababab YES +2 aaaaabaaaababab aaaaabaaaababa @@ -771,12 +857,14 @@ ([ab]??)b bb YES +2 b #132 (c[ab]?)b cbb YES +2 cbb cb @@ -784,6 +872,7 @@ (c[ab]??)b cbb YES +2 cb c @@ -791,6 +880,7 @@ (c[ab]*?)b cbb YES +2 cb c @@ -798,6 +888,7 @@ [:digit:]+ 789 YES +1 789 #136 @@ -809,6 +900,7 @@ [:xdigit:]+ ffe5a YES +1 ffe5a #138 @@ -819,6 +911,7 @@ (wee|week)(knights|knight) weeknights YES +3 weeknights wee knights @@ -827,6 +920,7 @@ (ac*)c*d[ac]*\1 acdacaa YES +2 acdac ac @@ -834,6 +928,7 @@ (a.*b)(a.*b) accbaccccb YES +3 accbaccccb accb accccb @@ -842,6 +937,7 @@ (.)=\1 x=x YES +2 x=x x @@ -849,6 +945,7 @@ ([ab])=\1 a=a YES +2 a=a a @@ -856,6 +953,7 @@ ([ab]+)=\1 abba=abba YES +2 abba=abba abba @@ -863,18 +961,21 @@ \u004a J YES +1 J #146 \x4a J YES +1 J #147 \[([:javastart:][:javapart:]*)\] foo[bar]baz YES +2 [bar] bar @@ -882,6 +983,7 @@ (\s*\w+)? aa YES +2 aa aa @@ -889,30 +991,35 @@ (?:a) a YES +1 a #150 (?:a) aa YES +1 a #151 (?:\w) abc YES +1 a #152 (?:\w\s\w)+ a b c YES +1 a b #153 (a\w)(?:,(a\w))+ ab,ac,ad YES +3 ab,ac,ad ab ad @@ -921,6 +1028,7 @@ z(\w\s+(?:\w\s+\w)+)z za b bc cd dz YES +2 za b bc cd dz a b bc cd d @@ -928,6 +1036,7 @@ (([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)* http://www.test.com YES +4 http://www.test.com http:// http @@ -937,6 +1046,7 @@ ((?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)* ftp://www.test.com YES +3 ftp://www.test.com ftp:// .com @@ -945,6 +1055,7 @@ (([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)* htTp://www.test.com YES +3 htTp://www.test.com htTp:// htTp @@ -953,6 +1064,7 @@ (?:([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)* FTP://www.test.com YES +3 FTP://www.test.com FTP .com @@ -966,6 +1078,7 @@ ^(?:(?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$ FtP://www.test.com YES +1 FtP://www.test.com #161 @@ -977,24 +1090,28 @@ ^(?:(?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$ www.test.com YES +1 www.test.com #163 abc.*?x+yz abcaaaaaxyzbbbbxyz YES +1 abcaaaaaxyz #164 abc.+?x+yz abcaaaaaxyzbbbbxyz YES +1 abcaaaaaxyz #165 a.+?(c|d) aaaacaaaaad YES +2 aaaac c @@ -1002,6 +1119,7 @@ a.+(c|d) aaaacaaaaad YES +2 aaaacaaaaad d @@ -1009,12 +1127,14 @@ a+?b+?c+? aaabccaaabbbccc YES +1 aaabc #168 a(.+)b(.+)c(.+)d(.+)e(.+)f(.+)g(.+)h(.+)i(.+)j(.+)k(.+)l(.+)m(.+)n(.+)o(.+)p(.+)q(.+)r a01b02c03d04e05f06g07h08i09j10k11l12m13n14o15p16q17r YES +18 a01b02c03d04e05f06g07h08i09j10k11l12m13n14o15p16q17r 01 02 @@ -1048,35 +1168,41 @@ [^ac]+ bd YES +1 bd #172 [^ca]+ bd YES +1 bd #173 [^ac]+ acb YES +1 b #174 [a-z]{0,3} 123abcdefg123 YES +1 #175 ab{0,1}a aa YES +1 aa #176 ab{0,1}a aba YES +1 aba #177 @@ -1088,18 +1214,21 @@ ab{0,2}a aa YES +1 aa #179 ab{0,2}a aba YES +1 aba #180 ab{0,2}a abba YES +1 abba #181 @@ -1116,6 +1245,7 @@ ab{1,1}a aba YES +1 aba #184 @@ -1132,12 +1262,14 @@ ab{1,2}a aba YES +1 aba #187 ab{1,2}a abba YES +1 abba #188 @@ -1149,18 +1281,21 @@ ab{0,}a aa YES +1 aa #190 ab{0,}a aba YES +1 aba #191 ab{0,}a abba YES +1 abba #192 @@ -1172,12 +1307,14 @@ ab{1,}a aba YES +1 aba #194 ab{1,}a abba YES +1 abba #195 @@ -1189,6 +1326,7 @@ ab{1}a aba YES +1 aba #197 @@ -1200,6 +1338,7 @@ ab{0}a aa YES +1 aa #199 @@ -1221,6 +1360,7 @@ ab{2}a abba YES +1 abba #203 @@ -1230,38 +1370,44 @@ #204 [ \-] - - +- YES - - +1 +- #205 [a-z0-9\.\-]+ {regexp-1.2} YES +1 regexp-1.2 #206 [a-z0-9\-\.]+ {regexp-1.2} YES +1 regexp-1.2 #207 [a-z\-0-9\.]+ {regexp-1.2} YES +1 regexp-1.2 #208 \w+ a_b YES +1 a_b #209 ([0123])??((((1st)|(2nd))|(3rd))|(\dth)) 1st YES +6 1st 1st @@ -1273,6 +1419,7 @@ [^\s\]'<>(),;:\.\[] - YES +1 - #211 @@ -1284,12 +1431,14 @@ [^\s\(\)<>@,;:\\\"\.\[\]] - YES +1 - #213 a{0,1}b{0,1}c{0,1}d{0,1}e{0,1}f{0,1}g{0,1}h{0,1}i{0,1}j{0,1}k{0,1}l{0,1} acghij YES +1 acghij #214 @@ -1297,9 +1446,11 @@ 012 YES 1 +1 #215 [^02468ACEGIKMOQSUW] UVW YES +1 V 1.8 +496 -271 jakarta-regexp/src/java/org/apache/regexp/RETest.java Index: RETest.java =================================================================== RCS file: /home/cvs/jakarta-regexp/src/java/org/apache/regexp/RETest.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- RETest.java 7 Sep 2003 15:04:14 -0000 1.7 +++ RETest.java 20 Dec 2003 17:21:44 -0000 1.8 @@ -66,6 +66,9 @@ import java.io.ObjectOutputStream; import java.io.ByteArrayInputStream; import java.io.ObjectInputStream; +import java.io.StringBufferInputStream; +import java.io.StringReader; +import java.io.IOException; /** * Data driven (and optionally interactive) testing harness to exercise regular @@ -84,8 +87,7 @@ // A new line character. static final String NEW_LINE = System.getProperty( "line.separator" ); - // Construct a matcher and a debug compiler - RE r = new RE(); + // Construct a debug compiler REDebugCompiler compiler = new REDebugCompiler(); /** @@ -98,11 +100,14 @@ { try { - test( args ); + if (!test( args )) { + System.exit(1); + } } catch (Exception e) { e.printStackTrace(); + System.exit(1); } } @@ -147,6 +152,7 @@ */ void runInteractiveTests(String expr) { + RE r = new RE(); try { // Compile expression @@ -206,14 +212,26 @@ void die(String s) { say("FATAL ERROR: " + s); - System.exit(0); + System.exit(-1); } /** - * Fail with an error. - * Will print a big failure message to System.out. - * @param s Failure description - */ + * Fail with an error. Will print a big failure message to System.out. + * + * @param log Output before failure + * @param s Failure description + */ + void fail(StringBuffer log, String s) + { + System.out.print(log.toString()); + fail(s); + } + + /** + * Fail with an error. Will print a big failure message to System.out. + * + * @param s Failure description + */ void fail(String s) { failures++; @@ -225,22 +243,11 @@ say(s); say(""); // make sure the writer gets flushed. - PrintWriter writer = new PrintWriter( System.out ); - compiler.dumpProgram( writer ); - writer.flush(); - say("" + NEW_LINE + ""); - } - - /** - * Show a success - * @param s Success story - */ - void success(String s) - { - if (showSuccesses) - { - show(); - say("Success: " + s); + if (compiler != null) { + PrintWriter writer = new PrintWriter( System.out ); + compiler.dumpProgram( writer ); + writer.flush(); + say("" + NEW_LINE + ""); } } @@ -250,16 +257,7 @@ */ void say(String s) { - System.out.println (s); - } - - /** - * Show an expression - */ - void show() - { - say("" + NEW_LINE + "-----------------------" + NEW_LINE + ""); - say("Expression #" + (n) + " \"" + expr + "\" "); + System.out.println(s); } /** @@ -276,23 +274,10 @@ } } - // Pre-compiled regular expression "a*b" - char[] re1Instructions = - { - 0x007c, 0x0000, 0x001a, 0x007c, 0x0000, 0x000d, 0x0041, - 0x0001, 0x0004, 0x0061, 0x007c, 0x0000, 0x0003, 0x0047, - 0x0000, 0xfff6, 0x007c, 0x0000, 0x0003, 0x004e, 0x0000, - 0x0003, 0x0041, 0x0001, 0x0004, 0x0062, 0x0045, 0x0000, - 0x0000, - }; - - REProgram re1 = new REProgram(re1Instructions); - /* - * Current expression and number in automated test - */ - String expr; - int n = 0; + * number in automated test + */ + int testCount = 0; /* * Count of failures in automated test @@ -307,218 +292,27 @@ { long ms = System.currentTimeMillis(); - // Simple test of pre-compiled regular expressions - RE r = new RE(re1); - say("a*b"); - say("aaaab = " + r.match("aaab")); - showParens(r); - say("b = " + r.match("b")); - showParens(r); - say("c = " + r.match("c")); - showParens(r); - say("ccccaaaaab = " + r.match("ccccaaaaab")); - showParens(r); - - r = new RE("a*b"); - String[] s = r.split("xxxxaabxxxxbyyyyaaabzzz"); - r = new RE("x+"); - s = r.grep(s); - for (int i = 0; i < s.length; i++) - { - say("s[" + i + "] = " + s[i]); - } - - r = new RE("a*b"); - String s1 = r.subst("aaaabfooaaabgarplyaaabwackyb", "-"); - say("s = " + s1); - // Some unit tests - runAutomatedTests(); + testPrecompiledRE(); + testSplitAndGrep(); + testSubst(); + testOther(); // Test from script file File testInput = new File(testDocument); - if (! testInput.exists()) + if (! testInput.exists()) { throw new Exception ("Could not find: " + testDocument); + } + BufferedReader br = new BufferedReader(new FileReader(testInput)); try { // While input is available, parse lines while (br.ready()) { - // Find next re test case - String number = ""; - String yesno; - while (br.ready()) - { - number = br.readLine(); - if (number == null) - { - break; - } - number = number.trim(); - if (number.startsWith("#")) - { - break; - } - if (!number.equals("")) - { - say("Script error. Line = " + number); - System.exit(0); - } - } - - // Are we done? - if (!br.ready()) - { - break; - } - - // Get expression - expr = br.readLine(); - n++; - say(""); - say(n + ". " + expr); - say(""); - - // Compile it - try - { - r.setProgram(compiler.compile(expr)); - } - - // Some expressions *should* cause exceptions to be thrown - catch (Exception e) - { - // Get expected result - yesno = br.readLine().trim(); - - // If it was supposed to be an error, report success and continue - if (yesno.equals("ERR")) - { - say(" Match: ERR"); - success("Produces an error (" + e.toString() + "), as expected."); - continue; - } - - // Wasn't supposed to be an error - String message = e.getMessage() == null ? e.toString() : e.getMessage(); - fail("Produces an unexpected exception \"" + message + "\""); - e.printStackTrace(); - } - catch (Error e) - { - // Internal error happened - fail("Compiler threw fatal error \"" + e.getMessage() + "\""); - e.printStackTrace(); - } - - // Get string to match against - String matchAgainst = br.readLine().trim(); - say(" Match against: '" + matchAgainst + "'"); - - // Expression didn't cause an expected error - if (matchAgainst.equals("ERR")) - { - fail("Was expected to be an error, but wasn't."); - continue; - } - - // Try matching - try - { - // Match against the string - boolean b = r.match(matchAgainst); - - // Get expected result - yesno = br.readLine().trim(); - - // If match succeeded - if (b) - { - // Status - say(" Match: YES"); - - // Match wasn't supposed to succeed - if (yesno.equals("NO")) - { - fail("Matched \"" + matchAgainst + "\", when not expected to."); - } - else - if (yesno.equals("YES")) - { - // Match succeeded as expected - success("Matched \"" + matchAgainst + "\", as expected:"); - - // Show subexpression registers - if (showSuccesses) - { - showParens(r); - } - - say(" Paren count: " + r.getParenCount()); - - // Check registers against expected contents - for (int p = 0; p < r.getParenCount(); p++) - { - // Get next register - String register = br.readLine().trim(); - say(" Paren " + p + " : " + r.getParen(p)); - - // Compare expected result with actual - if (register.length() == 0 && r.getParen(p) == null) - { - // Consider "" in test file equal to null - } else - if (!register.equals(r.getParen(p))) - { - // Register isn't what it was supposed to be - fail("Register " + p + " should be = \"" + register + "\", but is \"" + r.getParen(p) + "\" instead."); - } - } - } - else - { - // Bad test script - die("Test script error!"); - } - } - else - { - // Status - say(" Match: NO"); - - // Match failed - if (yesno.equals("YES")) - { - // Should have failed - fail("Did not match \"" + matchAgainst + "\", when expected to."); - } - else - if (yesno.equals("NO")) - { - // Should have failed - success("Did not match \"" + matchAgainst + "\", as expected."); - } - else - { - // Bad test script - die("Test script error!"); - } - } - } - - // Matcher blew it - catch(Exception e) - { - fail("Matcher threw exception: " + e.toString()); - e.printStackTrace(); - } - - // Internal error - catch(Error e) - { - fail("Matcher threw fatal error \"" + e.getMessage() + "\""); - e.printStackTrace(); + RETestCase testcase = getNextTestCase(br); + if (testcase != null) { + testcase.runTest(); } } } @@ -534,14 +328,14 @@ if (failures > 0) { say("*************** THERE ARE FAILURES! *******************"); } - say("Tests complete. " + n + " tests, " + failures + " failure(s)."); + say("Tests complete. " + testCount + " tests, " + failures + " failure(s)."); } /** * Run automated unit test * @exception Exception thrown in case of error */ - void runAutomatedTests() throws Exception + void testOther() throws Exception { // Serialization test 1: Compile regexp and serialize/deserialize it RE r = new RE("(a*)b"); @@ -553,9 +347,10 @@ if (!r.match("aaab")) { fail("Did not match 'aaab' with deserialized RE."); + } else { + say("aaaab = true"); + showParens(r); } - say("aaaab = true"); - showParens(r); // Serialization test 2: serialize/deserialize used regexp out.reset(); @@ -570,9 +365,10 @@ if (!r.match("aaab")) { fail("Did not match 'aaab' with deserialized RE."); + } else { + say("aaaab = true"); + showParens(r); } - say("aaaab = true"); - showParens(r); // Test MATCH_CASEINDEPENDENT r = new RE("abc(\\w*)"); @@ -582,42 +378,471 @@ if (!r.match("abcddd")) { fail("Did not match 'abcddd'."); + } else { + say("abcddd = true"); + showParens(r); } - say("abcddd = true"); - showParens(r); if (!r.match("aBcDDdd")) { fail("Did not match 'aBcDDdd'."); + } else { + say("aBcDDdd = true"); + showParens(r); } - say("aBcDDdd = true"); - showParens(r); if (!r.match("ABCDDDDD")) { fail("Did not match 'ABCDDDDD'."); + } else { + say("ABCDDDDD = true"); + showParens(r); } - say("ABCDDDDD = true"); - showParens(r); // Test subst() with backreferences r = new RE("http://[\\.\\w\\-\\?/~_@&=%]+"); String s = r.subst("visit us: http://www.apache.org!", "1234<a href=\"$0\">$0</a>", RE.REPLACE_BACKREFERENCES); - if (!s.equals("visit us: 1234<a href=\"http://www.apache.org\">http://www.apache.org</a>!")) - { - fail("Wrong subst() result: " + s); - } + assertEquals("Wrong subst() result", "visit us: 1234<a href=\"http://www.apache.org\">http://www.apache.org</a>!", s); // Test subst() with backreferences without leading characters // before first backreference r = new RE("(.*?)=(.*)"); s = r.subst("variable=value", - "$1_test_$212", RE.REPLACE_BACKREFERENCES); - if (!s.equals("variable_test_value12")) + "$1_test_$212", RE.REPLACE_BACKREFERENCES); + assertEquals("Wrong subst() result", "variable_test_value12", s); + } + + private void testPrecompiledRE() + { + // Pre-compiled regular expression "a*b" + char[] re1Instructions = + { + 0x007c, 0x0000, 0x001a, 0x007c, 0x0000, 0x000d, 0x0041, + 0x0001, 0x0004, 0x0061, 0x007c, 0x0000, 0x0003, 0x0047, + 0x0000, 0xfff6, 0x007c, 0x0000, 0x0003, 0x004e, 0x0000, + 0x0003, 0x0041, 0x0001, 0x0004, 0x0062, 0x0045, 0x0000, + 0x0000, + }; + + REProgram re1 = new REProgram(re1Instructions); + + // Simple test of pre-compiled regular expressions + RE r = new RE(re1); + say("a*b"); + boolean result = r.match("aaab"); + say("aaab = " + result); + showParens(r); + if (!result) { + fail("\"aaab\" doesn't match to precompiled \"a*b\""); + } + + result = r.match("b"); + say("b = " + result); + showParens(r); + if (!result) { + fail("\"b\" doesn't match to precompiled \"a*b\""); + } + + result = r.match("c"); + say("c = " + result); + showParens(r); + if (result) { + fail("\"c\" matches to precompiled \"a*b\""); + } + + result = r.match("ccccaaaaab"); + say("ccccaaaaab = " + result); + showParens(r); + if (!result) { + fail("\"ccccaaaaab\" doesn't match to precompiled \"a*b\""); + } + } + + private void testSplitAndGrep() + { + String[] expected = {"xxxx", "xxxx", "yyyy", "zzz"}; + RE r = new RE("a*b"); + String[] s = r.split("xxxxaabxxxxbyyyyaaabzzz"); + for (int i = 0; i < expected.length && i < s.length; i++) { + assertEquals("Wrong splitted part", expected[i], s[i]); + } + assertEquals("Wrong number of splitted parts", expected.length, + s.length); + + r = new RE("x+"); + expected = new String[] {"xxxx", "xxxx"}; + s = r.grep(s); + for (int i = 0; i < s.length; i++) + { + say("s[" + i + "] = " + s[i]); + assertEquals("Grep fails", expected[i], s[i]); + } + assertEquals("Wrong number of string found by grep", expected.length, + s.length); + } + + private void testSubst() + { + RE r = new RE("a*b"); + String expected = "-foo-garply-wacky-"; + String s1 = r.subst("aaaabfooaaabgarplyaaabwackyb", "-"); + say("s = " + s1); + assertEquals("Wrong result of substitution", expected, s1); + } + + public void assertEquals(String message, String expected, String actual) + { + if (expected != null && !expected.equals(actual) + || actual != null && !actual.equals(expected)) + { + fail(message + " (expected \"" + expected + + "\", actual \"" + actual + "\")"); + } + } + + public void assertEquals(String message, int expected, int actual) + { + if (expected != actual) { + fail(message + " (expected \"" + expected + + "\", actual \"" + actual + "\")"); + } + } + + /** + * Converts yesno string to boolean. + * @param yesno string representation of expected result + * @return true if yesno is "YES", false if yesno is "NO" + * stops program otherwise. + */ + private boolean getExpectedResult(String yesno) + { + if ("NO".equals(yesno)) + { + return false; + } + else if ("YES".equals(yesno)) + { + return true; + } + else + { + // Bad test script + die("Test script error!"); + return false; //to please javac + } + } + + /** + * Finds next test description in a given script. + * @param br <code>BufferedReader</code> for a script file + * @return strign tag for next test description + * @exception IOException if some io problems occured + */ + private String findNextTest(BufferedReader br) throws IOException + { + String number = ""; + + while (br.ready()) + { + number = br.readLine(); + if (number == null) + { + break; + } + number = number.trim(); + if (number.startsWith("#")) + { + break; + } + if (!number.equals("")) + { + say("Script error. Line = " + number); + System.exit(-1); + } + } + return number; + } + + /** + * Creates testcase for the next test description in the script file. + * @param br <code>BufferedReader</code> for script file. + * @return a new tescase or null. + * @exception IOException if some io problems occured + */ + private RETestCase getNextTestCase(BufferedReader br) throws IOException + { + // Find next re test case + final String tag = findNextTest(br); + + // Are we done? + if (!br.ready()) + { + return null; + } + + // Get expression + final String expr = br.readLine(); + + // Get test information + final String matchAgainst = br.readLine(); + final boolean badPattern = "ERR".equals(matchAgainst); + boolean shouldMatch = false; + int expectedParenCount = 0; + String[] expectedParens = null; + + if (!badPattern) { + shouldMatch = getExpectedResult(br.readLine().trim()); + if (shouldMatch) { + expectedParenCount = Integer.parseInt(br.readLine().trim()); + expectedParens = new String[expectedParenCount]; + for (int i = 0; i < expectedParenCount; i++) { + expectedParens[i] = br.readLine(); + } + } + } + + return new RETestCase(this, tag, expr, matchAgainst, badPattern, + shouldMatch, expectedParens); + } +} + +final class RETestCase +{ + final private StringBuffer log = new StringBuffer(); + final private int number; + final private String tag; // number from script file + final private String pattern; + final private String toMatch; + final private boolean badPattern; + final private boolean shouldMatch; + final private String[] parens; + final private RETest test; + private RE regexp; + + public RETestCase(RETest test, String tag, String pattern, + String toMatch, boolean badPattern, + boolean shouldMatch, String[] parens) + { + this.number = ++test.testCount; + this.test = test; + this.tag = tag; + this.pattern = pattern; + this.toMatch = toMatch; + this.badPattern = badPattern; + this.shouldMatch = shouldMatch; + if (parens != null) { + this.parens = new String[parens.length]; + for (int i = 0; i < parens.length; i++) { + this.parens[i] = parens[i]; + } + } else { + this.parens = null; + } + } + + public void runTest() + { + test.say(tag + "(" + number + "): " + pattern); + if (testCreation()) { + testMatch(); + } + } + + boolean testCreation() + { + try + { + // Compile it + regexp = new RE(); + regexp.setProgram(test.compiler.compile(pattern)); + // Expression didn't cause an expected error + if (badPattern) + { + test.fail(log, "Was expected to be an error, but wasn't."); + return false; + } + + return true; + } + // Some expressions *should* cause exceptions to be thrown + catch (Exception e) + { + // If it was supposed to be an error, report success and continue + if (badPattern) + { + log.append(" Match: ERR\n"); + success("Produces an error (" + e.toString() + "), as expected."); + return false; + } + + // Wasn't supposed to be an error + String message = (e.getMessage() == null) ? e.toString() : e.getMessage(); + test.fail(log, "Produces an unexpected exception \"" + message + "\""); + e.printStackTrace(); + } + catch (Error e) + { + // Internal error happened + test.fail(log, "Compiler threw fatal error \"" + e.getMessage() + "\""); + e.printStackTrace(); + } + + return false; + } + + private void testMatch() + { + log.append(" Match against: '" + toMatch + "'\n"); + // Try regular matching + try + { + // Match against the string + boolean result = regexp.match(toMatch); + log.append(" Matched: " + (result ? "YES" : "NO") + "\n"); + + // Check result, parens, and iterators + if (checkResult(result) && (!shouldMatch || checkParens())) + { + // test match(CharacterIterator, int) + // for every CharacterIterator implementation. + log.append(" Match using StringCharacterIterator\n"); + if (!tryMatchUsingCI(new StringCharacterIterator(toMatch))) + return; + + log.append(" Match using CharacterArrayCharacterIterator\n"); + if (!tryMatchUsingCI(new CharacterArrayCharacterIterator(toMatch.toCharArray(), 0, toMatch.length()))) + return; + + log.append(" Match using StreamCharacterIterator\n"); + if (!tryMatchUsingCI(new StreamCharacterIterator(new StringBufferInputStream(toMatch)))) + return; + + log.append(" Match using ReaderCharacterIterator\n"); + if (!tryMatchUsingCI(new ReaderCharacterIterator(new StringReader(toMatch)))) + return; + } + } + // Matcher blew it + catch(Exception e) + { + test.fail(log, "Matcher threw exception: " + e.toString()); + e.printStackTrace(); + } + // Internal error + catch(Error e) + { + test.fail(log, "Matcher threw fatal error \"" + e.getMessage() + "\""); + e.printStackTrace(); + } + } + + private boolean checkResult(boolean result) + { + // Write status + if (result == shouldMatch) { + success((shouldMatch ? "Matched" : "Did not match") + + " \"" + toMatch + "\", as expected:"); + return true; + } else { + if (shouldMatch) { + test.fail(log, "Did not match \"" + toMatch + "\", when expected to."); + } else { + test.fail(log, "Matched \"" + toMatch + "\", when not expected to."); + } + return false; + } + } + + private boolean checkParens() + { + // Show subexpression registers + if (test.showSuccesses) + { + test.showParens(regexp); + } + + log.append(" Paren count: " + regexp.getParenCount() + "\n"); + if(!assertEquals(log, "Wrong number of parens", parens.length, regexp.getParenCount())) + { + return false; + } + + // Check registers against expected contents + for (int p = 0; p < regexp.getParenCount(); p++) + { + log.append(" Paren " + p + ": " + regexp.getParen(p) + "\n"); + + // Compare expected result with actual + if (parens[p].length() == 0 && regexp.getParen(p) == null) + { + // Consider "" in test file equal to null + continue; + } + if (!assertEquals(log, "Wrong register " + p, parens[p], regexp.getParen(p))) + { + return false; + } + } + + return true; + } + + boolean tryMatchUsingCI(CharacterIterator matchAgainst) + { + try { + boolean result = regexp.match(matchAgainst, 0); + log.append(" Match: " + (result ? "YES" : "NO") + "\n"); + return checkResult(result) && (!shouldMatch || checkParens()); + } + // Matcher blew it + catch(Exception e) { - fail("Wrong subst() result: " + s); + test.fail(log, "Matcher threw exception: " + e.toString()); + e.printStackTrace(); } + // Internal error + catch(Error e) + { + test.fail(log, "Matcher threw fatal error \"" + e.getMessage() + "\""); + e.printStackTrace(); + } + return false; + } + public boolean assertEquals(StringBuffer log, String message, String expected, String actual) + { + if (expected != null && !expected.equals(actual) + || actual != null && !actual.equals(expected)) + { + test.fail(log, message + " (expected \"" + expected + + "\", actual \"" + actual + "\")"); + return false; + } + return true; + } + + public boolean assertEquals(StringBuffer log, String message, int expected, int actual) + { + if (expected != actual) { + test.fail(log, message + " (expected \"" + expected + + "\", actual \"" + actual + "\")"); + return false; + } + return true; + } + + /** + * Show a success + * @param s Success story + */ + void success(String s) + { + if (test.showSuccesses) + { + test.say("" + RETest.NEW_LINE + "-----------------------" + RETest.NEW_LINE + ""); + test.say("Expression #" + (number) + " \"" + pattern + "\" "); + test.say("Success: " + s); + } } } 1.11 +153 -2 jakarta-regexp/xdocs/RETest.txt Index: RETest.txt =================================================================== RCS file: /home/cvs/jakarta-regexp/xdocs/RETest.txt,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- RETest.txt 1 Sep 2003 18:31:53 -0000 1.10 +++ RETest.txt 20 Dec 2003 17:21:44 -0000 1.11 @@ -2,6 +2,7 @@ abc abc YES +1 abc #2 @@ -23,42 +24,49 @@ abc xabcy YES +1 abc #6 abc ababc YES +1 abc #7 ab*c abc YES +1 abc #8 ab*bc abc YES +1 abc #9 ab*bc abbc YES +1 abbc #10 ab*bc abbbbc YES +1 abbbbc #11 ab+bc abbc YES +1 abbc #12 @@ -75,18 +83,21 @@ ab+bc abbbbc YES +1 abbbbc #15 ab?bc abbc YES +1 abbc #16 ab?bc abc YES +1 abc #17 @@ -98,24 +109,28 @@ ab?c abc YES +1 abc #19 a.c abc YES +1 abc #20 a.c axc YES +1 axc #21 a.*c axyzc YES +1 axyzc #22 @@ -132,6 +147,7 @@ a[bc]d abd YES +1 abd #25 @@ -143,12 +159,14 @@ a[b-d]e ace YES +1 ace #27 a[b-d] aac YES +1 ac #28 @@ -159,12 +177,14 @@ a[-b] aa YES +1 aa #30 a[b-] ac YES +1 ac #31 @@ -187,6 +207,7 @@ a[^bc]d aed YES +1 aed #36 @@ -198,18 +219,21 @@ ab|cd abc YES +1 ab #38 ab|cd abcd YES +1 ab #39 ab|cd bcda YES +1 cd #40 @@ -220,6 +244,7 @@ ()ef ef YES +2 ef @@ -243,24 +268,28 @@ a\(b a(b YES +1 a(b #47 a\(*b ab YES +1 ab #48 a\(*b a((b YES +1 a((b #49 a\\b a\b YES +1 a\b #50 @@ -275,6 +304,7 @@ ((a)) abc YES +3 a a a @@ -283,6 +313,7 @@ (a)b(c) abc YES +3 abc a c @@ -291,6 +322,7 @@ a+b+c aabbabc YES +1 abc #55 @@ -305,12 +337,14 @@ a* aaaa YES +1 aaaa #58 a* baaaa YES +1 #59 @@ -329,6 +363,7 @@ (ab|cd)e abcde YES +2 cde cd @@ -336,30 +371,35 @@ [abhgefdc]ij hij YES +1 hij #64 ab* xabyabbbz YES +1 ab #65 ab* xayabbbz YES +1 a #66 abcd*efg abcdefg YES +1 abcdefg #67 (ab|ab*)bc abc YES +2 abc a @@ -368,6 +408,7 @@ (a|b|c|d|e)f ef YES +2 ef e @@ -375,12 +416,14 @@ a|b|c|d|e e YES +1 e #70 (.*)c(.*) abcde YES +3 abcde ab de @@ -389,6 +432,7 @@ \((.*), (.*)\) (a, b) YES +3 (a, b) a b @@ -397,6 +441,7 @@ a(bc)d abcd YES +2 abcd bc @@ -404,12 +449,14 @@ a* x YES +1 #74 ([abc])*d abbbcd YES +2 abbbcd c @@ -417,12 +464,14 @@ a* YES +1 #76 ([abc])*bcd abcd YES +2 abcd a @@ -430,6 +479,7 @@ (a|b)c*d abcd YES +2 bcd b @@ -437,6 +487,7 @@ a([bc]*)c* abc YES +2 abc bc @@ -444,12 +495,14 @@ [a-zA-Z_][a-zA-Z0-9_]* alpha YES +1 alpha #80 ((a)(b)c)(d) abcd YES +5 abcd abc a @@ -460,6 +513,7 @@ (ab|a)b*c abc YES +2 abc ab @@ -476,6 +530,7 @@ (((((((((a))))))))) a YES +10 a a a @@ -496,12 +551,14 @@ abcd abcd YES +1 abcd #87 a[-]?c abc YES +1 abc #88 @@ -513,18 +570,21 @@ multiple words multiple words, yeah YES +1 multiple words #90 a[bcd]*dcdcde adcdcde YES +1 adcdcde #91 a([bc]*)(c*d) abcd YES +3 abcd bc d @@ -533,6 +593,7 @@ a([bc]+)(c*d) abcd YES +3 abcd bc d @@ -541,6 +602,7 @@ a([bc]*)(c+d) abcd YES +3 abcd b cd @@ -562,6 +624,7 @@ ^abc$ abc YES +1 abc #98 @@ -573,6 +636,7 @@ ^abc abcc YES +1 abc #100 @@ -584,18 +648,21 @@ abc$ aabc YES +1 abc #102 ^ abc YES +1 #103 $ abc YES +1 #104 $b @@ -606,6 +673,7 @@ (a+|b)* ab YES +2 ab b @@ -613,6 +681,7 @@ (a+|b)+ ab YES +2 ab b @@ -620,6 +689,7 @@ (a+|b)? ab YES +2 a a @@ -635,6 +705,7 @@ [^ab]* cde YES +1 cde #111 @@ -646,6 +717,7 @@ ^a(bc+|b[eh])g|.h$ abh YES +1 bh @@ -653,6 +725,7 @@ (bc+d$|ef*g.|h?i(j|k)) effgz YES +2 effgz effgz @@ -661,6 +734,7 @@ (bc+d$|ef*g.|h?i(j|k)) ij YES +3 ij ij j @@ -680,6 +754,7 @@ (bc+d$|ef*g.|h?i(j|k)) reffgz YES +2 effgz effgz @@ -687,6 +762,7 @@ a*b\s+c aaaab c YES +1 aaaab c #119 @@ -698,6 +774,7 @@ a*(b*c*) aabbcc YES +2 aabbcc bbcc @@ -705,18 +782,21 @@ a?b+c* b YES +1 b #122 \d+ 99 YES +1 99 #123 ^[:javastart:]+[:javapart:]+$ javaIdentifier0 YES +1 javaIdentifier0 #124 @@ -728,12 +808,14 @@ [a-e]?d\\e yyzabecd\eyyz YES +1 cd\e #126 ((\w+)/)*(\w+) foo/bar/baz YES +4 foo/bar/baz bar/ bar @@ -743,6 +825,7 @@ i am a green (giant|man|martian) i am a green man YES +2 i am a green man man @@ -750,6 +833,7 @@ ([a-c]+?)c abcabcabc YES +2 abc ab @@ -757,6 +841,7 @@ ([ab]*?)b aaaaabaaaababab YES +2 aaaaab aaaaa @@ -764,6 +849,7 @@ ([ab]*)b aaaaabaaaababab YES +2 aaaaabaaaababab aaaaabaaaababa @@ -771,12 +857,14 @@ ([ab]??)b bb YES +2 b #132 (c[ab]?)b cbb YES +2 cbb cb @@ -784,6 +872,7 @@ (c[ab]??)b cbb YES +2 cb c @@ -791,6 +880,7 @@ (c[ab]*?)b cbb YES +2 cb c @@ -798,6 +888,7 @@ [:digit:]+ 789 YES +1 789 #136 @@ -809,6 +900,7 @@ [:xdigit:]+ ffe5a YES +1 ffe5a #138 @@ -819,6 +911,7 @@ (wee|week)(knights|knight) weeknights YES +3 weeknights wee knights @@ -827,6 +920,7 @@ (ac*)c*d[ac]*\1 acdacaa YES +2 acdac ac @@ -834,6 +928,7 @@ (a.*b)(a.*b) accbaccccb YES +3 accbaccccb accb accccb @@ -842,6 +937,7 @@ (.)=\1 x=x YES +2 x=x x @@ -849,6 +945,7 @@ ([ab])=\1 a=a YES +2 a=a a @@ -856,6 +953,7 @@ ([ab]+)=\1 abba=abba YES +2 abba=abba abba @@ -863,18 +961,21 @@ \u004a J YES +1 J #146 \x4a J YES +1 J #147 \[([:javastart:][:javapart:]*)\] foo[bar]baz YES +2 [bar] bar @@ -882,6 +983,7 @@ (\s*\w+)? aa YES +2 aa aa @@ -889,30 +991,35 @@ (?:a) a YES +1 a #150 (?:a) aa YES +1 a #151 (?:\w) abc YES +1 a #152 (?:\w\s\w)+ a b c YES +1 a b #153 (a\w)(?:,(a\w))+ ab,ac,ad YES +3 ab,ac,ad ab ad @@ -921,6 +1028,7 @@ z(\w\s+(?:\w\s+\w)+)z za b bc cd dz YES +2 za b bc cd dz a b bc cd d @@ -928,6 +1036,7 @@ (([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)* http://www.test.com YES +4 http://www.test.com http:// http @@ -937,6 +1046,7 @@ ((?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)* ftp://www.test.com YES +3 ftp://www.test.com ftp:// .com @@ -945,6 +1055,7 @@ (([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)* htTp://www.test.com YES +3 htTp://www.test.com htTp:// htTp @@ -953,6 +1064,7 @@ (?:([hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+)* FTP://www.test.com YES +3 FTP://www.test.com FTP .com @@ -966,6 +1078,7 @@ ^(?:(?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$ FtP://www.test.com YES +1 FtP://www.test.com #161 @@ -977,24 +1090,28 @@ ^(?:(?:[hH][tT]{2}[pP]|[fF][tT][pP]):\/\/)?[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*$ www.test.com YES +1 www.test.com #163 abc.*?x+yz abcaaaaaxyzbbbbxyz YES +1 abcaaaaaxyz #164 abc.+?x+yz abcaaaaaxyzbbbbxyz YES +1 abcaaaaaxyz #165 a.+?(c|d) aaaacaaaaad YES +2 aaaac c @@ -1002,6 +1119,7 @@ a.+(c|d) aaaacaaaaad YES +2 aaaacaaaaad d @@ -1009,12 +1127,14 @@ a+?b+?c+? aaabccaaabbbccc YES +1 aaabc #168 a(.+)b(.+)c(.+)d(.+)e(.+)f(.+)g(.+)h(.+)i(.+)j(.+)k(.+)l(.+)m(.+)n(.+)o(.+)p(.+)q(.+)r a01b02c03d04e05f06g07h08i09j10k11l12m13n14o15p16q17r YES +18 a01b02c03d04e05f06g07h08i09j10k11l12m13n14o15p16q17r 01 02 @@ -1048,35 +1168,41 @@ [^ac]+ bd YES +1 bd #172 [^ca]+ bd YES +1 bd #173 [^ac]+ acb YES +1 b #174 [a-z]{0,3} 123abcdefg123 YES +1 #175 ab{0,1}a aa YES +1 aa #176 ab{0,1}a aba YES +1 aba #177 @@ -1088,18 +1214,21 @@ ab{0,2}a aa YES +1 aa #179 ab{0,2}a aba YES +1 aba #180 ab{0,2}a abba YES +1 abba #181 @@ -1116,6 +1245,7 @@ ab{1,1}a aba YES +1 aba #184 @@ -1132,12 +1262,14 @@ ab{1,2}a aba YES +1 aba #187 ab{1,2}a abba YES +1 abba #188 @@ -1149,18 +1281,21 @@ ab{0,}a aa YES +1 aa #190 ab{0,}a aba YES +1 aba #191 ab{0,}a abba YES +1 abba #192 @@ -1172,12 +1307,14 @@ ab{1,}a aba YES +1 aba #194 ab{1,}a abba YES +1 abba #195 @@ -1189,6 +1326,7 @@ ab{1}a aba YES +1 aba #197 @@ -1200,6 +1338,7 @@ ab{0}a aa YES +1 aa #199 @@ -1221,6 +1360,7 @@ ab{2}a abba YES +1 abba #203 @@ -1230,38 +1370,44 @@ #204 [ \-] - - +- YES - - +1 +- #205 [a-z0-9\.\-]+ {regexp-1.2} YES +1 regexp-1.2 #206 [a-z0-9\-\.]+ {regexp-1.2} YES +1 regexp-1.2 #207 [a-z\-0-9\.]+ {regexp-1.2} YES +1 regexp-1.2 #208 \w+ a_b YES +1 a_b #209 ([0123])??((((1st)|(2nd))|(3rd))|(\dth)) 1st YES +6 1st 1st @@ -1273,6 +1419,7 @@ [^\s\]'<>(),;:\.\[] - YES +1 - #211 @@ -1284,12 +1431,14 @@ [^\s\(\)<>@,;:\\\"\.\[\]] - YES +1 - #213 a{0,1}b{0,1}c{0,1}d{0,1}e{0,1}f{0,1}g{0,1}h{0,1}i{0,1}j{0,1}k{0,1}l{0,1} acghij YES +1 acghij #214 @@ -1297,9 +1446,11 @@ 012 YES 1 +1 #215 [^02468ACEGIKMOQSUW] UVW YES +1 V
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]