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 020package gnu.regexp; 021import java.util.Vector; 022 023final class RETokenOneOf extends REToken { 024 private Vector options; 025 private boolean negative; 026 027 // This constructor is used for convenience when we know the set beforehand, 028 // e.g. \d --> new RETokenOneOf("0123456789",false, ..) 029 // \D --> new RETokenOneOf("0123456789",true, ..) 030 031 RETokenOneOf(int subIndex, String optionsStr, boolean negative, boolean insens) { 032 super(subIndex); 033 options = new Vector(); 034 this.negative = negative; 035 for (int i = 0; i < optionsStr.length(); i++) 036 options.addElement(new RETokenChar(subIndex,optionsStr.charAt(i),insens)); 037 } 038 039 RETokenOneOf(int subIndex, Vector options, boolean negative) { 040 super(subIndex); 041 this.options = options; 042 this.negative = negative; 043 } 044 045 int getMinimumLength() { 046 int min = Integer.MAX_VALUE; 047 int x; 048 for (int i=0; i < options.size(); i++) { 049 if ((x = ((REToken) options.elementAt(i)).getMinimumLength()) < min) 050 min = x; 051 } 052 return min; 053 } 054 055 boolean match(CharIndexed input, REMatch mymatch) { 056 if (negative && (input.charAt(mymatch.index) == CharIndexed.OUT_OF_BOUNDS)) 057 return false; 058 059 REMatch newMatch = null; 060 REMatch last = null; 061 REToken tk; 062 boolean isMatch; 063 for (int i=0; i < options.size(); i++) { 064 tk = (REToken) options.elementAt(i); 065 REMatch tryMatch = (REMatch) mymatch.clone(); 066 if (tk.match(input, tryMatch)) { // match was successful 067 if (negative) return false; 068 069 if (next(input, tryMatch)) { 070 // Add tryMatch to list of possibilities. 071 if (last == null) { 072 newMatch = tryMatch; 073 last = tryMatch; 074 } else { 075 last.next = tryMatch; 076 last = tryMatch; 077 } 078 } // next succeeds 079 } // is a match 080 } // try next option 081 082 if (newMatch != null) { 083 if (negative) { 084 return false; 085 } else { 086 // set contents of mymatch equal to newMatch 087 088 // try each one that matched 089 mymatch.assignFrom(newMatch); 090 return true; 091 } 092 } else { 093 if (negative) { 094 ++mymatch.index; 095 return next(input, mymatch); 096 } else { 097 return false; 098 } 099 } 100 101 // index+1 works for [^abc] lists, not for generic lookahead (--> index) 102 } 103 104 void dump(StringBuffer os) { 105 os.append(negative ? "[^" : "(?:"); 106 for (int i = 0; i < options.size(); i++) { 107 if (!negative && (i > 0)) os.append('|'); 108 ((REToken) options.elementAt(i)).dumpAll(os); 109 } 110 os.append(negative ? ']' : ')'); 111 } 112}