001: /*
002: * gnu/regexp/RETokenOneOf.java
003: * Copyright (C) 1998 Wes Biggs
004: *
005: * This library is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU Library General Public License as published
007: * by the Free Software Foundation; either version 2 of the License, or
008: * (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU Library General Public License for more details.
014: *
015: * You should have received a copy of the GNU Library General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
018: */
019:
020: package gnu.regexp;
021:
022: import java.util.Vector;
023:
024: class RETokenOneOf extends REToken {
025: private Vector options;
026: private boolean negative;
027:
028: // This constructor is used for convenience when we know the set beforehand,
029: // e.g. \d --> new RETokenOneOf("0123456789",false, ..)
030: // \D --> new RETokenOneOf("0123456789",true, ..)
031:
032: RETokenOneOf(int f_subIndex, String f_options, boolean f_negative,
033: boolean f_insens) {
034: super (f_subIndex);
035: options = new Vector();
036: negative = f_negative;
037: for (int i = 0; i < f_options.length(); i++)
038: options.addElement(new RETokenChar(f_subIndex, f_options
039: .charAt(i), f_insens));
040: }
041:
042: RETokenOneOf(int f_subIndex, Vector f_options, boolean f_negative) {
043: super (f_subIndex);
044: options = f_options;
045: negative = f_negative;
046: }
047:
048: int getMinimumLength() {
049: int min = Integer.MAX_VALUE;
050: int x;
051: for (int i = 0; i < options.size(); i++) {
052: if ((x = ((REToken) options.elementAt(i))
053: .getMinimumLength()) < min)
054: min = x;
055: }
056: return min;
057: }
058:
059: int[] match(CharIndexed input, int index, int eflags,
060: REMatch mymatch) {
061: if (negative
062: && (input.charAt(index) == CharIndexed.OUT_OF_BOUNDS))
063: return null;
064:
065: int[] newIndex;
066: int[] possibles = new int[0];
067: REToken tk;
068: for (int i = 0; i < options.size(); i++) {
069: tk = (REToken) options.elementAt(i);
070: newIndex = tk.match(input, index, eflags, mymatch);
071:
072: // Voodoo.
073: if ((newIndex == null) && (tk instanceof RE)
074: && (tk.m_subIndex > 0)) {
075: mymatch.reset(tk.m_subIndex + 1);
076: }
077:
078: if (newIndex != null) { // match was successful
079: if (negative)
080: return null;
081: // Add newIndex to list of possibilities.
082:
083: int[] temp = new int[possibles.length + newIndex.length];
084: System.arraycopy(possibles, 0, temp, 0,
085: possibles.length);
086: for (int j = 0; j < newIndex.length; j++)
087: temp[possibles.length + j] = newIndex[j];
088: possibles = temp;
089: }
090: } // try next option
091: // Now possibles is array of all possible matches.
092: // Try next with each possibility.
093:
094: int[] doables = new int[0];
095: for (int i = 0; i < possibles.length; i++) {
096: newIndex = next(input, possibles[i], eflags, mymatch);
097: if (newIndex != null) {
098: int[] temp = new int[doables.length + newIndex.length];
099: System.arraycopy(doables, 0, temp, 0, doables.length);
100: for (int j = 0; j < newIndex.length; j++)
101: temp[doables.length + j] = newIndex[j];
102: doables = temp;
103: } else {
104: // Voodoo.
105: if (m_subIndex > 0) {
106: mymatch.reset(m_subIndex + 1);
107: }
108: }
109:
110: }
111:
112: if (doables.length > 0)
113: return (negative) ? null : doables;
114: else
115: return (negative) ? next(input, index + 1, eflags, mymatch)
116: : null;
117:
118: // index+1 works for [^abc] lists, not for generic lookahead (--> index)
119: }
120:
121: void dump(StringBuffer os) {
122: os.append(negative ? "[^" : "(?:");
123: for (int i = 0; i < options.size(); i++) {
124: if (!negative && (i > 0))
125: os.append('|');
126: ((REToken) options.elementAt(i)).dumpAll(os);
127: }
128: os.append(negative ? ']' : ')');
129: }
130:
131: // Overrides REToken.chain
132: boolean chain(REToken f_next) {
133: super .chain(f_next);
134: for (int i = 0; i < options.size(); i++)
135: ((REToken) options.elementAt(i)).setUncle(f_next);
136: return true;
137: }
138:
139: /*
140: void setUncle(REToken f_next) {
141: for (int i = 0; i < options.size(); i++)
142: ((REToken) options.elementAt(i)).setUncle(f_next);
143: }
144: */
145: }
|