2 // This software is now distributed according to
\r
3 // the Lesser Gnu Public License. Please see
\r
4 // http://www.gnu.org/copyleft/lesser.txt for
\r
6 // -- Happy Computing!
\r
8 package com.stevesoft.pat;
\r
13 Shareware: package pat
\r
14 <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>
\r
17 Class Pattern is the base class on which all the other pattern
\r
18 elements are built. */
\r
20 public abstract class Pattern
\r
22 /** The ESC character, the user can provide his own value
\r
23 for the escape character through regex.esc */
\r
24 public final static char ESC = '\\';
\r
25 final static String PROTECT_THESE = "[]{}(),$,-\"^.";
\r
27 /** The interal match function, it must be provided by any
\r
28 class which wishes to extend Pattern. */
\r
29 public abstract int matchInternal(int i, Pthings p);
\r
31 public abstract String toString();
\r
33 // Class Pattern is a singly linked list
\r
34 // chained together by member next. The member
\r
35 // parent is used so that sub patterns can access
\r
36 // the chain they are branching from.
\r
37 Pattern next = null, parent = null;
\r
39 /** This gets the next element of a Pattern that
\r
40 we wish to match. If we are at the end of a
\r
41 subchain of patterns, it will return us to the
\r
43 public Pattern getNext()
\r
45 return next != null ? next :
\r
46 (parent == null ? null : parent.getNext());
\r
49 /** Call this method if you have a pattern element that
\r
50 takes a sub pattern (such as Or), and
\r
51 after you have added a sub pattern to the current
\r
53 public void setParent(Pattern p)
\r
65 /** This determines if the remainder of a Pattern
\r
66 matches. Type "return nextMatch" from within
\r
67 matchInternal if the current
\r
68 Pattern matches. Otherwise, return a -1.*/
\r
69 public int nextMatch(int i, Pthings pt)
\r
71 Pattern p = getNext();
\r
72 /*if(p == null) return i;
\r
73 return p.matchInternal(i,pt);*/
\r
74 return p == null ? i : p.matchInternal(i, pt);
\r
77 /** This is a toString() for the remainder
\r
78 of the Pattern elements after this one.
\r
79 use this when overriding toString(). Called from
\r
80 within toString(). */
\r
81 public String nextString()
\r
87 return next.toString();
\r
90 /** a method to detect whether char c is in String s */
\r
91 final static boolean inString(char c, String s)
\r
94 for (i = 0; i < s.length(); i++)
\r
96 if (s.charAt(i) == c)
\r
104 /** A method to create a string that protects the characters
\r
105 listed in PROTECT_THESE by prepending the esc character.
\r
106 The esc character itself is automatically protected. */
\r
108 String protect(String s, String PROTECT_THESE, char esc)
\r
111 StringBuffer sb = new StringBuffer();
\r
112 String p = PROTECT_THESE + esc;
\r
113 for (i = 0; i < s.length(); i++)
\r
115 char c = s.charAt(i);
\r
116 if (inString(c, p))
\r
122 return sb.toString();
\r
125 /** This can be used to perform a match test from
\r
126 within class Pattern. */
\r
127 public int match(StringLike s, Pthings pt)
\r
129 return matchAt(s, 0, pt);
\r
132 /** This can be used to perform a match test from
\r
133 within class Pattern. */
\r
134 public int matchAt(StringLike s, int i, Pthings pt)
\r
137 int r = matchInternal(i, pt);
\r
142 mfrom = r < i ? r + 1 : i;
\r
143 return r < i ? i - r - 1 : r - i;
\r
148 // Detect masked characters
\r
149 final boolean Masked(int i, Pthings pt)
\r
151 return pt.cbits == null ? false : pt.cbits.get(i);
\r
154 /** add a Pattern to the singly-linked Pattern chain. */
\r
155 public Pattern add(Pattern p)
\r
174 /** The minimum number of characters which
\r
175 this pattern element can match. */
\r
176 public patInt minChars()
\r
178 return new patInt(0);
\r
181 /** The maximum number of characters which
\r
182 this pattern element can match. */
\r
183 public patInt maxChars()
\r
185 return new patInf();
\r
188 /** return minimum number of characters in pattern */
\r
189 public final patInt countMinChars()
\r
192 patInt sum = new patInt(0);
\r
195 sum.pluseq(p.minChars());
\r
201 /** return maximum number of characters in pattern */
\r
202 public final patInt countMaxChars()
\r
205 patInt sum = new patInt(0);
\r
208 sum.pluseq(p.maxChars());
\r
214 // This method is only needed by Multi_stage2 so far...
\r
215 // the reason is that it may try something else after a
\r
216 // match succeeds. OrMark will only record the last thing
\r
217 // tried in marks, so we need to backup the result of the
\r
218 // last successful match and restore it if the next one
\r
219 // does not succeed.
\r
220 final int testMatch(Pattern p, int pos, Pthings pt)
\r
223 if (pt.marks != null)
\r
227 tab = new int[pt.marks.length];
\r
228 for (int i = 0; i < tab.length; i++)
\r
230 tab[i] = pt.marks[i];
\r
233 catch (Throwable t)
\r
236 int ret = p.matchInternal(pos, pt);
\r
244 /** Clones this pattern elements without cloning others in the
\r
246 Pattern clone1(Hashtable h)
\r
248 throw new Error("No such method as clone1 for " + getClass().getName());
\r
251 Pattern clone(Hashtable h)
\r
253 Pattern p = (Pattern) h.get(this);
\r
261 throw new Error("Null from clone1!");
\r
267 p.next = next.clone(h);
\r
269 if (parent != null)
\r
271 p.parent = parent.clone(h);
\r
276 public boolean equals(Object o)
\r