2 // This software is now distributed according to
3 // the Lesser Gnu Public License. Please see
4 // http://www.gnu.org/copyleft/lesser.txt for
8 package com.stevesoft.pat;
11 * This class provides a method for parsing the "s/.../.../" constructs of
18 final static char close(char c)
20 // This switch statement does not behave
21 // properly when compiled with jdk1.1.5
24 * switch(c) { case '[': return ']'; case '(': return ')'; case '{': return
46 final public static String codify(String s, boolean keepbs)
48 return codify(s, 0, s.length(), keepbs);
51 final public static String codify(String s, int i0, int iN, boolean keepbs)
53 javajs.util.SB sb = new javajs.util.SB();
54 boolean ucmode = false, lcmode = false, litmode = false;
55 boolean uc1 = false, lc1 = false;
56 boolean modified = false;
57 for (int i = i0; i < iN; i++)
60 boolean mf = true, app = true;
67 char c2 = s.charAt(i);
86 uc1 = lc1 = ucmode = lcmode = litmode = false;
124 if (litmode && needbs(c))
131 return modified ? sb.toString() : s;
134 final static char uc(char c)
136 return CaseMgr.toUpperCase(c);
139 final static char lc(char c)
141 return CaseMgr.toLowerCase(c);
144 final static boolean needbs(char c)
146 if (c >= 'a' && c <= 'z')
150 if (c >= 'A' && c <= 'Z')
154 if (c >= '0' && c <= '9')
165 final static Regex parse(String s)
167 boolean igncase = false, optim = false, gFlag = false;
168 boolean sFlag = false, mFlag = false, xFlag = false;
170 javajs.util.SB s1 = new javajs.util.SB();
171 javajs.util.SB s2 = new javajs.util.SB();
172 int i = 0, count = 0;
173 char mode, delim = '/', cdelim = '/';
174 if (s.length() >= 3 && s.charAt(0) == 's')
178 cdelim = close(delim);
181 else if (s.length() >= 2 && s.charAt(0) == 'm')
185 cdelim = close(delim);
188 else if (s.length() >= 1 && s.charAt(0) == '/')
197 RegSyntaxError.endItAll("Regex.perlCode should be of the "
198 + "form s/// or m// or //");
199 } catch (RegSyntax rs)
204 for (; i < s.length(); i++)
206 if (s.charAt(i) == '\\')
211 else if (s.charAt(i) == cdelim && count == 0)
216 else if (s.charAt(i) == delim && cdelim != delim)
220 else if (s.charAt(i) == cdelim && cdelim != delim)
224 s1.appendC(s.charAt(i));
226 if (mode == 's' && cdelim != delim)
228 while (i < s.length() && Prop.isWhite(s.charAt(i)))
236 RegSyntaxError.endItAll("" + mode + delim + " needs " + cdelim);
237 } catch (RegSyntax rs)
242 cdelim = close(delim = s.charAt(i));
248 for (; i < s.length(); i++)
250 if (s.charAt(i) == '\\')
255 else if (s.charAt(i) == cdelim && count == 0)
260 else if (s.charAt(i) == delim && cdelim != delim)
264 else if (s.charAt(i) == cdelim && cdelim != delim)
268 s2.appendC(s.charAt(i));
271 for (; i < s.length(); i++)
273 char c = s.charAt(i);
299 RegSyntaxError.endItAll("Illegal flag to pattern: " + c);
300 } catch (RegSyntax rs)
306 Regex r = new Regex();
309 String pat = s1.toString(), reprul = s2.toString();
313 reprul = strip(reprul);
316 r.ignoreCase |= igncase;
326 r.setReplaceRule(new StringRule(reprul));
330 r.setReplaceRule(parsePerl.perlCode(reprul));
332 } catch (RegSyntax rs)
339 static String strip(String s)
341 javajs.util.SB sb = new javajs.util.SB();
342 for (int i = 0; i < s.length(); i++)
344 char c = s.charAt(i);
352 while (i < s.length())
354 if (s.charAt(i) == '\n')
364 sb.appendC(s.charAt(++i));
371 return sb.toString();
375 * Compile a ReplaceRule using the text that would go between the second and
376 * third /'s in a typical substitution pattern in Perl: s/ ... / <i>The
377 * argument to ReplaceRule.perlCode</i> /.
379 public static ReplaceRule perlCode(String s)
381 // String sav_backGs = Regex.backGs;
382 // int sav_backGto = Regex.backGto;
386 Regex gv = ReplaceRule.getv();
387 ReplaceRule head = null;
389 while (gv.searchFrom(s, mt))
391 int off = Regex.BackRefOffset - 1;
392 mf = gv.matchedFrom();
395 head = ReplaceRule.add(head, new StringRule(s.substring(mt, mf)));
398 if ((var = gv.stringMatched(1 + off)) != null
399 || (var = gv.stringMatched(2 + off)) != null
400 || (var = gv.stringMatched(5 + off)) != null)
403 for (int i = 0; i < var.length(); i++)
405 d = 8 * d + (var.charAt(i) - '0');
407 if (var.length() == 1)
409 head = ReplaceRule.add(head, new BackRefRule(d));
413 head = new StringRule("" + (char) d);
416 else if ((var = gv.stringMatched(10 + off)) != null)
418 if ("QELlUu".indexOf(var) >= 0)
420 head = ReplaceRule.add(head, new CodeRule(var.charAt(0)));
424 head = ReplaceRule.add(head, new StringRule(var));
427 else if ((var = gv.stringMatched(3 + off)) != null
428 || (var = gv.stringMatched(4 + off)) != null
429 || (var = gv.stringMatched(6 + off)) != null)
433 if ((pc = var.indexOf(':')) > 0)
435 arg = var.substring(pc + 1);
436 var = var.substring(0, pc);
438 if (var.equals("&") || var.equals("MATCH"))
440 head = ReplaceRule.add(head, new AmpersandRule());
442 else if (var.equals("`") || var.equals("PREMATCH"))
444 head = ReplaceRule.add(head, new LeftRule());
446 else if (var.equals("'") || var.equals("POSTMATCH"))
448 head = ReplaceRule.add(head, new RightRule());
450 else if (var.equals("WANT_MORE_TEXT"))
452 head = ReplaceRule.add(head, new WantMoreTextReplaceRule());
454 else if (var.equals("POP"))
456 head = ReplaceRule.add(head, new PopRule());
458 else if (var.startsWith("+")
459 && (tmp = ReplaceRule.defs.get(var.substring(1))) != null)
461 if (tmp instanceof Regex)
463 head = ReplaceRule.add(head, new PushRule(var.substring(1), (Regex) tmp));
465 else if (tmp instanceof Transformer)
467 head = ReplaceRule.add(head, new PushRule(var.substring(1),
472 head = ReplaceRule.add(head, new StringRule("${" + var + "}"));
475 else if (var.startsWith("=")
476 && (tmp = ReplaceRule.defs.get(var.substring(1))) != null)
478 if (tmp instanceof Regex)
480 head = ReplaceRule.add(head,
481 new ChangeRule(var.substring(1), (Regex) tmp));
483 else if (tmp instanceof Transformer)
485 head = ReplaceRule.add(head, new ChangeRule(var.substring(1),
490 head = ReplaceRule.add(head, new StringRule("${" + var + "}"));
493 else if ((tmp = ReplaceRule.defs.get(var)) != null)
495 if (tmp instanceof ReplaceRule)
497 ReplaceRule alt = ((ReplaceRule) tmp).arg(arg);
500 alt = ((ReplaceRule) tmp);
502 head = ReplaceRule.add(head, (ReplaceRule) (alt.clone()));
506 // can't figure out how to transform this thing...
508 head = ReplaceRule.add(head, new StringRule("${" + var + "}"));
511 else if ((var = gv.stringMatched(7 + off)) != null)
513 char c = var.charAt(0);
516 head = ReplaceRule.add(head, new StringRule("\n"));
520 head = ReplaceRule.add(head, new StringRule("\t"));
524 head = ReplaceRule.add(head, new StringRule("\r"));
528 head = ReplaceRule.add(head, new StringRule("\r"));
532 head = ReplaceRule.add(head, new StringRule("" + (char) 7));
536 head = ReplaceRule.add(head, new StringRule("" + (char) 27));
540 head = ReplaceRule.add(head, new StringRule("" + (char) 12));
543 else if ((var = gv.stringMatched(8 + off)) != null)
545 char c = var.charAt(0);
546 if (c < Ctrl.cmap.length)
550 head = ReplaceRule.add(head, new StringRule("" + c));
552 else if ((var = gv.stringMatched(9 + off)) != null)
554 int d = 16 * ReplaceRule.getHexDigit(var.charAt(0))
555 + ReplaceRule.getHexDigit(var.charAt(1));
556 head = ReplaceRule.add(head, new StringRule("" + (char) d));
560 if (mt <= s.length())
562 head = ReplaceRule.add(head, new StringRule(s.substring(mt)));
567 // Regex.backGs = sav_backGs;
568 // Regex.backGto = sav_backGto;