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
10 import jalview.util.MessageManager;
\r
15 Shareware: package pat
\r
16 <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>
\r
19 * Class Pattern is the base class on which all the other pattern elements are
\r
23 public abstract class Pattern
\r
26 * The ESC character, the user can provide his own value for the escape
\r
27 * character through regex.esc
\r
29 public final static char ESC = '\\';
\r
31 final static String PROTECT_THESE = "[]{}(),$,-\"^.";
\r
34 * The interal match function, it must be provided by any class which wishes
\r
35 * to extend Pattern.
\r
37 public abstract int matchInternal(int i, Pthings p);
\r
39 public abstract String toString();
\r
41 // Class Pattern is a singly linked list
\r
42 // chained together by member next. The member
\r
43 // parent is used so that sub patterns can access
\r
44 // the chain they are branching from.
\r
45 Pattern next = null, parent = null;
\r
48 * This gets the next element of a Pattern that we wish to match. If we are at
\r
49 * the end of a subchain of patterns, it will return us to the parent chain.
\r
51 public Pattern getNext()
\r
53 return next != null ? next : (parent == null ? null : parent.getNext());
\r
57 * Call this method if you have a pattern element that takes a sub pattern
\r
58 * (such as Or), and after you have added a sub pattern to the current pattern
\r
61 public void setParent(Pattern p)
\r
74 * This determines if the remainder of a Pattern matches. Type "return
\r
75 * nextMatch" from within matchInternal if the current Pattern matches.
\r
76 * Otherwise, return a -1.
\r
78 public int nextMatch(int i, Pthings pt)
\r
80 Pattern p = getNext();
\r
82 * if(p == null) return i; return p.matchInternal(i,pt);
\r
84 return p == null ? i : p.matchInternal(i, pt);
\r
88 * This is a toString() for the remainder of the Pattern elements after this
\r
89 * one. use this when overriding toString(). Called from within toString().
\r
91 public String nextString()
\r
97 return next.toString();
\r
100 /** a method to detect whether char c is in String s */
\r
101 final static boolean inString(char c, String s)
\r
104 for (i = 0; i < s.length(); i++)
\r
106 if (s.charAt(i) == c)
\r
115 * A method to create a string that protects the characters listed in
\r
116 * PROTECT_THESE by prepending the esc character. The esc character itself is
\r
117 * automatically protected.
\r
119 final static String protect(String s, String PROTECT_THESE, char esc)
\r
122 javajs.util.SB sb = new javajs.util.SB();
\r
123 String p = PROTECT_THESE + esc;
\r
124 for (i = 0; i < s.length(); i++)
\r
126 char c = s.charAt(i);
\r
127 if (inString(c, p))
\r
133 return sb.toString();
\r
137 * This can be used to perform a match test from within class Pattern.
\r
139 public int match(StringLike s, Pthings pt)
\r
141 return matchAt(s, 0, pt);
\r
145 * This can be used to perform a match test from within class Pattern.
\r
147 public int matchAt(StringLike s, int i, Pthings pt)
\r
150 int r = matchInternal(i, pt);
\r
155 mfrom = r < i ? r + 1 : i;
\r
156 return r < i ? i - r - 1 : r - i;
\r
161 // Detect masked characters
\r
162 final boolean Masked(int i, Pthings pt)
\r
164 return pt.cbits == null ? false : pt.cbits.get(i);
\r
167 /** add a Pattern to the singly-linked Pattern chain. */
\r
168 public Pattern add(Pattern p)
\r
188 * The minimum number of characters which this pattern element can match.
\r
190 public patInt minChars()
\r
192 return new patInt(0);
\r
196 * The maximum number of characters which this pattern element can match.
\r
198 public patInt maxChars()
\r
200 return new patInf();
\r
203 /** return minimum number of characters in pattern */
\r
204 public final patInt countMinChars()
\r
207 patInt sum = new patInt(0);
\r
210 sum.pluseq(p.minChars());
\r
216 /** return maximum number of characters in pattern */
\r
217 public final patInt countMaxChars()
\r
220 patInt sum = new patInt(0);
\r
223 sum.pluseq(p.maxChars());
\r
229 // This method is only needed by Multi_stage2 so far...
\r
230 // the reason is that it may try something else after a
\r
231 // match succeeds. OrMark will only record the last thing
\r
232 // tried in marks, so we need to backup the result of the
\r
233 // last successful match and restore it if the next one
\r
234 // does not succeed.
\r
235 final int testMatch(Pattern p, int pos, Pthings pt)
\r
238 if (pt.marks != null)
\r
242 tab = new int[pt.marks.length];
\r
243 for (int i = 0; i < tab.length; i++)
\r
245 tab[i] = pt.marks[i];
\r
247 } catch (Throwable t)
\r
251 int ret = p.matchInternal(pos, pt);
\r
260 * Clones this pattern elements without cloning others in the linked list.
\r
262 Pattern clone1(Hashtable h)
\r
264 throw new Error(MessageManager.formatMessage("error.no_such_method_as_clone1_for", new String[]{getClass().getName()}));
\r
267 Pattern clone(Hashtable h)
\r
269 Pattern p = (Pattern) h.get(this);
\r
277 throw new Error(MessageManager.getString("error.null_from_clone1"));
\r
283 p.next = next.clone(h);
\r
285 if (parent != null)
\r
287 p.parent = parent.clone(h);
\r
292 public boolean equals(Object o)
\r