/interpreter/tags/at2dist170907/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. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  15. 02111-1307 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package edu.vub.util;
  32. import edu.vub.util.regexp.REMatch;
  33. /**
  34. * Instance of a regular expression applied to a char sequence.
  35. *
  36. * @since 1.4
  37. */
  38. public class Matcher {
  39. private Pattern pattern;
  40. private StringBuffer input;
  41. private int position;
  42. private int appendPosition;
  43. private REMatch match;
  44. Matcher(Pattern pattern, StringBuffer input) {
  45. this.pattern = pattern;
  46. this.input = input;
  47. }
  48. /**
  49. * @param sb The target string buffer
  50. * @param replacement The replacement string
  51. *
  52. * @exception IllegalStateException If no match has yet been attempted,
  53. * or if the previous match operation failed
  54. * @exception IndexOutOfBoundsException If the replacement string refers
  55. * to a capturing group that does not exist in the pattern
  56. */
  57. public Matcher appendReplacement(StringBuffer sb, String replacement)
  58. throws IllegalStateException {
  59. assertMatchOp();
  60. sb.append(input.substring(appendPosition, match.getStartIndex())
  61. .toString());
  62. sb.append(match.substituteInto(replacement));
  63. appendPosition = match.getEndIndex();
  64. return this;
  65. }
  66. /**
  67. * @param sb The target string buffer
  68. */
  69. public StringBuffer appendTail(StringBuffer sb) {
  70. sb.append(input.substring(appendPosition, input.length()).toString());
  71. return sb;
  72. }
  73. /**
  74. * @exception IllegalStateException If no match has yet been attempted,
  75. * or if the previous match operation failed
  76. */
  77. public int end() throws IllegalStateException {
  78. assertMatchOp();
  79. return match.getEndIndex();
  80. }
  81. /**
  82. * @param group The index of a capturing group in this matcher's pattern
  83. *
  84. * @exception IllegalStateException If no match has yet been attempted,
  85. * or if the previous match operation failed
  86. * @exception IndexOutOfBoundsException If the replacement string refers
  87. * to a capturing group that does not exist in the pattern
  88. */
  89. public int end(int group) throws IllegalStateException {
  90. assertMatchOp();
  91. return match.getEndIndex(group);
  92. }
  93. /**
  94. * Attempts to find the next subsequence of the input sequence that matches the pattern.
  95. * <p>
  96. * This method starts at the beginning of the input sequence or, if a previous invocation of
  97. * the method was successful and the matcher has not since been reset, at the first character
  98. * not matched by the previous match.
  99. * <p>
  100. * If the match succeeds then more information can be obtained via the start, end, and group
  101. * methods.
  102. * @return true if, and only if, a subsequence of the input sequence matches this matcher's pattern
  103. */
  104. public boolean find() {
  105. boolean first = (match == null);
  106. match = pattern.getRE().getMatch(input, position);
  107. if (match != null) {
  108. int endIndex = match.getEndIndex();
  109. // Are we stuck at the same position?
  110. if (!first && endIndex == position) {
  111. match = null;
  112. // Not at the end of the input yet?
  113. if (position < input.length() - 1) {
  114. position++;
  115. return find(position);
  116. } else
  117. return false;
  118. }
  119. position = endIndex;
  120. return true;
  121. }
  122. return false;
  123. }
  124. /**
  125. * @param start The index to start the new pattern matching
  126. *
  127. * @exception IndexOutOfBoundsException If the replacement string refers
  128. * to a capturing group that does not exist in the pattern
  129. */
  130. public boolean find(int start) {
  131. match = pattern.getRE().getMatch(input, start);
  132. if (match != null) {
  133. position = match.getEndIndex();
  134. return true;
  135. }
  136. return false;
  137. }
  138. /**
  139. * @exception IllegalStateException If no match has yet been attempted,
  140. * or if the previous match operation failed
  141. */
  142. public String group() {
  143. assertMatchOp();
  144. return match.toString();
  145. }
  146. /**
  147. * @param group The index of a capturing group in this matcher's pattern
  148. *
  149. * @exception IllegalStateException If no match has yet been attempted,
  150. * or if the previous match operation failed
  151. * @exception IndexOutOfBoundsException If the replacement string refers
  152. * to a capturing group that does not exist in the pattern
  153. */
  154. public String group(int group) throws IllegalStateException {
  155. assertMatchOp();
  156. return match.toString(group);
  157. }
  158. /**
  159. * @param replacement The replacement string
  160. */
  161. public String replaceFirst(String replacement) {
  162. reset();
  163. // Semantics might not quite match
  164. return pattern.getRE().substitute(input, replacement, position);
  165. }
  166. /**
  167. * @param replacement The replacement string
  168. */
  169. public String replaceAll(String replacement) {
  170. reset();
  171. return pattern.getRE().substituteAll(input, replacement, position);
  172. }
  173. /**
  174. * Returns the number of capturing groups in this matcher's pattern.
  175. * <p>
  176. * Group zero denotes the entire pattern by convention. It is not included in this count.
  177. * <p>
  178. * Any non-negative integer smaller than or equal to the value returned by this method is
  179. * guaranteed to be a valid group index for this matcher.
  180. *
  181. * @return The number of capturing groups in this matcher's pattern
  182. */
  183. public int groupCount() {
  184. return pattern.getRE().getNumSubs();
  185. }
  186. /**
  187. * Attempts to match the input sequence, starting at the beginning, against the pattern.
  188. * <p>
  189. * Like the <code>matches</code> method, this method always starts at the beginning of the
  190. * input sequence; unlike that method, it does not require that the entire input sequence be
  191. * matched.
  192. * <p>
  193. * If the match succeeds then more information can be obtained via the <code>start</code>,
  194. * <code>end</code>, and <code>group</code> methods.
  195. *
  196. * @return true if, and only if, a prefix of the input sequence matches this matcher's pattern
  197. */
  198. public boolean lookingAt() {
  199. match = pattern.getRE().getMatch(input, 0);
  200. if (match != null) {
  201. if (match.getStartIndex() == 0)
  202. return true;
  203. match = null;
  204. }
  205. return false;
  206. }
  207. /**
  208. * Attempts to match the entire input sequence against the pattern.
  209. *
  210. * If the match succeeds then more information can be obtained via the
  211. * start, end, and group methods.
  212. *
  213. * @see #start
  214. * @see #end
  215. * @see #group
  216. */
  217. public boolean matches() {
  218. return find(0);
  219. }
  220. /**
  221. * Returns the Pattern that is interpreted by this Matcher
  222. */
  223. public Pattern pattern() {
  224. return pattern;
  225. }
  226. /**
  227. * Resets this matcher.
  228. * <p>
  229. * Resetting a matcher discards all of its explicit state information and sets its append
  230. * position to zero.
  231. *
  232. * @return This matcher
  233. */
  234. public Matcher reset() {
  235. position = 0;
  236. match = null;
  237. return this;
  238. }
  239. /**
  240. * @param input The new input character sequence
  241. */
  242. public Matcher reset(StringBuffer input) {
  243. this.input = input;
  244. return reset();
  245. }
  246. /**
  247. * @param group The index of a capturing group in this matcher's pattern
  248. *
  249. * @exception IllegalStateException If no match has yet been attempted,
  250. * or if the previous match operation failed
  251. */
  252. public int start() throws IllegalStateException {
  253. assertMatchOp();
  254. return match.getStartIndex();
  255. }
  256. /**
  257. * @param group The index of a capturing group in this matcher's pattern
  258. *
  259. * @exception IllegalStateException If no match has yet been attempted,
  260. * or if the previous match operation failed
  261. * @exception IndexOutOfBoundsException If the replacement string refers
  262. * to a capturing group that does not exist in the pattern
  263. */
  264. public int start(int group) throws IllegalStateException {
  265. assertMatchOp();
  266. return match.getStartIndex(group);
  267. }
  268. private void assertMatchOp() {
  269. if (match == null)
  270. throw new IllegalStateException();
  271. }
  272. }