JAL-1807 still testing
[jalviewjs.git] / unused / com / stevesoft / pat / Pattern.java
1 //\r
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
5 // the details.\r
6 //    -- Happy Computing!\r
7 //\r
8 package com.stevesoft.pat;\r
9 \r
10 import jalview.util.MessageManager;\r
11 \r
12 import java.util.*;\r
13 \r
14 /**\r
15  Shareware: package pat\r
16  <a href="copyright.html">Copyright 2001, Steven R. Brandt</a>\r
17  */\r
18 /**\r
19  * Class Pattern is the base class on which all the other pattern elements are\r
20  * built.\r
21  */\r
22 \r
23 public abstract class Pattern\r
24 {\r
25   /**\r
26    * The ESC character, the user can provide his own value for the escape\r
27    * character through regex.esc\r
28    */\r
29   public final static char ESC = '\\';\r
30 \r
31   final static String PROTECT_THESE = "[]{}(),$,-\"^.";\r
32 \r
33   /**\r
34    * The interal match function, it must be provided by any class which wishes\r
35    * to extend Pattern.\r
36    */\r
37   public abstract int matchInternal(int i, Pthings p);\r
38 \r
39   public abstract String toString();\r
40 \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
46 \r
47   /**\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
50    */\r
51   public Pattern getNext()\r
52   {\r
53     return next != null ? next : (parent == null ? null : parent.getNext());\r
54   }\r
55 \r
56   /**\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
59    * element.\r
60    */\r
61   public void setParent(Pattern p)\r
62   {\r
63     if (next != null)\r
64     {\r
65       next.setParent(p);\r
66     }\r
67     else\r
68     {\r
69       parent = p;\r
70     }\r
71   }\r
72 \r
73   /**\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
77    */\r
78   public int nextMatch(int i, Pthings pt)\r
79   {\r
80     Pattern p = getNext();\r
81     /*\r
82      * if(p == null) return i; return p.matchInternal(i,pt);\r
83      */\r
84     return p == null ? i : p.matchInternal(i, pt);\r
85   }\r
86 \r
87   /**\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
90    */\r
91   public String nextString()\r
92   {\r
93     if (next == null)\r
94     {\r
95       return "";\r
96     }\r
97     return next.toString();\r
98   }\r
99 \r
100   /** a method to detect whether char c is in String s */\r
101   final static boolean inString(char c, String s)\r
102   {\r
103     int i;\r
104     for (i = 0; i < s.length(); i++)\r
105     {\r
106       if (s.charAt(i) == c)\r
107       {\r
108         return true;\r
109       }\r
110     }\r
111     return false;\r
112   }\r
113 \r
114   /**\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
118    */\r
119   final static String protect(String s, String PROTECT_THESE, char esc)\r
120   {\r
121     int i;\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
125     {\r
126       char c = s.charAt(i);\r
127       if (inString(c, p))\r
128       {\r
129         sb.appendC(esc);\r
130       }\r
131       sb.appendC(c);\r
132     }\r
133     return sb.toString();\r
134   }\r
135 \r
136   /**\r
137    * This can be used to perform a match test from within class Pattern.\r
138    */\r
139   public int match(StringLike s, Pthings pt)\r
140   {\r
141     return matchAt(s, 0, pt);\r
142   }\r
143 \r
144   /**\r
145    * This can be used to perform a match test from within class Pattern.\r
146    */\r
147   public int matchAt(StringLike s, int i, Pthings pt)\r
148   {\r
149     pt.src = s;\r
150     int r = matchInternal(i, pt);\r
151     if (r < 0)\r
152     {\r
153       return -1;\r
154     }\r
155     mfrom = r < i ? r + 1 : i;\r
156     return r < i ? i - r - 1 : r - i;\r
157   }\r
158 \r
159   int mfrom = 0;\r
160 \r
161   // Detect masked characters\r
162   final boolean Masked(int i, Pthings pt)\r
163   {\r
164     return pt.cbits == null ? false : pt.cbits.get(i);\r
165   }\r
166 \r
167   /** add a Pattern to the singly-linked Pattern chain. */\r
168   public Pattern add(Pattern p)\r
169   {\r
170     if (next == null)\r
171     {\r
172       if (p == null)\r
173       {\r
174         return this;\r
175       }\r
176       next = p;\r
177       p.parent = parent;\r
178       parent = null;\r
179     }\r
180     else\r
181     {\r
182       next.add(p);\r
183     }\r
184     return this;\r
185   }\r
186 \r
187   /**\r
188    * The minimum number of characters which this pattern element can match.\r
189    */\r
190   public patInt minChars()\r
191   {\r
192     return new patInt(0);\r
193   }\r
194 \r
195   /**\r
196    * The maximum number of characters which this pattern element can match.\r
197    */\r
198   public patInt maxChars()\r
199   {\r
200     return new patInf();\r
201   }\r
202 \r
203   /** return minimum number of characters in pattern */\r
204   public final patInt countMinChars()\r
205   {\r
206     Pattern p = this;\r
207     patInt sum = new patInt(0);\r
208     while (p != null)\r
209     {\r
210       sum.pluseq(p.minChars());\r
211       p = p.next;\r
212     }\r
213     return sum;\r
214   }\r
215 \r
216   /** return maximum number of characters in pattern */\r
217   public final patInt countMaxChars()\r
218   {\r
219     Pattern p = this;\r
220     patInt sum = new patInt(0);\r
221     while (p != null)\r
222     {\r
223       sum.pluseq(p.maxChars());\r
224       p = p.next;\r
225     }\r
226     return sum;\r
227   }\r
228 \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
236   {\r
237     int[] tab = null;\r
238     if (pt.marks != null)\r
239     {\r
240       try\r
241       {\r
242         tab = new int[pt.marks.length];\r
243         for (int i = 0; i < tab.length; i++)\r
244         {\r
245           tab[i] = pt.marks[i];\r
246         }\r
247       } catch (Throwable t)\r
248       {\r
249       }\r
250     }\r
251     int ret = p.matchInternal(pos, pt);\r
252     if (ret < 0)\r
253     {\r
254       pt.marks = tab;\r
255     }\r
256     return ret;\r
257   }\r
258 \r
259   /**\r
260    * Clones this pattern elements without cloning others in the linked list.\r
261    */\r
262   Pattern clone1(Hashtable h)\r
263   {\r
264     throw new Error(MessageManager.formatMessage("error.no_such_method_as_clone1_for", new String[]{getClass().getName()}));\r
265   }\r
266 \r
267   Pattern clone(Hashtable h)\r
268   {\r
269     Pattern p = (Pattern) h.get(this);\r
270     if (p != null)\r
271     {\r
272       return p;\r
273     }\r
274     p = clone1(h);\r
275     if (p == null)\r
276     {\r
277       throw new Error(MessageManager.getString("error.null_from_clone1"));\r
278     }\r
279     h.put(this, p);\r
280     h.put(p, p);\r
281     if (next != null)\r
282     {\r
283       p.next = next.clone(h);\r
284     }\r
285     if (parent != null)\r
286     {\r
287       p.parent = parent.clone(h);\r
288     }\r
289     return p;\r
290   }\r
291 \r
292   public boolean equals(Object o)\r
293   {\r
294     return o == this;\r
295   }\r
296 };\r