OSDN Git Service

Imported GNU Classpath 0.90
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / util / regex / Matcher.java
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.regexp.RE;
42 import gnu.regexp.REMatch;
43 import gnu.regexp.CharIndexed;
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);
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);
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     return reset();
282   }
283   
284   /**
285    * @returns the index of a capturing group in this matcher's pattern
286    *
287    * @exception IllegalStateException If no match has yet been attempted,
288    * or if the previous match operation failed
289    */
290   public int start ()
291     throws IllegalStateException
292   {
293     assertMatchOp();
294     return match.getStartIndex();
295   }
296
297   /**
298    * @param group The index of a capturing group in this matcher's pattern
299    *
300    * @exception IllegalStateException If no match has yet been attempted,
301    * or if the previous match operation failed
302    * @exception IndexOutOfBoundsException If the replacement string refers
303    * to a capturing group that does not exist in the pattern
304    */
305   public int start (int group)
306     throws IllegalStateException
307   {
308     assertMatchOp();
309     return match.getStartIndex(group);
310   }
311
312   private void assertMatchOp()
313   {
314     if (match == null) throw new IllegalStateException();
315   }
316 }