001: /*
002: * gnu/regexp/RETokenOneOf.java
003: * Copyright (C) 1998-2001 Wes Biggs
004: *
005: * This library is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU Lesser General Public License as published
007: * by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser 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: final 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 subIndex, String optionsStr, boolean negative,
033: boolean insens) {
034: super (subIndex);
035: options = new Vector();
036: this .negative = negative;
037: for (int i = 0; i < optionsStr.length(); i++)
038: options.addElement(new RETokenChar(subIndex, optionsStr
039: .charAt(i), insens));
040: }
041:
042: RETokenOneOf(int subIndex, Vector options, boolean negative) {
043: super (subIndex);
044: this .options = options;
045: this .negative = 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: boolean match(CharIndexed input, REMatch mymatch) {
060: if (negative
061: && (input.charAt(mymatch.index) == CharIndexed.OUT_OF_BOUNDS))
062: return false;
063:
064: REMatch newMatch = null;
065: REMatch last = null;
066: REToken tk;
067: boolean isMatch;
068: for (int i = 0; i < options.size(); i++) {
069: tk = (REToken) options.elementAt(i);
070: REMatch tryMatch = (REMatch) mymatch.clone();
071: if (tk.match(input, tryMatch)) { // match was successful
072: if (negative)
073: return false;
074:
075: if (next(input, tryMatch)) {
076: // Add tryMatch to list of possibilities.
077: if (last == null) {
078: newMatch = tryMatch;
079: last = tryMatch;
080: } else {
081: last.next = tryMatch;
082: last = tryMatch;
083: }
084: } // next succeeds
085: } // is a match
086: } // try next option
087:
088: if (newMatch != null) {
089: if (negative) {
090: return false;
091: } else {
092: // set contents of mymatch equal to newMatch
093:
094: // try each one that matched
095: mymatch.assignFrom(newMatch);
096: return true;
097: }
098: } else {
099: if (negative) {
100: ++mymatch.index;
101: return next(input, mymatch);
102: } else {
103: return false;
104: }
105: }
106:
107: // index+1 works for [^abc] lists, not for generic lookahead (--> index)
108: }
109:
110: void dump(StringBuffer os) {
111: os.append(negative ? "[^" : "(?:");
112: for (int i = 0; i < options.size(); i++) {
113: if (!negative && (i > 0))
114: os.append('|');
115: ((REToken) options.elementAt(i)).dumpAll(os);
116: }
117: os.append(negative ? ']' : ')');
118: }
119: }
|