- </pre>\r
- <p>\r
- Differences between this package and perl5:<br>\r
- The extended Pattern for setting flags, is now supported,\r
- but the flags are different. "(?i)" tells the pattern to\r
- ignore case, "(?Q)" sets the "dontMatchInQuotes" flag, and\r
- "(?iQ)" sets them both. You can change the escape character.\r
- The pattern <pre>(?e=#)#d+</pre> is the same as <pre>\d+</pre>,\r
- but note that the sequence <pre>(?e=#)</pre> <b>must</b> occur\r
- at the very beginning of the pattern. There may be other small\r
- differences as well. I will either make my package conform\r
- or note them as I become aware of them.\r
- <p>\r
- This package supports additional patterns not in perl5:\r
- <center>\r
- <table border=1>\r
- <tr><td>(?@())</td><td>Group</td><td>This matches all characters between\r
- the '(' character and the balancing ')' character. Thus, it will\r
- match "()" as well as "(())". The balancing characters are\r
- arbitrary, thus (?@{}) matches on "{}" and "{{}}".</td>\r
- <tr><td>(?<1)</td><td>Backup</td><td>Moves the pointer backwards within the text.\r
- This allows you to make a "look behind." It fails if it\r
- attempts to move to a position before the beginning of the string.\r
- "x(?<1)" is equivalent to "(?=x)". The number, 1 in this example,\r
- is the number of characters to move backwards.</td>\r
- </table>\r
- </center>\r
- </dl>\r
- @author Steven R. Brandt\r
- @version package com.stevesoft.pat, release 1.5.3\r
- @see Pattern\r
- */\r
-public class Regex\r
- extends RegRes implements FilenameFilter\r
-{\r
- /** BackRefOffset gives the identity number of the first\r
- pattern. Version 1.0 used zero, version 1.1 uses 1 to be\r
- more compatible with perl. */\r
- static int BackRefOffset = 1;\r
- private static Pattern none = new NoPattern();\r
- Pattern thePattern = none;\r
- patInt minMatch = new patInt(0);\r
-\r
- static Hashtable validators = new Hashtable();\r
- static\r
- {\r
- define("p", "(?>1)", new UnicodePunct());\r
- define("P", "(?>1)", new NUnicodePunct());\r
- define("s", "(?>1)", new UnicodeWhite());\r
- define("S", "(?>1)", new NUnicodeWhite());\r
- define("w", "(?>1)", new UnicodeW());\r
- define("W", "(?>1)", new NUnicodeW());\r
- define("d", "(?>1)", new UnicodeDigit());\r
- define("D", "(?>1)", new NUnicodeDigit());\r
- define("m", "(?>1)", new UnicodeMath());\r
- define("M", "(?>1)", new NUnicodeMath());\r
- define("c", "(?>1)", new UnicodeCurrency());\r
- define("C", "(?>1)", new NUnicodeCurrency());\r
- define("a", "(?>1)", new UnicodeAlpha());\r
- define("A", "(?>1)", new NUnicodeAlpha());\r
- define("uc", "(?>1)", new UnicodeUpper());\r
- define("lc", "(?>1)", new UnicodeLower());\r
- }\r
-\r
- /** Set the dontMatch in quotes flag. */\r
- public void setDontMatchInQuotes(boolean b)\r
- {\r
- dontMatchInQuotes = b;\r
- }\r
-\r
- /** Find out if the dontMatchInQuotes flag is enabled. */\r
- public boolean getDontMatchInQuotes()\r
- {\r
- return dontMatchInQuotes;\r
- }\r
-\r
- boolean dontMatchInQuotes = false;\r
-\r
- /** Set the state of the ignoreCase flag. If set to true, then\r
- the pattern matcher will ignore case when searching for a\r
- match. */\r
- public void setIgnoreCase(boolean b)\r
- {\r
- ignoreCase = b;\r
- }\r
-\r
- /** Get the state of the ignoreCase flag. Returns true if we\r
- are ignoring the case of the pattern, false otherwise. */\r
- public boolean getIgnoreCase()\r
- {\r
- return ignoreCase;\r
- }\r
-\r
- boolean ignoreCase = false;\r
-\r
- static boolean defaultMFlag = false;\r
- /** Set the default value of the m flag. If it\r
- is set to true, then the MFlag will be on\r
- for any regex search executed. */\r
- public static void setDefaultMFlag(boolean mFlag)\r
- {\r
- defaultMFlag = mFlag;\r
- }\r
-\r
- /** Get the default value of the m flag. If it\r
- is set to true, then the MFlag will be on\r
- for any regex search executed. */\r
- public static boolean getDefaultMFlag()\r
- {\r
- return defaultMFlag;\r
- }\r
-\r
- /** Initializes the object without a Pattern. To supply a Pattern\r
- use compile(String s).\r
- @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
- */\r
- public Regex()\r
- {}\r
-\r
- /** Create and compile a Regex, but do not throw any exceptions.\r
- If you wish to have exceptions thrown for syntax errors,\r
- you must use the Regex(void) constructor to create the\r
- Regex object, and then call the compile method. Therefore, you\r
- should only call this method when you know your pattern is right.\r
- I will probably become more like\r
- @see com.stevesoft.pat.Regex#search(java.lang.String)\r
- @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
- */\r
- public Regex(String s)\r
- {\r
- try\r
- {\r
- compile(s);\r
- }\r
- catch (RegSyntax rs)\r
- {}\r
- }\r
-\r
- ReplaceRule rep = null;\r
- /** Create and compile both a Regex and a ReplaceRule.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
- */\r
- public Regex(String s, String rp)\r
- {\r
- this(s);\r
- rep = ReplaceRule.perlCode(rp);\r
- }\r
-\r
- /** Create and compile a Regex, but give it the ReplaceRule\r
- specified. This allows the user finer control of the\r
- Replacement process, if that is desired.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
- */\r
- public Regex(String s, ReplaceRule rp)\r
- {\r
- this(s);\r
- rep = rp;\r
- }\r
-\r
- /** Change the ReplaceRule of this Regex by compiling\r
- a new one using String rp. */\r
- public void setReplaceRule(String rp)\r
- {\r
- rep = ReplaceRule.perlCode(rp);\r
- repr = null; // Clear Replacer history\r
- }\r
-\r
- /** Change the ReplaceRule of this Regex to rp. */\r
- public void setReplaceRule(ReplaceRule rp)\r
- {\r
- rep = rp;\r
- }\r
-\r
- /** Test to see if a custom defined rule exists.\r
- @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator)\r
- */\r
- public static boolean isDefined(String nm)\r
- {\r
- return validators.get(nm) != null;\r
- }\r
-\r
- /** Removes a custom defined rule.\r
- @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator)\r
- */\r
- public static void undefine(String nm)\r
- {\r
- validators.remove(nm);\r
- }\r
-\r
- /** Defines a method to create a new rule. See test/deriv2.java\r
- and test/deriv3.java for examples of how to use it. */\r
- public static void define(String nm, String pat, Validator v)\r
- {\r
- v.pattern = pat;\r
- validators.put(nm, v);\r
- }\r
-\r
- /** Defines a shorthand for a pattern. The pattern will be\r
- invoked by a string that has the form "(??"+nm+")".\r
- */\r
- public static void define(String nm, String pat)\r
- {\r
- validators.put(nm, pat);\r
- }\r
-\r
- /** Get the current ReplaceRule. */\r
- public ReplaceRule getReplaceRule()\r
- {\r
- return rep;\r
- }\r
-\r
- Replacer repr = null;\r
- final Replacer _getReplacer()\r
- {\r
- return repr == null ? repr = new Replacer() : repr;\r
- }\r
-\r
- public Replacer getReplacer()\r
- {\r
- if (repr == null)\r
- {\r
- repr = new Replacer();\r
- }\r
- repr.rh.me = this;\r
- repr.rh.prev = null;\r
- return repr;\r
- }\r
-\r
- /** Replace the first occurence of this pattern in String s\r
- according to the ReplaceRule.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#getReplaceRule()\r
- */\r
- public String replaceFirst(String s)\r
- {\r
- return _getReplacer().replaceFirstRegion(s, this, 0, s.length()).toString();\r
- }\r
-\r
- /** Replace the first occurence of this pattern in String s\r
- beginning with position pos according to the ReplaceRule.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#getReplaceRule()\r
- */\r
- public String replaceFirstFrom(String s, int pos)\r
- {\r
- return _getReplacer().replaceFirstRegion(s, this, pos, s.length()).toString();\r
- }\r
-\r
- /** Replace the first occurence of this pattern in String s\r
- beginning with position start and ending with end\r
- according to the ReplaceRule.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#getReplaceRule()\r
- */\r
- public String replaceFirstRegion(String s, int start, int end)\r
- {\r
- return _getReplacer().replaceFirstRegion(s, this, start, end).toString();\r
- }\r
-\r
- /** Replace all occurences of this pattern in String s\r
- according to the ReplaceRule.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#getReplaceRule()\r
- */\r
- public String replaceAll(String s)\r
- {\r
- return _getReplacer().replaceAllRegion(s, this, 0, s.length()).toString();\r
- }\r
-\r
- public StringLike replaceAll(StringLike s)\r
- {\r
- return _getReplacer().replaceAllRegion(s, this, 0, s.length());\r
- }\r
-\r
- /** Replace all occurences of this pattern in String s\r
- beginning with position pos according to the ReplaceRule.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#getReplaceRule()\r
- */\r
- public String replaceAllFrom(String s, int pos)\r
- {\r
- return _getReplacer().replaceAllRegion(s, this, pos, s.length()).toString();\r
- }\r
-\r
- /** Replace all occurences of this pattern in String s\r
- beginning with position start and ending with end\r
- according to the ReplaceRule.\r
- @see com.stevesoft.pat.ReplaceRule\r
- @see com.stevesoft.pat.Regex#getReplaceRule()\r
- */\r
- public String replaceAllRegion(String s, int start, int end)\r
- {\r
- return _getReplacer().replaceAllRegion(s, this, start, end).toString();\r
- }\r
-\r
- /** Essentially clones the Regex object */\r
- public Regex(Regex r)\r
- {\r
- super( (RegRes) r);\r
- dontMatchInQuotes = r.dontMatchInQuotes;\r
- esc = r.esc;\r
- ignoreCase = r.ignoreCase;\r
- gFlag = r.gFlag;\r
- if (r.rep == null)\r
- {\r
- rep = null;\r
- }\r
- else\r
- {\r
- rep = (ReplaceRule) r.rep.clone();\r
- }\r
- /* try {\r
- compile(r.toString());\r
- } catch(RegSyntax r_) {} */\r
- thePattern = r.thePattern.clone(new Hashtable());\r
- minMatch = r.minMatch;\r
- skipper = r.skipper;\r
- }\r
-\r
- /** By default,\r
- the escape character is the backslash, but you can\r
- make it anything you want by setting this variable. */\r
- public char esc = Pattern.ESC;\r
- /** This method compiles a regular expression, making it\r
- possible to call the search or matchAt methods.\r
- @exception com.stevesoft.pat.RegSyntax\r
- is thrown if a syntax error is encountered\r
- in the pattern.\r
- For example, "x{3,1}" or "*a" are not valid\r
- patterns.\r
- @see com.stevesoft.pat.Regex#search\r
- @see com.stevesoft.pat.Regex#matchAt\r
- */\r
- public void compile(String prepat)\r
- throws RegSyntax\r
- {\r
- String postpat = parsePerl.codify(prepat, true);\r
- String pat = postpat == null ? prepat : postpat;\r
- minMatch = null;\r
- ignoreCase = false;\r
- dontMatchInQuotes = false;\r
- Rthings mk = new Rthings(this);\r
- int offset = mk.val;\r
- String newpat = pat;\r
- thePattern = none;\r
- p = null;\r
- or = null;\r
- minMatch = new patInt(0);\r
- StrPos sp = new StrPos(pat, 0);\r
- if (sp.incMatch("(?e="))\r
- {\r
- char newEsc = sp.c;\r
- sp.inc();\r
- if (sp.match(')'))\r
- {\r
- newpat = reEscape(pat.substring(6),\r
- newEsc, Pattern.ESC);\r
- }\r
- }\r
- else if (esc != Pattern.ESC)\r
- {\r
- newpat = reEscape(pat, esc, Pattern.ESC);\r
- }\r
- thePattern = _compile(newpat, mk);\r
- numSubs_ = mk.val - offset;\r
- mk.set(this);\r
- }\r
-\r
- /* If a Regex is compared against a Regex, a check is\r
- done to see that the patterns are equal as well as\r
- the most recent match. If a Regex is compare with\r
- a RegRes, only the result of the most recent match\r
- is compared. */\r
- public boolean equals(Object o)\r
- {\r
- if (o instanceof Regex)\r
- {\r
- if (toString().equals(o.toString()))\r
- {\r
- return super.equals(o);\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
- }\r
- else\r
- {\r
- return super.equals(o);\r
- }\r
- }\r
-\r
- /** A clone by any other name would smell as sweet. */\r
- public Object clone()\r
- {\r
- return new Regex(this);\r
- }\r
-\r
- /** Return a clone of the underlying RegRes object. */\r
- public RegRes result()\r
- {\r
- return (RegRes)super.clone();\r
- }\r
-\r
- // prep sets global variables of class\r
- // Pattern so that it can access them\r
- // during an attempt at a match\r
- Pthings pt = new Pthings();\r
- final Pthings prep(StringLike s)\r
- {\r
- //if(gFlag)\r
- pt.lastPos = matchedTo();\r
- if (pt.lastPos < 0)\r
- {\r
- pt.lastPos = 0;\r
- }\r
- if ( (s == null ? null : s.unwrap()) != (src == null ? null : s.unwrap()))\r
- {\r
- pt.lastPos = 0;\r
- }\r
- src = s;\r
- pt.dotDoesntMatchCR = dotDoesntMatchCR && (!sFlag);\r
- pt.mFlag = (mFlag | defaultMFlag);\r
- pt.ignoreCase = ignoreCase;\r
- pt.no_check = false;\r
- if (pt.marks != null)\r
- {\r
- for (int i = 0; i < pt.marks.length; i++)\r
- {\r
- pt.marks[i] = -1;\r
- }\r
- }\r
- pt.marks = null;\r
- pt.nMarks = numSubs_;\r
- pt.src = s;\r
- if (dontMatchInQuotes)\r
- {\r
- setCbits(s, pt);\r
- }\r
- else\r
- {\r
- pt.cbits = null;\r
- }\r
- return pt;\r
- }\r
-\r
- /** Attempt to match a Pattern beginning\r
- at a specified location within the string.\r
- @see com.stevesoft.pat.Regex#search\r
- */\r
- public boolean matchAt(String s, int start_pos)\r
- {\r
- return _search(s, start_pos, start_pos);\r
- }\r
-\r
- /** Attempt to match a Pattern beginning\r
- at a specified location within the StringLike.\r
- @see com.stevesoft.pat.Regex#search\r
- */\r
- public boolean matchAt(StringLike s, int start_pos)\r
- {\r
- return _search(s, start_pos, start_pos);\r
- }\r
-\r
- /** Search through a String for the first\r
- occurrence of a match.\r
- @see com.stevesoft.pat.Regex#searchFrom\r
- @see com.stevesoft.pat.Regex#matchAt\r
- */\r
- public boolean search(String s)\r
- {\r
- if (s == null)\r
- {\r
- throw new NullPointerException("Null String Given to Regex.search");\r
- }\r
- return _search(s, 0, s.length());\r
- }\r
-\r
- public boolean search(StringLike sl)\r
- {\r
- if (sl == null)\r
- {\r
- throw new NullPointerException("Null StringLike Given to Regex.search");\r
- }\r
- return _search(sl, 0, sl.length());\r
- }\r
-\r
- public boolean reverseSearch(String s)\r
- {\r
- if (s == null)\r
- {\r
- throw new NullPointerException("Null String Given to Regex.reverseSearch");\r
- }\r
- return _reverseSearch(s, 0, s.length());\r
- }\r
-\r
- public boolean reverseSearch(StringLike sl)\r
- {\r
- if (sl == null)\r
- {\r
- throw new NullPointerException(\r
- "Null StringLike Given to Regex.reverseSearch");\r
- }\r
- return _reverseSearch(sl, 0, sl.length());\r
- }\r
-\r
- /** Search through a String for the first\r
- occurence of a match, but start at position <pre>start</pre>*/\r
- public boolean searchFrom(String s, int start)\r
- {\r
- if (s == null)\r
- {\r
- throw new NullPointerException("Null String Given to Regex.searchFrom");\r
- }\r
- return _search(s, start, s.length());\r
- }\r
-\r
- public boolean searchFrom(StringLike s, int start)\r
- {\r
- if (s == null)\r
- {\r
- throw new NullPointerException("Null String Given to Regex.searchFrom");\r
- }\r
- return _search(s, start, s.length());\r
- }\r
-\r
- /** Search through a region of a String\r
- for the first occurence of a match. */\r
- public boolean searchRegion(String s, int start, int end)\r
- {\r
- if (s == null)\r
- {\r
- throw new NullPointerException("Null String Given to Regex.searchRegion");\r
- }\r
- return _search(s, start, end);\r
- }\r
-\r
- /** Set this to change the default behavior of the "." pattern.\r
- By default it now matches perl's behavior and fails to\r
- match the '\n' character. */\r
- public static boolean dotDoesntMatchCR = true;\r
- StringLike gFlags;\r
- int gFlagto = 0;\r
- boolean gFlag = false;\r
- /** Set the 'g' flag */\r
- public void setGFlag(boolean b)\r
- {\r
- gFlag = b;\r
- }\r
-\r
- /** Get the state of the 'g' flag. */\r
- public boolean getGFlag()\r
- {\r
- return gFlag;\r
- }\r
-\r
- boolean sFlag = false;\r
- /** Get the state of the sFlag */\r
- public boolean getSFlag()\r
- {\r
- return sFlag;\r
- }\r
-\r
- boolean mFlag = false;\r
- /** Get the state of the sFlag */\r
- public boolean getMFlag()\r
- {\r
- return mFlag;\r
- }\r
-\r
- final boolean _search(String s, int start, int end)\r
- {\r
- return _search(new StringWrap(s), start, end);\r
- }\r
-\r
- final boolean _search(StringLike s, int start, int end)\r
- {\r
- if (gFlag && gFlagto > 0 && gFlags != null && s.unwrap() == gFlags.unwrap())\r
- {\r
- start = gFlagto;\r
- }\r
- gFlags = null;\r
-\r
- Pthings pt = prep(s);\r
-\r
- int up = (minMatch == null ? end : end - minMatch.i);\r
-\r
- if (up < start && end >= start)\r
- {\r
- up = start;\r
- }\r
-\r
- if (skipper == null)\r
- {\r
- for (int i = start; i <= up; i++)\r
- {\r
- charsMatched_ = thePattern.matchAt(s, i, pt);\r
- if (charsMatched_ >= 0)\r
- {\r
- matchFrom_ = thePattern.mfrom;\r
- marks = pt.marks;\r
- gFlagto = matchFrom_ + charsMatched_;\r
- gFlags = s;\r
- return didMatch_ = true;\r
+</pre>\r
+<p>\r
+Differences between this package and perl5:<br>\r
+The extended Pattern for setting flags, is now supported,\r
+but the flags are different. "(?i)" tells the pattern to\r
+ignore case, "(?Q)" sets the "dontMatchInQuotes" flag, and\r
+"(?iQ)" sets them both. You can change the escape character.\r
+The pattern <pre>(?e=#)#d+</pre> is the same as <pre>\d+</pre>,\r
+but note that the sequence <pre>(?e=#)</pre> <b>must</b> occur\r
+at the very beginning of the pattern. There may be other small\r
+differences as well. I will either make my package conform\r
+or note them as I become aware of them.\r
+<p>\r
+This package supports additional patterns not in perl5:\r
+<center>\r
+<table border=1>\r
+<tr><td>(?@())</td><td>Group</td><td>This matches all characters between\r
+the '(' character and the balancing ')' character. Thus, it will\r
+match "()" as well as "(())". The balancing characters are\r
+arbitrary, thus (?@{}) matches on "{}" and "{{}}".</td>\r
+<tr><td>(?<1)</td><td>Backup</td><td>Moves the pointer backwards within the text.\r
+This allows you to make a "look behind." It fails if it\r
+attempts to move to a position before the beginning of the string.\r
+"x(?<1)" is equivalent to "(?=x)". The number, 1 in this example,\r
+is the number of characters to move backwards.</td>\r
+</table>\r
+</center>\r
+</dl>\r
+@author Steven R. Brandt\r
+@version package com.stevesoft.pat, release 1.5.3\r
+@see Pattern\r
+*/\r
+public class Regex extends RegRes implements FilenameFilter {\r
+ /** BackRefOffset gives the identity number of the first\r
+ pattern. Version 1.0 used zero, version 1.1 uses 1 to be\r
+ more compatible with perl. */\r
+ static int BackRefOffset = 1;\r
+ private static Pattern none = new NoPattern();\r
+ Pattern thePattern = none;\r
+ patInt minMatch = new patInt(0);\r
+\r
+ static Hashtable validators = new Hashtable();\r
+ static {\r
+ define("p","(?>1)",new UnicodePunct());\r
+ define("P","(?>1)",new NUnicodePunct());\r
+ define("s","(?>1)",new UnicodeWhite());\r
+ define("S","(?>1)",new NUnicodeWhite());\r
+ define("w","(?>1)",new UnicodeW());\r
+ define("W","(?>1)",new NUnicodeW());\r
+ define("d","(?>1)",new UnicodeDigit());\r
+ define("D","(?>1)",new NUnicodeDigit());\r
+ define("m","(?>1)",new UnicodeMath());\r
+ define("M","(?>1)",new NUnicodeMath());\r
+ define("c","(?>1)",new UnicodeCurrency());\r
+ define("C","(?>1)",new NUnicodeCurrency());\r
+ define("a","(?>1)",new UnicodeAlpha());\r
+ define("A","(?>1)",new NUnicodeAlpha());\r
+ define("uc","(?>1)",new UnicodeUpper());\r
+ define("lc","(?>1)",new UnicodeLower());\r
+ }\r
+\r
+ /** Set the dontMatch in quotes flag. */\r
+ public void setDontMatchInQuotes(boolean b) {\r
+ dontMatchInQuotes = b;\r
+ }\r
+ /** Find out if the dontMatchInQuotes flag is enabled. */\r
+ public boolean getDontMatchInQuotes() {\r
+ return dontMatchInQuotes;\r
+ }\r
+ boolean dontMatchInQuotes = false;\r
+\r
+ /** Set the state of the ignoreCase flag. If set to true, then\r
+ the pattern matcher will ignore case when searching for a\r
+ match. */\r
+ public void setIgnoreCase(boolean b) {\r
+ ignoreCase = b;\r
+ }\r
+ /** Get the state of the ignoreCase flag. Returns true if we\r
+ are ignoring the case of the pattern, false otherwise. */\r
+ public boolean getIgnoreCase() {\r
+ return ignoreCase;\r
+ }\r
+ boolean ignoreCase = false;\r
+\r
+ static boolean defaultMFlag = false;\r
+ /** Set the default value of the m flag. If it\r
+ is set to true, then the MFlag will be on\r
+ for any regex search executed. */\r
+ public static void setDefaultMFlag(boolean mFlag) {\r
+ defaultMFlag = mFlag;\r
+ }\r
+ /** Get the default value of the m flag. If it\r
+ is set to true, then the MFlag will be on\r
+ for any regex search executed. */\r
+ public static boolean getDefaultMFlag() {\r
+ return defaultMFlag;\r
+ }\r
+\r
+ /** Initializes the object without a Pattern. To supply a Pattern\r
+ use compile(String s).\r
+ @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+ */\r
+ public Regex() {}\r
+ /** Create and compile a Regex, but do not throw any exceptions.\r
+ If you wish to have exceptions thrown for syntax errors,\r
+ you must use the Regex(void) constructor to create the\r
+ Regex object, and then call the compile method. Therefore, you\r
+ should only call this method when you know your pattern is right.\r
+ I will probably become more like\r
+ @see com.stevesoft.pat.Regex#search(java.lang.String)\r
+ @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+ */\r
+ public Regex(String s) {\r
+ try {\r
+ compile(s);\r
+ } catch(RegSyntax rs) {}\r
+ }\r
+\r
+ ReplaceRule rep = null;\r
+ /** Create and compile both a Regex and a ReplaceRule.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+ */\r
+ public Regex(String s,String rp) {\r
+ this(s);\r
+ rep = ReplaceRule.perlCode(rp);\r
+ }\r
+ /** Create and compile a Regex, but give it the ReplaceRule\r
+ specified. This allows the user finer control of the\r
+ Replacement process, if that is desired.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#compile(java.lang.String)\r
+ */\r
+ public Regex(String s,ReplaceRule rp) {\r
+ this(s);\r
+ rep = rp;\r
+ }\r
+\r
+ /** Change the ReplaceRule of this Regex by compiling\r
+ a new one using String rp. */\r
+ public void setReplaceRule(String rp) {\r
+ rep = ReplaceRule.perlCode(rp);\r
+ repr = null; // Clear Replacer history\r
+ }\r
+\r
+ /** Change the ReplaceRule of this Regex to rp. */\r
+ public void setReplaceRule(ReplaceRule rp) {\r
+ rep = rp;\r
+ }\r
+ /** Test to see if a custom defined rule exists.\r
+ @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator)\r
+ */\r
+ public static boolean isDefined(String nm) {\r
+ return validators.get(nm) != null;\r
+ }\r
+ /** Removes a custom defined rule.\r
+ @see com.stevesoft.pat#define(java.lang.String,java.lang.String,Validator)\r
+ */\r
+ public static void undefine(String nm) {\r
+ validators.remove(nm);\r
+ }\r
+ /** Defines a method to create a new rule. See test/deriv2.java\r
+ and test/deriv3.java for examples of how to use it. */\r
+ public static void define(String nm,String pat,Validator v) {\r
+ v.pattern = pat;\r
+ validators.put(nm,v);\r
+ }\r
+ /** Defines a shorthand for a pattern. The pattern will be\r
+ invoked by a string that has the form "(??"+nm+")".\r
+ */\r
+ public static void define(String nm,String pat) {\r
+ validators.put(nm,pat);\r
+ }\r
+\r
+ /** Get the current ReplaceRule. */\r
+ public ReplaceRule getReplaceRule() { return rep; }\r
+\r
+ Replacer repr = null;\r
+ final Replacer _getReplacer() {\r
+ return repr==null ? repr=new Replacer() : repr;\r
+ }\r
+ public Replacer getReplacer() {\r
+ if(repr == null)\r
+ repr = new Replacer();\r
+ repr.rh.me = this;\r
+ repr.rh.prev = null;\r
+ return repr;\r
+ }\r
+ /** Replace the first occurence of this pattern in String s\r
+ according to the ReplaceRule.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#getReplaceRule()\r
+ */\r
+ public String replaceFirst(String s) {\r
+ return _getReplacer().replaceFirstRegion(s,this,0,s.length()).toString();\r
+ }\r
+ /** Replace the first occurence of this pattern in String s\r
+ beginning with position pos according to the ReplaceRule.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#getReplaceRule()\r
+ */\r
+ public String replaceFirstFrom(String s,int pos) {\r
+ return _getReplacer().replaceFirstRegion(s,this,pos,s.length()).toString();\r
+ }\r
+ /** Replace the first occurence of this pattern in String s\r
+ beginning with position start and ending with end\r
+ according to the ReplaceRule.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#getReplaceRule()\r
+ */\r
+ public String replaceFirstRegion(String s,int start,int end) {\r
+ return _getReplacer().replaceFirstRegion(s,this,start,end).toString();\r
+ }\r
+\r
+ /** Replace all occurences of this pattern in String s\r
+ according to the ReplaceRule.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#getReplaceRule()\r
+ */\r
+ public String replaceAll(String s) {\r
+ return _getReplacer().replaceAllRegion(s,this,0,s.length()).toString();\r
+ }\r
+ public StringLike replaceAll(StringLike s) {\r
+ return _getReplacer().replaceAllRegion(s,this,0,s.length());\r
+ }\r
+ /** Replace all occurences of this pattern in String s\r
+ beginning with position pos according to the ReplaceRule.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#getReplaceRule()\r
+ */\r
+ public String replaceAllFrom(String s,int pos) {\r
+ return _getReplacer().replaceAllRegion(s,this,pos,s.length()).toString();\r
+ }\r
+ /** Replace all occurences of this pattern in String s\r
+ beginning with position start and ending with end\r
+ according to the ReplaceRule.\r
+ @see com.stevesoft.pat.ReplaceRule\r
+ @see com.stevesoft.pat.Regex#getReplaceRule()\r
+ */\r
+ public String replaceAllRegion(String s,int start,int end) {\r
+ return _getReplacer().replaceAllRegion(s,this,start,end).toString();\r
+ }\r
+\r
+\r
+ /** Essentially clones the Regex object */\r
+ public Regex(Regex r) {\r
+ super((RegRes)r);\r
+ dontMatchInQuotes = r.dontMatchInQuotes;\r
+ esc = r.esc;\r
+ ignoreCase = r.ignoreCase;\r
+ gFlag = r.gFlag;\r
+ if(r.rep==null)\r
+ rep = null;\r
+ else\r
+ rep = (ReplaceRule)r.rep.clone();\r
+ /* try {\r
+ compile(r.toString());\r
+ } catch(RegSyntax r_) {} */\r
+ thePattern = r.thePattern.clone(new Hashtable());\r
+ minMatch = r.minMatch;\r
+ skipper = r.skipper;\r
+ }\r
+\r
+ /** By default,\r
+ the escape character is the backslash, but you can\r
+ make it anything you want by setting this variable. */\r
+ public char esc = Pattern.ESC;\r
+ /** This method compiles a regular expression, making it\r
+ possible to call the search or matchAt methods.\r
+ @exception com.stevesoft.pat.RegSyntax\r
+ is thrown if a syntax error is encountered\r
+ in the pattern.\r
+ For example, "x{3,1}" or "*a" are not valid\r
+ patterns.\r
+ @see com.stevesoft.pat.Regex#search\r
+ @see com.stevesoft.pat.Regex#matchAt\r
+ */\r
+ public void compile(String prepat) throws RegSyntax {\r
+ String postpat = parsePerl.codify(prepat,true);\r
+ String pat = postpat==null ? prepat : postpat;\r
+ minMatch = null;\r
+ ignoreCase = false;\r
+ dontMatchInQuotes = false;\r
+ Rthings mk = new Rthings(this);\r
+ int offset = mk.val;\r
+ String newpat = pat;\r
+ thePattern = none;\r
+ p = null;\r
+ or = null;\r
+ minMatch = new patInt(0);\r
+ StrPos sp = new StrPos(pat,0);\r
+ if(sp.incMatch("(?e=")) {\r
+ char newEsc = sp.c;\r
+ sp.inc();\r
+ if(sp.match(')'))\r
+ newpat = reEscape(pat.substring(6),\r
+ newEsc,Pattern.ESC);\r
+ } else if(esc != Pattern.ESC)\r
+ newpat = reEscape(pat,esc,Pattern.ESC);\r
+ thePattern = _compile(newpat,mk);\r
+ numSubs_ = mk.val-offset;\r
+ mk.set(this);\r
+ }\r
+\r
+ /* If a Regex is compared against a Regex, a check is\r
+ done to see that the patterns are equal as well as\r
+ the most recent match. If a Regex is compare with\r
+ a RegRes, only the result of the most recent match\r
+ is compared. */\r
+ public boolean equals(Object o) {\r
+ if(o instanceof Regex) {\r
+ if(toString().equals(o.toString()))\r
+ return super.equals(o);\r
+ else\r
+ return false;\r
+ } else return super.equals(o);\r
+ }\r
+\r
+ /** A clone by any other name would smell as sweet. */\r
+ public Object clone() {\r
+ return new Regex(this);\r
+ }\r
+ /** Return a clone of the underlying RegRes object. */\r
+ public RegRes result() {\r
+ return (RegRes)super.clone();\r
+ }\r
+\r
+ // prep sets global variables of class\r
+ // Pattern so that it can access them\r
+ // during an attempt at a match\r
+ Pthings pt = new Pthings();\r
+ final Pthings prep(StringLike s) {\r
+ //if(gFlag)\r
+ pt.lastPos = matchedTo();\r
+ if(pt.lastPos < 0) pt.lastPos = 0;\r
+ if( (s==null ? null : s.unwrap()) != (src==null ? null : s.unwrap()) )\r
+ pt.lastPos = 0;\r
+ src = s;\r
+ pt.dotDoesntMatchCR=dotDoesntMatchCR && (!sFlag);\r
+ pt.mFlag = (mFlag | defaultMFlag);\r
+ pt.ignoreCase = ignoreCase;\r
+ pt.no_check = false;\r
+ if(pt.marks != null)\r
+ for(int i=0;i<pt.marks.length;i++)\r
+ pt.marks[i]=-1;\r
+ pt.marks = null;\r
+ pt.nMarks = numSubs_;\r
+ pt.src = s;\r
+ if(dontMatchInQuotes)\r
+ setCbits(s,pt);\r
+ else\r
+ pt.cbits = null;\r
+ return pt;\r
+ }\r
+ /** Attempt to match a Pattern beginning\r
+ at a specified location within the string.\r
+ @see com.stevesoft.pat.Regex#search\r
+ */\r
+ public boolean matchAt(String s,int start_pos) {\r
+ return _search(s,start_pos,start_pos);\r
+ }\r
+ /** Attempt to match a Pattern beginning\r
+ at a specified location within the StringLike.\r
+ @see com.stevesoft.pat.Regex#search\r
+ */\r
+ public boolean matchAt(StringLike s,int start_pos) {\r
+ return _search(s,start_pos,start_pos);\r
+ }\r
+\r
+\r
+ /** Search through a String for the first\r
+ occurrence of a match.\r
+ @see com.stevesoft.pat.Regex#searchFrom\r
+ @see com.stevesoft.pat.Regex#matchAt\r
+ */\r
+ public boolean search(String s) {\r
+ if(s==null)\r
+ throw new NullPointerException("Null String Given to Regex.search");\r
+ return _search(s,0,s.length());\r
+ }\r
+ public boolean search(StringLike sl) {\r
+ if(sl==null)\r
+ throw new NullPointerException("Null StringLike Given to Regex.search");\r
+ return _search(sl,0,sl.length());\r
+ }\r
+ public boolean reverseSearch(String s) {\r
+ if(s==null)\r
+ throw new NullPointerException("Null String Given to Regex.reverseSearch");\r
+ return _reverseSearch(s,0,s.length());\r
+ }\r
+ public boolean reverseSearch(StringLike sl) {\r
+ if(sl==null)\r
+ throw new NullPointerException("Null StringLike Given to Regex.reverseSearch");\r
+ return _reverseSearch(sl,0,sl.length());\r
+ }\r
+ /** Search through a String for the first\r
+ occurence of a match, but start at position <pre>start</pre>*/\r
+ public boolean searchFrom(String s,int start) {\r
+ if(s==null)\r
+ throw new NullPointerException("Null String Given to Regex.searchFrom");\r
+ return _search(s,start,s.length());\r
+ }\r
+ public boolean searchFrom(StringLike s,int start) {\r
+ if(s==null)\r
+ throw new NullPointerException("Null String Given to Regex.searchFrom");\r
+ return _search(s,start,s.length());\r
+ }\r
+ /** Search through a region of a String\r
+ for the first occurence of a match. */\r
+ public boolean searchRegion(String s,int start,int end) {\r
+ if(s==null)\r
+ throw new NullPointerException("Null String Given to Regex.searchRegion");\r
+ return _search(s,start,end);\r
+ }\r
+ /** Set this to change the default behavior of the "." pattern.\r
+ By default it now matches perl's behavior and fails to\r
+ match the '\n' character. */\r
+ public static boolean dotDoesntMatchCR = true;\r
+ StringLike gFlags;\r
+ int gFlagto = 0;\r
+ boolean gFlag = false;\r
+ /** Set the 'g' flag */\r
+ public void setGFlag(boolean b) {\r
+ gFlag = b;\r
+ }\r
+ /** Get the state of the 'g' flag. */\r
+ public boolean getGFlag() {\r
+ return gFlag;\r
+ }\r
+ boolean sFlag = false;\r
+ /** Get the state of the sFlag */\r
+ public boolean getSFlag() {\r
+ return sFlag;\r
+ }\r
+ boolean mFlag = false;\r
+ /** Get the state of the sFlag */\r
+ public boolean getMFlag() {\r
+ return mFlag;\r
+ }\r
+\r
+ final boolean _search(String s,int start,int end) {\r
+ return _search(new StringWrap(s),start,end);\r
+ }\r
+ final boolean _search(StringLike s,int start,int end) {\r
+ if(gFlag && gFlagto > 0 && gFlags!=null && s.unwrap()==gFlags.unwrap())\r
+ start = gFlagto;\r
+ gFlags = null;\r
+\r
+ Pthings pt=prep(s);\r
+\r
+ int up = (minMatch == null ? end : end-minMatch.i);\r
+\r
+ if(up < start && end >= start) up = start;\r
+\r
+ if(skipper == null) {\r
+ for(int i=start;i<=up;i++) {\r
+ charsMatched_ = thePattern.matchAt(s,i,pt);\r
+ if(charsMatched_ >= 0) {\r
+ matchFrom_ = thePattern.mfrom;\r
+ marks = pt.marks;\r
+ gFlagto = matchFrom_+charsMatched_;\r
+ gFlags = s;\r
+ return didMatch_=true;\r
+ }\r
+ }\r
+ } else {\r
+ pt.no_check = true;\r
+ for(int i=start;i<=up;i++) {\r
+ i = skipper.find(src,i,up);\r
+ if(i<0) {\r
+ charsMatched_ = matchFrom_ = -1;\r
+ return didMatch_ = false;\r
+ }\r
+ charsMatched_ = thePattern.matchAt(s,i,pt);\r
+ if(charsMatched_ >= 0) {\r
+ matchFrom_ = thePattern.mfrom;\r
+ marks = pt.marks;\r
+ gFlagto = matchFrom_+charsMatched_;\r
+ gFlags = s;\r
+ return didMatch_=true;\r
+ }\r
+ }\r
+ }\r
+ return didMatch_=false;\r
+ }\r
+ /*final boolean _search(LongStringLike s,long start,long end) {\r
+ if(gFlag && gFlagto > 0 && s==gFlags)\r
+ start = gFlagto;\r
+ gFlags = null;\r
+\r
+ Pthings pt=prep(s);\r
+\r
+ int up = end;//(minMatch == null ? end : end-minMatch.i);\r
+\r
+ if(up < start && end >= start) up = start;\r
+\r
+ if(skipper == null) {\r
+ for(long i=start;i<=up;i++) {\r
+ charsMatched_ = thePattern.matchAt(s,i,pt);\r
+ if(charsMatched_ >= 0) {\r
+ matchFrom_ = thePattern.mfrom;\r
+ marks = pt.marks;\r
+ gFlagto = matchFrom_+charsMatched_;\r
+ return didMatch_=true;\r
+ }\r
+ }\r
+ } else {\r
+ pt.no_check = true;\r
+ for(long i=start;i<=up;i++) {\r
+ i = skipper.find(src,i,up);\r
+ if(i<0) {\r
+ charsMatched_ = matchFrom_ = -1;\r
+ return didMatch_ = false;\r
+ }\r
+ charsMatched_ = thePattern.matchAt(s,i,pt);\r
+ if(charsMatched_ >= 0) {\r
+ matchFrom_ = thePattern.mfrom;\r
+ marks = pt.marks;\r
+ gFlagto = matchFrom_+charsMatched_;\r
+ gFlags = s;\r
+ return didMatch_=true;\r
+ } else {\r
+ i = s.adjustIndex(i);\r
+ up = s.adjustEnd(i);\r
+ }\r
+ }\r
+ }\r
+ return didMatch_=false;\r
+ }*/\r
+\r
+ boolean _reverseSearch(String s,int start,int end) {\r
+ return _reverseSearch(new StringWrap(s),start,end);\r
+ }\r
+ boolean _reverseSearch(StringLike s,int start,int end) {\r
+ if(gFlag && gFlagto > 0 && s.unwrap()==gFlags.unwrap())\r
+ end = gFlagto;\r
+ gFlags = null;\r
+ Pthings pt=prep(s);\r
+ for(int i=end;i>=start;i--) {\r
+ charsMatched_ = thePattern.matchAt(s,i,pt);\r
+ if(charsMatched_ >= 0) {\r
+ matchFrom_ = thePattern.mfrom;\r
+ marks = pt.marks;\r
+ gFlagto = matchFrom_-1;\r
+ gFlags = s;\r
+ return didMatch_=true;\r
+ }\r
+ }\r
+ return didMatch_=false;\r
+ }\r
+\r
+ // This routine sets the cbits variable\r
+ // of class Pattern. Cbits is true for\r
+ // the bit corresponding to a character inside\r
+ // a set of quotes.\r
+ static StringLike lasts=null;\r
+ static BitSet lastbs=null;\r
+ static void setCbits(StringLike s,Pthings pt) {\r
+ if(s == lasts) {\r
+ pt.cbits = lastbs;\r
+ return;\r