// -- Happy Computing!\r
//\r
package com.stevesoft.pat;\r
+\r
import java.util.*;\r
+\r
/**\r
Shareware: package pat\r
<a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
-*/ /**\r
-Class Pattern is the base class on which all the other pattern\r
-elements are built. */\r
-\r
-public abstract class Pattern {\r
- /** The ESC character, the user can provide his own value\r
- for the escape character through regex.esc */\r
- public final static char ESC = '\\';\r
- final static String PROTECT_THESE = "[]{}(),$,-\"^.";\r
-\r
- /** The interal match function, it must be provided by any\r
- class which wishes to extend Pattern. */\r
- public abstract int matchInternal(int i,Pthings p);\r
- public abstract String toString();\r
-\r
- // Class Pattern is a singly linked list\r
- // chained together by member next. The member\r
- // parent is used so that sub patterns can access\r
- // the chain they are branching from.\r
- Pattern next=null,parent=null;\r
-\r
- /** This gets the next element of a Pattern that\r
- we wish to match. If we are at the end of a\r
- subchain of patterns, it will return us to the\r
- parent chain. */\r
- public Pattern getNext() {\r
- return next != null ? next :\r
+ */\r
+/**\r
+ Class Pattern is the base class on which all the other pattern\r
+ elements are built. */\r
+\r
+public abstract class Pattern\r
+{\r
+ /** The ESC character, the user can provide his own value\r
+ for the escape character through regex.esc */\r
+ public final static char ESC = '\\';\r
+ final static String PROTECT_THESE = "[]{}(),$,-\"^.";\r
+\r
+ /** The interal match function, it must be provided by any\r
+ class which wishes to extend Pattern. */\r
+ public abstract int matchInternal(int i, Pthings p);\r
+\r
+ public abstract String toString();\r
+\r
+ // Class Pattern is a singly linked list\r
+ // chained together by member next. The member\r
+ // parent is used so that sub patterns can access\r
+ // the chain they are branching from.\r
+ Pattern next = null, parent = null;\r
+\r
+ /** This gets the next element of a Pattern that\r
+ we wish to match. If we are at the end of a\r
+ subchain of patterns, it will return us to the\r
+ parent chain. */\r
+ public Pattern getNext()\r
+ {\r
+ return next != null ? next :\r
(parent == null ? null : parent.getNext());\r
+ }\r
+\r
+ /** Call this method if you have a pattern element that\r
+ takes a sub pattern (such as Or), and\r
+ after you have added a sub pattern to the current\r
+ pattern element. */\r
+ public void setParent(Pattern p)\r
+ {\r
+ if (next != null)\r
+ {\r
+ next.setParent(p);\r
}\r
- /** Call this method if you have a pattern element that\r
- takes a sub pattern (such as Or), and\r
- after you have added a sub pattern to the current\r
- pattern element. */\r
- public void setParent(Pattern p) {\r
- if(next != null) next.setParent(p);\r
- else parent = p;\r
- }\r
- /** This determines if the remainder of a Pattern\r
- matches. Type "return nextMatch" from within\r
- matchInternal if the current\r
- Pattern matches. Otherwise, return a -1.*/\r
- public int nextMatch(int i,Pthings pt) {\r
- Pattern p = getNext();\r
- /*if(p == null) return i;\r
- return p.matchInternal(i,pt);*/\r
- return p==null ? i : p.matchInternal(i,pt);\r
- }\r
- /** This is a toString() for the remainder\r
- of the Pattern elements after this one.\r
- use this when overriding toString(). Called from\r
- within toString(). */\r
- public String nextString() {\r
- if(next == null) return "";\r
- return next.toString();\r
- }\r
-\r
- /** a method to detect whether char c is in String s */\r
- final static boolean inString(char c,String s) {\r
- int i;\r
- for(i=0;i<s.length();i++)\r
- if(s.charAt(i)==c)\r
- return true;\r
- return false;\r
- }\r
-\r
- /** A method to create a string that protects the characters\r
- listed in PROTECT_THESE by prepending the esc character.\r
- The esc character itself is automatically protected. */\r
- final static\r
- String protect(String s,String PROTECT_THESE,char esc) {\r
- int i;\r
- StringBuffer sb = new StringBuffer();\r
- String p = PROTECT_THESE+esc;\r
- for(i=0;i<s.length();i++) {\r
- char c = s.charAt(i);\r
- if(inString(c,p))\r
- sb.append(esc);\r
- sb.append(c);\r
- }\r
- return sb.toString();\r
- }\r
-\r
- /** This can be used to perform a match test from\r
- within class Pattern. */\r
- public int match(StringLike s,Pthings pt) {\r
- return matchAt(s,0,pt);\r
- }\r
- /** This can be used to perform a match test from\r
- within class Pattern. */\r
- public int matchAt(StringLike s,int i,Pthings pt) {\r
- pt.src = s;\r
- int r = matchInternal(i,pt);\r
- if(r < 0) return -1;\r
- mfrom = r<i ? r+1 : i;\r
- return r<i ? i-r-1 : r-i;\r
- }\r
- int mfrom=0;\r
-\r
- // Detect masked characters\r
- final boolean Masked(int i,Pthings pt) {\r
- return pt.cbits == null ? false : pt.cbits.get(i);\r
- }\r
-\r
- /** add a Pattern to the singly-linked Pattern chain. */\r
- public Pattern add(Pattern p) {\r
- if(next == null) {\r
- if(p==null) return this;\r
- next = p;\r
- p.parent = parent;\r
- parent = null;\r
- } else next.add(p);\r
+ else\r
+ {\r
+ parent = p;\r
+ }\r
+ }\r
+\r
+ /** This determines if the remainder of a Pattern\r
+ matches. Type "return nextMatch" from within\r
+ matchInternal if the current\r
+ Pattern matches. Otherwise, return a -1.*/\r
+ public int nextMatch(int i, Pthings pt)\r
+ {\r
+ Pattern p = getNext();\r
+ /*if(p == null) return i;\r
+ return p.matchInternal(i,pt);*/\r
+ return p == null ? i : p.matchInternal(i, pt);\r
+ }\r
+\r
+ /** This is a toString() for the remainder\r
+ of the Pattern elements after this one.\r
+ use this when overriding toString(). Called from\r
+ within toString(). */\r
+ public String nextString()\r
+ {\r
+ if (next == null)\r
+ {\r
+ return "";\r
+ }\r
+ return next.toString();\r
+ }\r
+\r
+ /** a method to detect whether char c is in String s */\r
+ final static boolean inString(char c, String s)\r
+ {\r
+ int i;\r
+ for (i = 0; i < s.length(); i++)\r
+ {\r
+ if (s.charAt(i) == c)\r
+ {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /** A method to create a string that protects the characters\r
+ listed in PROTECT_THESE by prepending the esc character.\r
+ The esc character itself is automatically protected. */\r
+ final static\r
+ String protect(String s, String PROTECT_THESE, char esc)\r
+ {\r
+ int i;\r
+ StringBuffer sb = new StringBuffer();\r
+ String p = PROTECT_THESE + esc;\r
+ for (i = 0; i < s.length(); i++)\r
+ {\r
+ char c = s.charAt(i);\r
+ if (inString(c, p))\r
+ {\r
+ sb.append(esc);\r
+ }\r
+ sb.append(c);\r
+ }\r
+ return sb.toString();\r
+ }\r
+\r
+ /** This can be used to perform a match test from\r
+ within class Pattern. */\r
+ public int match(StringLike s, Pthings pt)\r
+ {\r
+ return matchAt(s, 0, pt);\r
+ }\r
+\r
+ /** This can be used to perform a match test from\r
+ within class Pattern. */\r
+ public int matchAt(StringLike s, int i, Pthings pt)\r
+ {\r
+ pt.src = s;\r
+ int r = matchInternal(i, pt);\r
+ if (r < 0)\r
+ {\r
+ return -1;\r
+ }\r
+ mfrom = r < i ? r + 1 : i;\r
+ return r < i ? i - r - 1 : r - i;\r
+ }\r
+\r
+ int mfrom = 0;\r
+\r
+ // Detect masked characters\r
+ final boolean Masked(int i, Pthings pt)\r
+ {\r
+ return pt.cbits == null ? false : pt.cbits.get(i);\r
+ }\r
+\r
+ /** add a Pattern to the singly-linked Pattern chain. */\r
+ public Pattern add(Pattern p)\r
+ {\r
+ if (next == null)\r
+ {\r
+ if (p == null)\r
+ {\r
return this;\r
+ }\r
+ next = p;\r
+ p.parent = parent;\r
+ parent = null;\r
}\r
- /** The minimum number of characters which\r
- this pattern element can match. */\r
- public patInt minChars() { return new patInt(0); }\r
- /** The maximum number of characters which\r
- this pattern element can match. */\r
- public patInt maxChars() { return new patInf(); }\r
- /** return minimum number of characters in pattern */\r
- public final patInt countMinChars() {\r
- Pattern p = this;\r
- patInt sum = new patInt(0);\r
- while(p != null) {\r
- sum.pluseq(p.minChars());\r
- p = p.next;\r
- }\r
- return sum;\r
- }\r
- /** return maximum number of characters in pattern */\r
- public final patInt countMaxChars() {\r
- Pattern p = this;\r
- patInt sum = new patInt(0);\r
- while(p != null) {\r
- sum.pluseq(p.maxChars());\r
- p = p.next;\r
- }\r
- return sum;\r
- }\r
-\r
- // This method is only needed by Multi_stage2 so far...\r
- // the reason is that it may try something else after a\r
- // match succeeds. OrMark will only record the last thing\r
- // tried in marks, so we need to backup the result of the\r
- // last successful match and restore it if the next one\r
- // does not succeed.\r
- final int testMatch(Pattern p,int pos,Pthings pt) {\r
- int[] tab = null;\r
- if(pt.marks != null) try {\r
- tab = new int[pt.marks.length];\r
- for(int i=0;i<tab.length;i++)\r
- tab[i] = pt.marks[i];\r
- } catch(Throwable t) {}\r
- int ret = p.matchInternal(pos,pt);\r
- if(ret < 0) pt.marks = tab;\r
- return ret;\r
- }\r
-\r
- /** Clones this pattern elements without cloning others in the\r
- linked list. */\r
- Pattern clone1(Hashtable h) {\r
- throw new Error("No such method as clone1 for "+getClass().getName());\r
- }\r
- Pattern clone(Hashtable h) {\r
- Pattern p = (Pattern)h.get(this);\r
- if(p != null) {\r
- return p;\r
+ else\r
+ {\r
+ next.add(p);\r
+ }\r
+ return this;\r
+ }\r
+\r
+ /** The minimum number of characters which\r
+ this pattern element can match. */\r
+ public patInt minChars()\r
+ {\r
+ return new patInt(0);\r
+ }\r
+\r
+ /** The maximum number of characters which\r
+ this pattern element can match. */\r
+ public patInt maxChars()\r
+ {\r
+ return new patInf();\r
+ }\r
+\r
+ /** return minimum number of characters in pattern */\r
+ public final patInt countMinChars()\r
+ {\r
+ Pattern p = this;\r
+ patInt sum = new patInt(0);\r
+ while (p != null)\r
+ {\r
+ sum.pluseq(p.minChars());\r
+ p = p.next;\r
+ }\r
+ return sum;\r
+ }\r
+\r
+ /** return maximum number of characters in pattern */\r
+ public final patInt countMaxChars()\r
+ {\r
+ Pattern p = this;\r
+ patInt sum = new patInt(0);\r
+ while (p != null)\r
+ {\r
+ sum.pluseq(p.maxChars());\r
+ p = p.next;\r
+ }\r
+ return sum;\r
+ }\r
+\r
+ // This method is only needed by Multi_stage2 so far...\r
+ // the reason is that it may try something else after a\r
+ // match succeeds. OrMark will only record the last thing\r
+ // tried in marks, so we need to backup the result of the\r
+ // last successful match and restore it if the next one\r
+ // does not succeed.\r
+ final int testMatch(Pattern p, int pos, Pthings pt)\r
+ {\r
+ int[] tab = null;\r
+ if (pt.marks != null)\r
+ {\r
+ try\r
+ {\r
+ tab = new int[pt.marks.length];\r
+ for (int i = 0; i < tab.length; i++)\r
+ {\r
+ tab[i] = pt.marks[i];\r
}\r
- p=clone1(h);\r
- if(p==null)throw new Error("Null from clone1!");\r
- h.put(this,p);\r
- h.put(p,p);\r
- if(next != null) p.next = next.clone(h);\r
- if(parent != null) p.parent = parent.clone(h);\r
- return p;\r
+ }\r
+ catch (Throwable t)\r
+ {}\r
}\r
- public boolean equals(Object o) {\r
- return o == this;\r
+ int ret = p.matchInternal(pos, pt);\r
+ if (ret < 0)\r
+ {\r
+ pt.marks = tab;\r
}\r
-};\r
+ return ret;\r
+ }\r
+\r
+ /** Clones this pattern elements without cloning others in the\r
+ linked list. */\r
+ Pattern clone1(Hashtable h)\r
+ {\r
+ throw new Error("No such method as clone1 for " + getClass().getName());\r
+ }\r
+\r
+ Pattern clone(Hashtable h)\r
+ {\r
+ Pattern p = (Pattern) h.get(this);\r
+ if (p != null)\r
+ {\r
+ return p;\r
+ }\r
+ p = clone1(h);\r
+ if (p == null)\r
+ {\r
+ throw new Error("Null from clone1!");\r
+ }\r
+ h.put(this, p);\r
+ h.put(p, p);\r
+ if (next != null)\r
+ {\r
+ p.next = next.clone(h);\r
+ }\r
+ if (parent != null)\r
+ {\r
+ p.parent = parent.clone(h);\r
+ }\r
+ return p;\r
+ }\r
\r
+ public boolean equals(Object o)\r
+ {\r
+ return o == this;\r
+ }\r
+};\r