OSDN Git Service

Merged gcj-eclipse branch to trunk.
[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.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 }