Formatting
[jalview.git] / src / com / stevesoft / pat / parsePerl.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 /** This class provides a method for parsing the "s/.../.../" constructs\r
11  of Regex.perlCode.\r
12  @see Regex#perlCode\r
13  */\r
14 class parsePerl\r
15 {\r
16   final static char close(char c)\r
17   {\r
18     // This switch statement does not behave\r
19     // properly when compiled with jdk1.1.5\r
20     // and the -O flag.\r
21     /*\r
22              switch(c) {\r
23              case '[':\r
24       return ']';\r
25              case '(':\r
26       return ')';\r
27              case '{':\r
28       return '}';\r
29              }\r
30              return c;*/\r
31     if (c == '<')\r
32     {\r
33       return '>';\r
34     }\r
35     if (c == '[')\r
36     {\r
37       return ']';\r
38     }\r
39     if (c == '(')\r
40     {\r
41       return ')';\r
42     }\r
43     if (c == '{')\r
44     {\r
45       return '}';\r
46     }\r
47     return c;\r
48   }\r
49 \r
50   final public static String codify(String s, boolean keepbs)\r
51   {\r
52     return codify(s, 0, s.length(), keepbs);\r
53   }\r
54 \r
55   final public static String codify(String s, int i0, int iN, boolean keepbs)\r
56   {\r
57     StringBuffer sb = new StringBuffer();\r
58     boolean ucmode = false, lcmode = false, litmode = false;\r
59     boolean uc1 = false, lc1 = false;\r
60     boolean modified = false;\r
61     for (int i = i0; i < iN; i++)\r
62     {\r
63       char c = s.charAt(i);\r
64       boolean mf = true, app = true;\r
65       if (c == '\\')\r
66       {\r
67         app = false;\r
68         i++;\r
69         if (i < s.length())\r
70         {\r
71           char c2 = s.charAt(i);\r
72           switch (c2)\r
73           {\r
74             case 'Q':\r
75               litmode = true;\r
76               break;\r
77             case 'U':\r
78               ucmode = true;\r
79               break;\r
80             case 'L':\r
81               lcmode = true;\r
82               break;\r
83             case 'u':\r
84               uc1 = true;\r
85               break;\r
86             case 'l':\r
87               lc1 = true;\r
88               break;\r
89             case 'E':\r
90               uc1 = lc1 = ucmode = lcmode = litmode = false;\r
91               break;\r
92             default:\r
93               if (keepbs)\r
94               {\r
95                 sb.append('\\');\r
96               }\r
97               c = c2;\r
98               if (keepbs)\r
99               {\r
100                 mf = false;\r
101               }\r
102               app = true;\r
103               break;\r
104           }\r
105           modified |= mf;\r
106         }\r
107       }\r
108       if (app)\r
109       {\r
110         if (lc1)\r
111         {\r
112           c = lc(c);\r
113           lc1 = false;\r
114         }\r
115         else if (uc1)\r
116         {\r
117           c = uc(c);\r
118           uc1 = false;\r
119         }\r
120         else if (ucmode)\r
121         {\r
122           c = uc(c);\r
123         }\r
124         else if (lcmode)\r
125         {\r
126           c = lc(c);\r
127         }\r
128         if (litmode && needbs(c))\r
129         {\r
130           sb.append('\\');\r
131         }\r
132         sb.append(c);\r
133       }\r
134     }\r
135     return modified ? sb.toString() : s;\r
136   }\r
137 \r
138   final static char uc(char c)\r
139   {\r
140     return CaseMgr.toUpperCase(c);\r
141   }\r
142 \r
143   final static char lc(char c)\r
144   {\r
145     return CaseMgr.toLowerCase(c);\r
146   }\r
147 \r
148   final static boolean needbs(char c)\r
149   {\r
150     if (c >= 'a' && c <= 'z')\r
151     {\r
152       return false;\r
153     }\r
154     if (c >= 'A' && c <= 'Z')\r
155     {\r
156       return false;\r
157     }\r
158     if (c >= '0' && c <= '9')\r
159     {\r
160       return false;\r
161     }\r
162     if (c == '_')\r
163     {\r
164       return false;\r
165     }\r
166     return true;\r
167   }\r
168 \r
169   final static Regex parse(String s)\r
170   {\r
171     boolean igncase = false, optim = false, gFlag = false;\r
172     boolean sFlag = false, mFlag = false, xFlag = false;\r
173 \r
174     StringBuffer s1 = new StringBuffer();\r
175     StringBuffer s2 = new StringBuffer();\r
176     int i = 0, count = 0;\r
177     char mode, delim = '/', cdelim = '/';\r
178     if (s.length() >= 3 && s.charAt(0) == 's')\r
179     {\r
180       mode = 's';\r
181       delim = s.charAt(1);\r
182       cdelim = close(delim);\r
183       i = 2;\r
184     }\r
185     else if (s.length() >= 2 && s.charAt(0) == 'm')\r
186     {\r
187       mode = 'm';\r
188       delim = s.charAt(1);\r
189       cdelim = close(delim);\r
190       i = 2;\r
191     }\r
192     else if (s.length() >= 1 && s.charAt(0) == '/')\r
193     {\r
194       mode = 'm';\r
195       i = 1;\r
196     }\r
197     else\r
198     {\r
199       try\r
200       {\r
201         RegSyntaxError.endItAll(\r
202             "Regex.perlCode should be of the " +\r
203             "form s/// or m// or //");\r
204       }\r
205       catch (RegSyntax rs)\r
206       {}\r
207       return null;\r
208     }\r
209     for (; i < s.length(); i++)\r
210     {\r
211       if (s.charAt(i) == '\\')\r
212       {\r
213         s1.append('\\');\r
214         i++;\r
215       }\r
216       else if (s.charAt(i) == cdelim && count == 0)\r
217       {\r
218         i++;\r
219         break;\r
220       }\r
221       else if (s.charAt(i) == delim && cdelim != delim)\r
222       {\r
223         count++;\r
224       }\r
225       else if (s.charAt(i) == cdelim && cdelim != delim)\r
226       {\r
227         count--;\r
228       }\r
229       s1.append(s.charAt(i));\r
230     }\r
231     if (mode == 's' && cdelim != delim)\r
232     {\r
233       while (i < s.length() && Prop.isWhite(s.charAt(i)))\r
234       {\r
235         i++;\r
236       }\r
237       if (i >= s.length())\r
238       {\r
239         try\r
240         {\r
241           RegSyntaxError.endItAll("" + mode + delim + " needs " + cdelim);\r
242         }\r
243         catch (RegSyntax rs)\r
244         {}\r
245         return null;\r
246       }\r
247       cdelim = close(delim = s.charAt(i));\r
248       i++;\r
249     }\r
250     count = 0;\r
251     if (mode == 's')\r
252     {\r
253       for (; i < s.length(); i++)\r
254       {\r
255         if (s.charAt(i) == '\\')\r
256         {\r
257           s2.append('\\');\r
258           i++;\r
259         }\r
260         else if (s.charAt(i) == cdelim && count == 0)\r
261         {\r
262           i++;\r
263           break;\r
264         }\r
265         else if (s.charAt(i) == delim && cdelim != delim)\r
266         {\r
267           count++;\r
268         }\r
269         else if (s.charAt(i) == cdelim && cdelim != delim)\r
270         {\r
271           count--;\r
272         }\r
273         s2.append(s.charAt(i));\r
274       }\r
275     }\r
276     for (; i < s.length(); i++)\r
277     {\r
278       char c = s.charAt(i);\r
279       switch (c)\r
280       {\r
281         case 'x':\r
282           xFlag = true;\r
283           break;\r
284         case 'i':\r
285           igncase = true;\r
286           break;\r
287         case 'o':\r
288           optim = true;\r
289           break;\r
290         case 's':\r
291           sFlag = true;\r
292           break;\r
293         case 'm':\r
294           mFlag = true;\r
295           break;\r
296         case 'g':\r
297           gFlag = true;\r
298           break;\r
299         default:\r
300 \r
301           // syntax error!\r
302           try\r
303           {\r
304             RegSyntaxError.endItAll("Illegal flag to pattern: " + c);\r
305           }\r
306           catch (RegSyntax rs)\r
307           {}\r
308           return null;\r
309       }\r
310     }\r
311     Regex r = new Regex();\r
312     try\r
313     {\r
314       String pat = s1.toString(), reprul = s2.toString();\r
315       if (xFlag)\r
316       {\r
317         pat = strip(pat);\r
318         reprul = strip(reprul);\r
319       }\r
320       r.compile(pat);\r
321       r.ignoreCase |= igncase;\r
322       r.gFlag |= gFlag;\r
323       r.sFlag |= sFlag;\r
324       r.mFlag |= mFlag;\r
325       if (optim)\r
326       {\r
327         r.optimize();\r
328       }\r
329       if (delim == '\'')\r
330       {\r
331         r.setReplaceRule(new StringRule(reprul));\r
332       }\r
333       else\r
334       {\r
335         r.setReplaceRule(ReplaceRule.perlCode(reprul));\r
336       }\r
337     }\r
338     catch (RegSyntax rs)\r
339     {\r
340       r = null;\r
341     }\r
342     return r;\r
343   }\r
344 \r
345   static String strip(String s)\r
346   {\r
347     StringBuffer sb = new StringBuffer();\r
348     for (int i = 0; i < s.length(); i++)\r
349     {\r
350       char c = s.charAt(i);\r
351       if (Prop.isWhite(c))\r
352       {\r
353         ;\r
354       }\r
355       else if (c == '#')\r
356       {\r
357         i++;\r
358         while (i < s.length())\r
359         {\r
360           if (s.charAt(i) == '\n')\r
361           {\r
362             break;\r
363           }\r
364           i++;\r
365         }\r
366       }\r
367       else if (c == '\\')\r
368       {\r
369         sb.append(c);\r
370         sb.append(s.charAt(++i));\r
371       }\r
372       else\r
373       {\r
374         sb.append(c);\r
375       }\r
376     }\r
377     return sb.toString();\r
378   }\r
379 }\r