-//\r
-// This software is now distributed according to\r
-// the Lesser Gnu Public License. Please see\r
-// http://www.gnu.org/copyleft/lesser.txt for\r
-// the details.\r
-// -- Happy Computing!\r
-//\r
-package com.stevesoft.pat;\r
-\r
-import java.util.*;\r
-\r
-/** This class is just like oneChar, but doesn't worry about case. */\r
-class FastChar\r
- extends oneChar\r
-{\r
- FastChar(char c)\r
- {\r
- super(c);\r
- }\r
-\r
- public int matchInternal(int p, Pthings pt)\r
- {\r
- return (p < pt.src.length()\r
- && pt.src.charAt(p) == c) ?\r
- nextMatch(p + 1, pt) : -1;\r
- }\r
-\r
- Pattern clone1(Hashtable h)\r
- {\r
- return new FastChar(c);\r
- }\r
-}\r
-\r
-/** This class is a hashtable keyed by Character\r
- * Objects. It is used to match things of the\r
- * form (?:a..|b..|c..|..) match with greater efficiency --\r
- * by using a Hashtable that indexes into the group\r
- * of patterns.\r
- */\r
-class Branch\r
- extends Pattern\r
-{\r
- Hashtable h = new Hashtable();\r
- // We need to keep track of the order\r
- // of the keys -- if we don't then\r
- // recompiling the output of toString\r
- // may produce errors by re-ordering\r
- // ()'s and changing the id number of\r
- // the backreference associated with\r
- // a subpattern.\r
- Vector keys = new Vector();\r
- Branch()\r
- {}\r
-\r
- Pattern clone1(Hashtable x)\r
- {\r
- Branch b = new Branch();\r
- b.keys = (Vector) keys.clone();\r
- x.put(this, b);\r
- x.put(b, b);\r
-\r
- for (int i = 0; i < keys.size(); i++)\r
- {\r
- Pattern p = (Pattern) h.get(keys.elementAt(i));\r
- b.h.put(keys.elementAt(i), p.clone(x));\r
- }\r
- return b;\r
- }\r
-\r
- // this function eliminates Branches with 0 or 1 elements.\r
- final Pattern reduce(boolean ignoreCase, boolean dontMinQ)\r
- {\r
- if (h.size() == 1)\r
- {\r
- Enumeration e = h.keys();\r
- Character c = (Character) e.nextElement();\r
- Pattern oc;\r
- if (ignoreCase || dontMinQ)\r
- {\r
- oc = new oneChar(c.charValue());\r
- }\r
- else\r
- {\r
- oc = new FastChar(c.charValue());\r
- }\r
- oc.next = (Pattern) h.get(c);\r
- oc.add(next);\r
- return oc;\r
- }\r
- else if (h.size() == 0)\r
- {\r
- return null;\r
- }\r
- return this;\r
- }\r
-\r
- public patInt maxChars()\r
- {\r
- Enumeration e = h.keys();\r
- patInt count = new patInt(0);\r
- while (e.hasMoreElements())\r
- {\r
- Object key = e.nextElement();\r
- Pattern pa = (Pattern) h.get(key);\r
- patInt pi = pa.maxChars();\r
- pi.inc();\r
- count.maxeq(pi);\r
- }\r
- return count;\r
- }\r
-\r
- public patInt minChars()\r
- {\r
- Enumeration e = h.keys();\r
- patInt count = new patInt(0);\r
- while (e.hasMoreElements())\r
- {\r
- Object key = e.nextElement();\r
- Pattern pa = (Pattern) h.get(key);\r
- patInt pi = pa.minChars();\r
- pi.inc();\r
- count.mineq(pi);\r
- }\r
- return count;\r
- }\r
-\r
- // adds a oneChar object to this Branch\r
- void addc(oneChar o, boolean ignoreCase, boolean dontMinQ)\r
- {\r
- Pattern n = o.next;\r
- if (n == null)\r
- {\r
- n = new NullPattern();\r
- }\r
- else\r
- {\r
- n = RegOpt.opt(n, ignoreCase, dontMinQ);\r
- }\r
- n.setParent(this);\r
- set(new Character(o.c), n, ignoreCase, dontMinQ);\r
- if (ignoreCase)\r
- {\r
- if (o.c != o.altc)\r
- {\r
- set(new Character(o.altc), n, ignoreCase, dontMinQ);\r
- }\r
- if (o.c != o.altc2 && o.altc != o.altc2)\r
- {\r
- set(new Character(o.altc2), n, ignoreCase, dontMinQ);\r
- }\r
- }\r
- }\r
-\r
- void set(Character c, Pattern n, boolean igc, boolean dontMinQ)\r
- {\r
- Pattern p = (Pattern) h.get(c);\r
- next = null;\r
- // This letter is not yet used in the Branch object.\r
- // We need to add it.\r
- if (p == null)\r
- {\r
- if (n instanceof Or)\r
- {\r
- // A NullPattern is prepended to an Or\r
- // to prevent confusing this object.\r
- // For example: (boo|bug) => (b(?:oo|ug))\r
- // during this process. However, we\r
- // want (b(?:oo|ell)|bug)\r
- NullPattern np = new NullPattern();\r
- np.add(n);\r
- h.put(c, np);\r
- }\r
- else\r
- {\r
- h.put(c, n);\r
- }\r
- // Make sure we remember the order things were\r
- // added into the Branch object so that we can\r
- // properly convert it to a String.\r
- keys.addElement(c);\r
- }\r
- else if (p instanceof Or)\r
- {\r
- ( (Or) p).addOr(n);\r
- }\r
- else if (p instanceof oneChar && n instanceof oneChar\r
- && ( (oneChar) p).c != ( (oneChar) n).c)\r
- {\r
- Branch b = new Branch();\r
- b.addc( (oneChar) p, igc, dontMinQ);\r
- b.addc( (oneChar) n, igc, dontMinQ);\r
- h.put(c, b);\r
- b.setParent(this);\r
- }\r
- else if (p instanceof Branch && n instanceof oneChar)\r
- {\r
- ( (Branch) p).addc( (oneChar) n, igc, dontMinQ);\r
- n.setParent(p);\r
- }\r
- else\r
- {\r
- // Create an Or object to receive the variety\r
- // of branches in the pattern if the current letter\r
- // is matched. We do not attempt to make these\r
- // sub-branches into a Branch object yet.\r
- Or o = new Or();\r
- o.setParent(this);\r
-\r
- // Remove NullPattern from p -- it's no longer needed.\r
- if (p instanceof NullPattern\r
- && p.parent == null && p.next != null)\r
- {\r
- o.addOr(p.next);\r
- }\r
- else\r
- {\r
- o.addOr(p);\r
- }\r
- o.addOr(n);\r
-\r
- Pattern optpat = RegOpt.opt(o, igc, dontMinQ);\r
- h.put(c, optpat);\r
- optpat.setParent(this);\r
- }\r
- }\r
-\r
- public String toString()\r
- {\r
- StringBuffer sb = new StringBuffer();\r
- // should protect this...\r
- sb.append("(?:(?#branch)"); // Hashtable)");\r
- for (int i = 0; i < keys.size(); i++)\r
- {\r
- Character c = (Character) keys.elementAt(i);\r
- sb.append(c);\r
- sb.append(h.get(c));\r
- if (i + 1 < keys.size())\r
- {\r
- sb.append("|");\r
- }\r
- }\r
- sb.append(")");\r
- sb.append(nextString());\r
- return sb.toString();\r
- }\r
-\r
- public int matchInternal(int pos, Pthings pt)\r
- {\r
- if (pos >= pt.src.length())\r
- {\r
- return -1;\r
- }\r
- Pattern n = (Pattern) h.get(new Character(pt.src.charAt(pos)));\r
- if (n == null)\r
- {\r
- return -1;\r
- }\r
- if (pt.cbits != null && pt.cbits.get(pos))\r
- {\r
- return -1;\r
- }\r
- return n.matchInternal(pos + 1, pt);\r
- }\r
-}\r
-\r
-/** This is just a place to put the optimizing function.\r
- It is never instantiated as an Object. It just sorts\r
- through the RegOpt looking for things it can change\r
- and make faster. */\r
-public class RegOpt\r
-{\r
- static Pattern opt(Pattern p, boolean ignoreCase,\r
- boolean dontMinQ)\r
- {\r
- if (p == null)\r
- {\r
- return p;\r
- }\r
- if (p instanceof Bracket)\r
- {\r
- Bracket b = (Bracket) p;\r
- // FastBracket is the only special\r
- // optimized class to have its own\r
- // source file.\r
- p = FastBracket.process(b, ignoreCase);\r
- //if(!(p instanceof FastBracket)\r
- //p = Switch.process(b,ignoreCase);\r
- p.next = b.next;\r
- p.parent = b.parent;\r
- }\r
- else if (p instanceof oneChar && !ignoreCase\r
- && !dontMinQ)\r
- {\r
- oneChar o = (oneChar) p;\r
- p = new FastChar(o.c);\r
- p.next = o.next;\r
- p.parent = o.parent;\r
- }\r
- else if (p instanceof Or\r
- && ( (Or) p).leftForm().equals("(?:")\r
- && ( (Or) p).v.size() == 1)\r
- { // Eliminate this Or Object.\r
- Or o = (Or) p;\r
- p = (Pattern) o.v.elementAt(0);\r
- p.setParent(null);\r
- p = RegOpt.opt(p, ignoreCase, dontMinQ);\r
- p.add(o.next);\r
- }\r
- else if (p instanceof Or)\r
- {\r
- Or o = (Or) p;\r
- o.pv = null;\r
- Vector v = o.v;\r
- o.v = new Vector();\r
- Branch b = new Branch();\r
- b.parent = o.parent;\r
- for (int i = 0; i < v.size(); i++)\r
- {\r
- Pattern pp = (Pattern) v.elementAt(i);\r
- // We want to have at least two oneChar's in\r
- // the Or Object to consider making a Branch.\r
- if (pp instanceof oneChar && (b.h.size() >= 1 ||\r
- (i + 1 < v.size() &&\r
- v.elementAt(i + 1) instanceof oneChar)))\r
- {\r
- b.addc( (oneChar) pp, ignoreCase, dontMinQ);\r
- }\r
- else\r
- {\r
- if (b.keys.size() > 0)\r
- {\r
- Pattern p2 = (Pattern) b.reduce(ignoreCase, dontMinQ);\r
- if (p2 != null)\r
- {\r
- o.addOr(p2);\r
- b = new Branch();\r
- b.parent = o.parent;\r
- }\r
- }\r
- o.addOr(opt(pp, ignoreCase, dontMinQ));\r
- }\r
- }\r
- if (b.keys.size() > 0)\r
- {\r
- Pattern p2 = (Pattern) b.reduce(ignoreCase, dontMinQ);\r
- if (p2 != null)\r
- {\r
- o.addOr(p2);\r
- }\r
- }\r
- if (o.v.size() == 1\r
- && o.leftForm().equals("(?:"))\r
- { // Eliminate Or Object\r
- p = (Pattern) o.v.elementAt(0);\r
- p.setParent(null);\r
- p = RegOpt.opt(p, ignoreCase, dontMinQ);\r
- p.add(o.next);\r
- }\r
- }\r
- else if (p instanceof FastMulti)\r
- {\r
- PatternSub ps = (PatternSub) p;\r
- ps.sub = RegOpt.opt(ps.sub, ignoreCase, dontMinQ);\r
- }\r
- else if (p instanceof Multi && safe4fm( ( (PatternSub) p).sub))\r
- {\r
- Multi m = (Multi) p;\r
- FastMulti fm = null;\r
- try\r
- {\r
- fm = new FastMulti(m.a, m.b,\r
- opt(m.sub, ignoreCase, dontMinQ));\r
- }\r
- catch (RegSyntax rs)\r
- {}\r
- fm.parent = m.parent;\r
- fm.matchFewest = m.matchFewest;\r
- fm.next = m.next;\r
- p = fm;\r
- }\r
- if (p.next != null)\r
- {\r
- p.next = opt(p.next, ignoreCase, dontMinQ);\r
- }\r
- return p;\r
- }\r
-\r
- final static boolean safe4fm(Pattern x)\r
- {\r
- while (x != null)\r
- {\r
- if (x instanceof Bracket)\r
- {\r
- ;\r
- }\r
- else if (x instanceof Range)\r
- {\r
- ;\r
- }\r
- else if (x instanceof oneChar)\r
- {\r
- ;\r
- }\r
- else if (x instanceof Any)\r
- {\r
- ;\r
- }\r
- else if (x instanceof Custom\r
- && ( (Custom) x).v instanceof UniValidator)\r
- {\r
- ;\r
- }\r
- else if (x instanceof Or)\r
- {\r
- Or o = (Or) x;\r
- if (!o.leftForm().equals("(?:"))\r
- {\r
- return false;\r
- }\r
- patInt lo = o.countMinChars();\r
- patInt hi = o.countMaxChars();\r
- if (!lo.equals(hi))\r
- {\r
- return false;\r
- }\r
- for (int i = 0; i < o.v.size(); i++)\r
- {\r
- if (!safe4fm( (Pattern) o.v.elementAt(i)))\r
- {\r
- return false;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
- x = x.next;\r
- }\r
- return true;\r
- }\r
- /*\r
- public static void setParents(Regex r) {\r
- setParents(r.thePattern,null);\r
- }\r
- static void setParents(Pattern p,Pattern x) {\r
- if(p instanceof PatternSub && !(p instanceof FastMulti)\r
- && !(p instanceof DotMulti))\r
- RegOpt.setParents( ((PatternSub)p).sub, p);\r
- else if(p instanceof Or && !(p instanceof Bracket)) {\r
- Or o = (Or)p;\r
- for(int i=0;i<o.v.size();i++)\r
- RegOpt.setParents((Pattern)o.v.elementAt(i),o);\r
- } else if(p instanceof Branch) {\r
- Branch b = (Branch)p;\r
- Enumeration e = b.h.keys();\r
- while(e.hasMoreElements()) {\r
- Object o = e.nextElement();\r
- RegOpt.setParents( (Pattern)b.h.get(o), b);\r
- }\r
- }\r
- if(p.next == null)\r
- p.parent = x;\r
- else {\r
- p.parent = null;\r
- RegOpt.setParents(p.next,x);\r
- }\r
- }*/\r
-}\r
+//
+// This software is now distributed according to
+// the Lesser Gnu Public License. Please see
+// http://www.gnu.org/copyleft/lesser.txt for
+// the details.
+// -- Happy Computing!
+//
+package com.stevesoft.pat;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/** This class is just like oneChar, but doesn't worry about case. */
+class FastChar extends oneChar
+{
+ FastChar(char c)
+ {
+ super(c);
+ }
+
+ public int matchInternal(int p, Pthings pt)
+ {
+ return (p < pt.src.length() && pt.src.charAt(p) == c) ? nextMatch(
+ p + 1, pt) : -1;
+ }
+
+ Pattern clone1(Hashtable h)
+ {
+ return new FastChar(c);
+ }
+}
+
+/**
+ * This class is a hashtable keyed by Character Objects. It is used to match
+ * things of the form (?:a..|b..|c..|..) match with greater efficiency -- by
+ * using a Hashtable that indexes into the group of patterns.
+ */
+class Branch extends Pattern
+{
+ Hashtable h = new Hashtable();
+
+ // We need to keep track of the order
+ // of the keys -- if we don't then
+ // recompiling the output of toString
+ // may produce errors by re-ordering
+ // ()'s and changing the id number of
+ // the backreference associated with
+ // a subpattern.
+ Vector keys = new Vector();
+
+ Branch()
+ {
+ }
+
+ Pattern clone1(Hashtable x)
+ {
+ Branch b = new Branch();
+ b.keys = (Vector) keys.clone();
+ x.put(this, b);
+ x.put(b, b);
+
+ for (int i = 0; i < keys.size(); i++)
+ {
+ Pattern p = (Pattern) h.get(keys.elementAt(i));
+ b.h.put(keys.elementAt(i), p.clone(x));
+ }
+ return b;
+ }
+
+ // this function eliminates Branches with 0 or 1 elements.
+ final Pattern reduce(boolean ignoreCase, boolean dontMinQ)
+ {
+ if (h.size() == 1)
+ {
+ Enumeration e = h.keys();
+ Character c = (Character) e.nextElement();
+ Pattern oc;
+ if (ignoreCase || dontMinQ)
+ {
+ oc = new oneChar(c.charValue());
+ }
+ else
+ {
+ oc = new FastChar(c.charValue());
+ }
+ oc.next = (Pattern) h.get(c);
+ oc.add(next);
+ return oc;
+ }
+ else if (h.size() == 0)
+ {
+ return null;
+ }
+ return this;
+ }
+
+ public patInt maxChars()
+ {
+ Enumeration e = h.keys();
+ patInt count = new patInt(0);
+ while (e.hasMoreElements())
+ {
+ Object key = e.nextElement();
+ Pattern pa = (Pattern) h.get(key);
+ patInt pi = pa.maxChars();
+ pi.inc();
+ count.maxeq(pi);
+ }
+ return count;
+ }
+
+ public patInt minChars()
+ {
+ Enumeration e = h.keys();
+ patInt count = new patInt(0);
+ while (e.hasMoreElements())
+ {
+ Object key = e.nextElement();
+ Pattern pa = (Pattern) h.get(key);
+ patInt pi = pa.minChars();
+ pi.inc();
+ count.mineq(pi);
+ }
+ return count;
+ }
+
+ // adds a oneChar object to this Branch
+ void addc(oneChar o, boolean ignoreCase, boolean dontMinQ)
+ {
+ Pattern n = o.next;
+ if (n == null)
+ {
+ n = new NullPattern();
+ }
+ else
+ {
+ n = RegOpt.opt(n, ignoreCase, dontMinQ);
+ }
+ n.setParent(this);
+ set(Character.valueOf(o.c), n, ignoreCase, dontMinQ);
+ if (ignoreCase)
+ {
+ if (o.c != o.altc)
+ {
+ set(Character.valueOf(o.altc), n, ignoreCase, dontMinQ);
+ }
+ if (o.c != o.altc2 && o.altc != o.altc2)
+ {
+ set(Character.valueOf(o.altc2), n, ignoreCase, dontMinQ);
+ }
+ }
+ }
+
+ void set(Character c, Pattern n, boolean igc, boolean dontMinQ)
+ {
+ Pattern p = (Pattern) h.get(c);
+ next = null;
+ // This letter is not yet used in the Branch object.
+ // We need to add it.
+ if (p == null)
+ {
+ if (n instanceof Or)
+ {
+ // A NullPattern is prepended to an Or
+ // to prevent confusing this object.
+ // For example: (boo|bug) => (b(?:oo|ug))
+ // during this process. However, we
+ // want (b(?:oo|ell)|bug)
+ NullPattern np = new NullPattern();
+ np.add(n);
+ h.put(c, np);
+ }
+ else
+ {
+ h.put(c, n);
+ }
+ // Make sure we remember the order things were
+ // added into the Branch object so that we can
+ // properly convert it to a String.
+ keys.addElement(c);
+ }
+ else if (p instanceof Or)
+ {
+ ((Or) p).addOr(n);
+ }
+ else if (p instanceof oneChar && n instanceof oneChar
+ && ((oneChar) p).c != ((oneChar) n).c)
+ {
+ Branch b = new Branch();
+ b.addc((oneChar) p, igc, dontMinQ);
+ b.addc((oneChar) n, igc, dontMinQ);
+ h.put(c, b);
+ b.setParent(this);
+ }
+ else if (p instanceof Branch && n instanceof oneChar)
+ {
+ ((Branch) p).addc((oneChar) n, igc, dontMinQ);
+ n.setParent(p);
+ }
+ else
+ {
+ // Create an Or object to receive the variety
+ // of branches in the pattern if the current letter
+ // is matched. We do not attempt to make these
+ // sub-branches into a Branch object yet.
+ Or o = new Or();
+ o.setParent(this);
+
+ // Remove NullPattern from p -- it's no longer needed.
+ if (p instanceof NullPattern && p.parent == null && p.next != null)
+ {
+ o.addOr(p.next);
+ }
+ else
+ {
+ o.addOr(p);
+ }
+ o.addOr(n);
+
+ Pattern optpat = RegOpt.opt(o, igc, dontMinQ);
+ h.put(c, optpat);
+ optpat.setParent(this);
+ }
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ // should protect this...
+ sb.append("(?:(?#branch)"); // Hashtable)");
+ for (int i = 0; i < keys.size(); i++)
+ {
+ Character c = (Character) keys.elementAt(i);
+ sb.append(c);
+ sb.append(h.get(c));
+ if (i + 1 < keys.size())
+ {
+ sb.append("|");
+ }
+ }
+ sb.append(")");
+ sb.append(nextString());
+ return sb.toString();
+ }
+
+ public int matchInternal(int pos, Pthings pt)
+ {
+ if (pos >= pt.src.length())
+ {
+ return -1;
+ }
+ Pattern n = (Pattern) h.get(Character.valueOf(pt.src.charAt(pos)));
+ if (n == null)
+ {
+ return -1;
+ }
+ if (pt.cbits != null && pt.cbits.get(pos))
+ {
+ return -1;
+ }
+ return n.matchInternal(pos + 1, pt);
+ }
+}
+
+/**
+ * This is just a place to put the optimizing function. It is never instantiated
+ * as an Object. It just sorts through the RegOpt looking for things it can
+ * change and make faster.
+ */
+public class RegOpt
+{
+ static Pattern opt(Pattern p, boolean ignoreCase, boolean dontMinQ)
+ {
+ if (p == null)
+ {
+ return p;
+ }
+ if (p instanceof Bracket)
+ {
+ Bracket b = (Bracket) p;
+ // FastBracket is the only special
+ // optimized class to have its own
+ // source file.
+ p = FastBracket.process(b, ignoreCase);
+ // if(!(p instanceof FastBracket)
+ // p = Switch.process(b,ignoreCase);
+ p.next = b.next;
+ p.parent = b.parent;
+ }
+ else if (p instanceof oneChar && !ignoreCase && !dontMinQ)
+ {
+ oneChar o = (oneChar) p;
+ p = new FastChar(o.c);
+ p.next = o.next;
+ p.parent = o.parent;
+ }
+ else if (p instanceof Or && ((Or) p).leftForm().equals("(?:")
+ && ((Or) p).v.size() == 1)
+ { // Eliminate this Or Object.
+ Or o = (Or) p;
+ p = (Pattern) o.v.elementAt(0);
+ p.setParent(null);
+ p = RegOpt.opt(p, ignoreCase, dontMinQ);
+ p.add(o.next);
+ }
+ else if (p instanceof Or)
+ {
+ Or o = (Or) p;
+ o.pv = null;
+ Vector v = o.v;
+ o.v = new Vector();
+ Branch b = new Branch();
+ b.parent = o.parent;
+ for (int i = 0; i < v.size(); i++)
+ {
+ Pattern pp = (Pattern) v.elementAt(i);
+ // We want to have at least two oneChar's in
+ // the Or Object to consider making a Branch.
+ if (pp instanceof oneChar
+ && (b.h.size() >= 1 || (i + 1 < v.size() && v
+ .elementAt(i + 1) instanceof oneChar)))
+ {
+ b.addc((oneChar) pp, ignoreCase, dontMinQ);
+ }
+ else
+ {
+ if (b.keys.size() > 0)
+ {
+ Pattern p2 = (Pattern) b.reduce(ignoreCase, dontMinQ);
+ if (p2 != null)
+ {
+ o.addOr(p2);
+ b = new Branch();
+ b.parent = o.parent;
+ }
+ }
+ o.addOr(opt(pp, ignoreCase, dontMinQ));
+ }
+ }
+ if (b.keys.size() > 0)
+ {
+ Pattern p2 = (Pattern) b.reduce(ignoreCase, dontMinQ);
+ if (p2 != null)
+ {
+ o.addOr(p2);
+ }
+ }
+ if (o.v.size() == 1 && o.leftForm().equals("(?:"))
+ { // Eliminate Or Object
+ p = (Pattern) o.v.elementAt(0);
+ p.setParent(null);
+ p = RegOpt.opt(p, ignoreCase, dontMinQ);
+ p.add(o.next);
+ }
+ }
+ else if (p instanceof FastMulti)
+ {
+ PatternSub ps = (PatternSub) p;
+ ps.sub = RegOpt.opt(ps.sub, ignoreCase, dontMinQ);
+ }
+ else if (p instanceof Multi && safe4fm(((PatternSub) p).sub))
+ {
+ Multi m = (Multi) p;
+ FastMulti fm = null;
+ try
+ {
+ fm = new FastMulti(m.a, m.b, opt(m.sub, ignoreCase, dontMinQ));
+ } catch (RegSyntax rs)
+ {
+ }
+ fm.parent = m.parent;
+ fm.matchFewest = m.matchFewest;
+ fm.next = m.next;
+ p = fm;
+ }
+ if (p.next != null)
+ {
+ p.next = opt(p.next, ignoreCase, dontMinQ);
+ }
+ return p;
+ }
+
+ final static boolean safe4fm(Pattern x)
+ {
+ while (x != null)
+ {
+ if (x instanceof Bracket)
+ {
+ ;
+ }
+ else if (x instanceof Range)
+ {
+ ;
+ }
+ else if (x instanceof oneChar)
+ {
+ ;
+ }
+ else if (x instanceof Any)
+ {
+ ;
+ }
+ else if (x instanceof Custom
+ && ((Custom) x).v instanceof UniValidator)
+ {
+ ;
+ }
+ else if (x instanceof Or)
+ {
+ Or o = (Or) x;
+ if (!o.leftForm().equals("(?:"))
+ {
+ return false;
+ }
+ patInt lo = o.countMinChars();
+ patInt hi = o.countMaxChars();
+ if (!lo.equals(hi))
+ {
+ return false;
+ }
+ for (int i = 0; i < o.v.size(); i++)
+ {
+ if (!safe4fm((Pattern) o.v.elementAt(i)))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+ x = x.next;
+ }
+ return true;
+ }
+ /*
+ * public static void setParents(Regex r) { setParents(r.thePattern,null); }
+ * static void setParents(Pattern p,Pattern x) { if(p instanceof PatternSub &&
+ * !(p instanceof FastMulti) && !(p instanceof DotMulti)) RegOpt.setParents(
+ * ((PatternSub)p).sub, p); else if(p instanceof Or && !(p instanceof
+ * Bracket)) { Or o = (Or)p; for(int i=0;i<o.v.size();i++)
+ * RegOpt.setParents((Pattern)o.v.elementAt(i),o); } else if(p instanceof
+ * Branch) { Branch b = (Branch)p; Enumeration e = b.h.keys();
+ * while(e.hasMoreElements()) { Object o = e.nextElement(); RegOpt.setParents(
+ * (Pattern)b.h.get(o), b); } } if(p.next == null) p.parent = x; else {
+ * p.parent = null; RegOpt.setParents(p.next,x); } }
+ */
+}