PageRenderTime 18ms CodeModel.GetById 2ms app.highlight 12ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at2-build190607/src/edu/vub/util/Matcher.java

http://ambienttalk.googlecode.com/
Java | 305 lines | 115 code | 27 blank | 163 comment | 15 complexity | 36dc0f3a9709835a3fb258fc5f2533e3 MD5 | raw file
  1/* Matcher.java -- Instance of a regular expression applied to a char sequence.
  2 Copyright (C) 2002, 2004 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., 59 Temple Place, Suite 330, Boston, MA
 19 02111-1307 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
 38package edu.vub.util;
 39
 40import edu.vub.util.regexp.REMatch;
 41
 42/**
 43 * Instance of a regular expression applied to a char sequence.
 44 *
 45 * @since 1.4
 46 */
 47public class Matcher {
 48	private Pattern pattern;
 49
 50	private StringBuffer input;
 51
 52	private int position;
 53
 54	private int appendPosition;
 55
 56	private REMatch match;
 57
 58	Matcher(Pattern pattern, StringBuffer input) {
 59		this.pattern = pattern;
 60		this.input = input;
 61	}
 62
 63	/**
 64	 * @param sb The target string buffer
 65	 * @param replacement The replacement string
 66	 *
 67	 * @exception IllegalStateException If no match has yet been attempted,
 68	 * or if the previous match operation failed
 69	 * @exception IndexOutOfBoundsException If the replacement string refers
 70	 * to a capturing group that does not exist in the pattern
 71	 */
 72	public Matcher appendReplacement(StringBuffer sb, String replacement)
 73			throws IllegalStateException {
 74		assertMatchOp();
 75		sb.append(input.substring(appendPosition, match.getStartIndex())
 76				.toString());
 77		sb.append(match.substituteInto(replacement));
 78		appendPosition = match.getEndIndex();
 79		return this;
 80	}
 81
 82	/**
 83	 * @param sb The target string buffer
 84	 */
 85	public StringBuffer appendTail(StringBuffer sb) {
 86		sb.append(input.substring(appendPosition, input.length()).toString());
 87		return sb;
 88	}
 89
 90	/**
 91	 * @exception IllegalStateException If no match has yet been attempted,
 92	 * or if the previous match operation failed
 93	 */
 94	public int end() throws IllegalStateException {
 95		assertMatchOp();
 96		return match.getEndIndex();
 97	}
 98
 99	/**
100	 * @param group The index of a capturing group in this matcher's pattern
101	 *
102	 * @exception IllegalStateException If no match has yet been attempted,
103	 * or if the previous match operation failed
104	 * @exception IndexOutOfBoundsException If the replacement string refers
105	 * to a capturing group that does not exist in the pattern
106	 */
107	public int end(int group) throws IllegalStateException {
108		assertMatchOp();
109		return match.getEndIndex(group);
110	}
111
112	/**
113	 * Attempts to find the next subsequence of the input sequence that matches the pattern. 
114	 * <p>
115	 * This method starts at the beginning of the input sequence or, if a previous invocation of 
116	 * the method was successful and the matcher has not since been reset, at the first character 
117	 * not matched by the previous match.
118	 * <p>
119	 * If the match succeeds then more information can be obtained via the start, end, and group 
120	 * methods.
121	 * @return true if, and only if, a subsequence of the input sequence matches this matcher's pattern
122	 */
123	public boolean find() {
124		boolean first = (match == null);
125		match = pattern.getRE().getMatch(input, position);
126		if (match != null) {
127			int endIndex = match.getEndIndex();
128			// Are we stuck at the same position?
129			if (!first && endIndex == position) {
130				match = null;
131				// Not at the end of the input yet?
132				if (position < input.length() - 1) {
133					position++;
134					return find(position);
135				} else
136					return false;
137			}
138			position = endIndex;
139			return true;
140		}
141		return false;
142	}
143
144	/**
145	 * @param start The index to start the new pattern matching
146	 *
147	 * @exception IndexOutOfBoundsException If the replacement string refers
148	 * to a capturing group that does not exist in the pattern
149	 */
150	public boolean find(int start) {
151		match = pattern.getRE().getMatch(input, start);
152		if (match != null) {
153			position = match.getEndIndex();
154			return true;
155		}
156		return false;
157	}
158
159	/**
160	 * @exception IllegalStateException If no match has yet been attempted,
161	 * or if the previous match operation failed
162	 */
163	public String group() {
164		assertMatchOp();
165		return match.toString();
166	}
167
168	/**
169	 * @param group The index of a capturing group in this matcher's pattern
170	 *
171	 * @exception IllegalStateException If no match has yet been attempted,
172	 * or if the previous match operation failed
173	 * @exception IndexOutOfBoundsException If the replacement string refers
174	 * to a capturing group that does not exist in the pattern
175	 */
176	public String group(int group) throws IllegalStateException {
177		assertMatchOp();
178		return match.toString(group);
179	}
180
181	/**
182	 * @param replacement The replacement string
183	 */
184	public String replaceFirst(String replacement) {
185		reset();
186		// Semantics might not quite match
187		return pattern.getRE().substitute(input, replacement, position);
188	}
189
190	/**
191	 * @param replacement The replacement string
192	 */
193	public String replaceAll(String replacement) {
194		reset();
195		return pattern.getRE().substituteAll(input, replacement, position);
196	}
197
198	/**
199	 * Returns the number of capturing groups in this matcher's pattern.
200	 * <p>
201	 * Group zero denotes the entire pattern by convention. It is not included in this count.
202	 * <p>
203	 * Any non-negative integer smaller than or equal to the value returned by this method is 
204	 * guaranteed to be a valid group index for this matcher.
205	 *
206	 * @return The number of capturing groups in this matcher's pattern
207	 */
208	public int groupCount() {
209		return pattern.getRE().getNumSubs();
210	}
211
212	/**
213	 * Attempts to match the input sequence, starting at the beginning, against the pattern.
214	 * <p>
215	 * Like the <code>matches</code> method, this method always starts at the beginning of the 
216	 * input sequence; unlike that method, it does not require that the entire input sequence be 
217	 * matched.
218	 * <p>
219	 * If the match succeeds then more information can be obtained via the <code>start</code>, 
220	 * <code>end</code>, and <code>group</code> methods.
221	 * 
222	 * @return true if, and only if, a prefix of the input sequence matches this matcher's pattern
223	 */
224	public boolean lookingAt() {
225		match = pattern.getRE().getMatch(input, 0);
226		if (match != null) {
227			if (match.getStartIndex() == 0)
228				return true;
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		return find(0);
246	}
247
248	/**
249	 * Returns the Pattern that is interpreted by this Matcher
250	 */
251	public Pattern pattern() {
252		return pattern;
253	}
254
255	/**
256	 * Resets this matcher.
257	 * <p>
258	 * Resetting a matcher discards all of its explicit state information and sets its append 
259	 * position to zero.
260	 * 
261	 * @return This matcher
262	 */
263	public Matcher reset() {
264		position = 0;
265		match = null;
266		return this;
267	}
268
269	/**
270	 * @param input The new input character sequence
271	 */
272	public Matcher reset(StringBuffer input) {
273		this.input = input;
274		return reset();
275	}
276
277	/**
278	 * @param group The index of a capturing group in this matcher's pattern
279	 *
280	 * @exception IllegalStateException If no match has yet been attempted,
281	 * or if the previous match operation failed
282	 */
283	public int start() throws IllegalStateException {
284		assertMatchOp();
285		return match.getStartIndex();
286	}
287
288	/**
289	 * @param group The index of a capturing group in this matcher's pattern
290	 *
291	 * @exception IllegalStateException If no match has yet been attempted,
292	 * or if the previous match operation failed
293	 * @exception IndexOutOfBoundsException If the replacement string refers
294	 * to a capturing group that does not exist in the pattern
295	 */
296	public int start(int group) throws IllegalStateException {
297		assertMatchOp();
298		return match.getStartIndex(group);
299	}
300
301	private void assertMatchOp() {
302		if (match == null)
303			throw new IllegalStateException();
304	}
305}