GNU Classpath (0.95) | |
Frames | No Frames |
1: /* Matcher.java -- Instance of a regular expression applied to a char sequence. 2: Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.util.regex; 40: 41: import gnu.java.util.regex.CharIndexed; 42: import gnu.java.util.regex.RE; 43: import gnu.java.util.regex.REMatch; 44: 45: /** 46: * Instance of a regular expression applied to a char sequence. 47: * 48: * @since 1.4 49: */ 50: public final class Matcher implements MatchResult 51: { 52: private Pattern pattern; 53: private CharSequence input; 54: // We use CharIndexed as an input object to the getMatch method in order 55: // that /\G/ (the end of the previous match) may work. The information 56: // of the previous match is stored in the CharIndexed object. 57: private CharIndexed inputCharIndexed; 58: private int position; 59: private int appendPosition; 60: private REMatch match; 61: 62: Matcher(Pattern pattern, CharSequence input) 63: { 64: this.pattern = pattern; 65: this.input = input; 66: this.inputCharIndexed = RE.makeCharIndexed(input, 0); 67: } 68: 69: /** 70: * @param sb The target string buffer 71: * @param replacement The replacement string 72: * 73: * @exception IllegalStateException If no match has yet been attempted, 74: * or if the previous match operation failed 75: * @exception IndexOutOfBoundsException If the replacement string refers 76: * to a capturing group that does not exist in the pattern 77: */ 78: public Matcher appendReplacement (StringBuffer sb, String replacement) 79: throws IllegalStateException 80: { 81: assertMatchOp(); 82: sb.append(input.subSequence(appendPosition, 83: match.getStartIndex()).toString()); 84: sb.append(RE.getReplacement(replacement, match, 85: RE.REG_REPLACE_USE_BACKSLASHESCAPE)); 86: appendPosition = match.getEndIndex(); 87: return this; 88: } 89: 90: /** 91: * @param sb The target string buffer 92: */ 93: public StringBuffer appendTail (StringBuffer sb) 94: { 95: sb.append(input.subSequence(appendPosition, input.length()).toString()); 96: return sb; 97: } 98: 99: /** 100: * @exception IllegalStateException If no match has yet been attempted, 101: * or if the previous match operation failed 102: */ 103: public int end () 104: throws IllegalStateException 105: { 106: assertMatchOp(); 107: return match.getEndIndex(); 108: } 109: 110: /** 111: * @param group The index of a capturing group in this matcher's pattern 112: * 113: * @exception IllegalStateException If no match has yet been attempted, 114: * or if the previous match operation failed 115: * @exception IndexOutOfBoundsException If the replacement string refers 116: * to a capturing group that does not exist in the pattern 117: */ 118: public int end (int group) 119: throws IllegalStateException 120: { 121: assertMatchOp(); 122: return match.getEndIndex(group); 123: } 124: 125: public boolean find () 126: { 127: boolean first = (match == null); 128: match = pattern.getRE().getMatch(inputCharIndexed, position); 129: if (match != null) 130: { 131: int endIndex = match.getEndIndex(); 132: // Are we stuck at the same position? 133: if (!first && endIndex == position) 134: { 135: match = null; 136: // Not at the end of the input yet? 137: if (position < input.length() - 1) 138: { 139: position++; 140: return find(position); 141: } 142: else 143: return false; 144: } 145: position = endIndex; 146: return true; 147: } 148: return false; 149: } 150: 151: /** 152: * @param start The index to start the new pattern matching 153: * 154: * @exception IndexOutOfBoundsException If the replacement string refers 155: * to a capturing group that does not exist in the pattern 156: */ 157: public boolean find (int start) 158: { 159: match = pattern.getRE().getMatch(inputCharIndexed, start); 160: if (match != null) 161: { 162: position = match.getEndIndex(); 163: return true; 164: } 165: return false; 166: } 167: 168: /** 169: * @exception IllegalStateException If no match has yet been attempted, 170: * or if the previous match operation failed 171: */ 172: public String group () 173: { 174: assertMatchOp(); 175: return match.toString(); 176: } 177: 178: /** 179: * @param group The index of a capturing group in this matcher's pattern 180: * 181: * @exception IllegalStateException If no match has yet been attempted, 182: * or if the previous match operation failed 183: * @exception IndexOutOfBoundsException If the replacement string refers 184: * to a capturing group that does not exist in the pattern 185: */ 186: public String group (int group) 187: throws IllegalStateException 188: { 189: assertMatchOp(); 190: return match.toString(group); 191: } 192: 193: /** 194: * @param replacement The replacement string 195: */ 196: public String replaceFirst (String replacement) 197: { 198: reset(); 199: // Semantics might not quite match 200: return pattern.getRE().substitute(input, replacement, position, 201: RE.REG_REPLACE_USE_BACKSLASHESCAPE); 202: } 203: 204: /** 205: * @param replacement The replacement string 206: */ 207: public String replaceAll (String replacement) 208: { 209: reset(); 210: return pattern.getRE().substituteAll(input, replacement, position, 211: RE.REG_REPLACE_USE_BACKSLASHESCAPE); 212: } 213: 214: public int groupCount () 215: { 216: return pattern.getRE().getNumSubs(); 217: } 218: 219: public boolean lookingAt () 220: { 221: match = pattern.getRE().getMatch(inputCharIndexed, 0, RE.REG_FIX_STARTING_POSITION, null); 222: if (match != null) 223: { 224: if (match.getStartIndex() == 0) 225: { 226: position = match.getEndIndex(); 227: return true; 228: } 229: match = null; 230: } 231: return false; 232: } 233: 234: /** 235: * Attempts to match the entire input sequence against the pattern. 236: * 237: * If the match succeeds then more information can be obtained via the 238: * start, end, and group methods. 239: * 240: * @see #start() 241: * @see #end() 242: * @see #group() 243: */ 244: public boolean matches () 245: { 246: match = pattern.getRE().getMatch(inputCharIndexed, 0, RE.REG_TRY_ENTIRE_MATCH|RE.REG_FIX_STARTING_POSITION, null); 247: if (match != null) 248: { 249: if (match.getStartIndex() == 0) 250: { 251: position = match.getEndIndex(); 252: if (position == input.length()) 253: return true; 254: } 255: match = null; 256: } 257: return false; 258: } 259: 260: /** 261: * Returns the Pattern that is interpreted by this Matcher 262: */ 263: public Pattern pattern () 264: { 265: return pattern; 266: } 267: 268: public Matcher reset () 269: { 270: position = 0; 271: match = null; 272: return this; 273: } 274: 275: /** 276: * @param input The new input character sequence 277: */ 278: public Matcher reset (CharSequence input) 279: { 280: this.input = input; 281: this.inputCharIndexed = RE.makeCharIndexed(input, 0); 282: return reset(); 283: } 284: 285: /** 286: * @returns the index of a capturing group in this matcher's pattern 287: * 288: * @exception IllegalStateException If no match has yet been attempted, 289: * or if the previous match operation failed 290: */ 291: public int start () 292: throws IllegalStateException 293: { 294: assertMatchOp(); 295: return match.getStartIndex(); 296: } 297: 298: /** 299: * @param group The index of a capturing group in this matcher's pattern 300: * 301: * @exception IllegalStateException If no match has yet been attempted, 302: * or if the previous match operation failed 303: * @exception IndexOutOfBoundsException If the replacement string refers 304: * to a capturing group that does not exist in the pattern 305: */ 306: public int start (int group) 307: throws IllegalStateException 308: { 309: assertMatchOp(); 310: return match.getStartIndex(group); 311: } 312: 313: /** 314: * @return True if and only if the matcher hit the end of input. 315: */ 316: public boolean hitEnd() 317: { 318: return inputCharIndexed.hitEnd(); 319: } 320: 321: /** 322: * @return A string expression of this matcher. 323: */ 324: public String toString() 325: { 326: StringBuilder sb = new StringBuilder(); 327: sb.append(this.getClass().getName()) 328: .append("[pattern=").append(pattern.pattern()) 329: .append(" region=").append("0").append(",").append(input.length()) 330: .append(" lastmatch=").append(match == null ? "" : match.toString()) 331: .append("]"); 332: return sb.toString(); 333: } 334: 335: private void assertMatchOp() 336: { 337: if (match == null) throw new IllegalStateException(); 338: } 339: }
GNU Classpath (0.95) |