summaryrefslogtreecommitdiff
path: root/libjava/classpath/gnu/java/util/regex/REMatch.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/java/util/regex/REMatch.java')
-rw-r--r--libjava/classpath/gnu/java/util/regex/REMatch.java362
1 files changed, 362 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/java/util/regex/REMatch.java b/libjava/classpath/gnu/java/util/regex/REMatch.java
new file mode 100644
index 000000000..5940094ba
--- /dev/null
+++ b/libjava/classpath/gnu/java/util/regex/REMatch.java
@@ -0,0 +1,362 @@
+/* gnu/regexp/REMatch.java
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.util.regex;
+
+import gnu.java.lang.CPStringBuilder;
+
+import java.io.Serializable;
+
+/**
+ * An instance of this class represents a match
+ * completed by a gnu.regexp matching function. It can be used
+ * to obtain relevant information about the location of a match
+ * or submatch.
+ *
+ * @author <A HREF="mailto:wes@cacas.org">Wes Biggs</A>
+ */
+public final class REMatch implements Serializable, Cloneable
+{
+ private String matchedText;
+ private CharIndexed matchedCharIndexed;
+
+ // These variables are package scope for fast access within the engine
+ int eflags; // execution flags this match was made using
+
+ // Offset in source text where match was tried. This is zero-based;
+ // the actual position in the source text is given by (offset + anchor).
+ int offset;
+
+ // Anchor position refers to the index into the source input
+ // at which the matching operation began.
+ // This is also useful for the ANCHORINDEX option.
+ int anchor;
+
+ // Package scope; used by RE.
+ int index; // used while matching to mark current match position in input
+ // start1[i] is set when the i-th subexp starts. And start1[i] is copied
+ // to start[i] when the i-th subexp ends. So start[i] keeps the previously
+ // assigned value while the i-th subexp is being processed. This makes
+ // backreference to the i-th subexp within the i-th subexp possible.
+ int[] start; // start positions (relative to offset) for each (sub)exp.
+ int[] start1; // start positions (relative to offset) for each (sub)exp.
+ int[] end; // end positions for the same
+ // start[i] == -1 or end[i] == -1 means that the start/end position is void.
+ // start[i] == p or end[i] == p where p < 0 and p != -1 means that
+ // the actual start/end position is (p+1). Start/end positions may
+ // become negative when the subexpression is in a RETokenLookBehind.
+ boolean empty; // empty string matched. This flag is used only within
+ // RETokenRepeated.
+
+ BacktrackStack backtrackStack;
+
+ public Object clone ()
+ {
+ try
+ {
+ REMatch copy = (REMatch) super.clone ();
+
+ copy.start = (int[]) start.clone ();
+ copy.start1 = (int[]) start1.clone ();
+ copy.end = (int[]) end.clone ();
+
+ return copy;
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw new Error (); // doesn't happen
+ }
+ }
+
+ void assignFrom (REMatch other)
+ {
+ start = other.start;
+ start1 = other.start1;
+ end = other.end;
+ index = other.index;
+ backtrackStack = other.backtrackStack;
+ }
+
+ REMatch (int subs, int anchor, int eflags)
+ {
+ start = new int[subs + 1];
+ start1 = new int[subs + 1];
+ end = new int[subs + 1];
+ this.anchor = anchor;
+ this.eflags = eflags;
+ clear (anchor);
+ }
+
+ void finish (CharIndexed text)
+ {
+ start[0] = 0;
+ CPStringBuilder sb = new CPStringBuilder ();
+ int i;
+ for (i = 0; i < end[0]; i++)
+ sb.append (text.charAt (i));
+ matchedText = sb.toString ();
+ matchedCharIndexed = text;
+ for (i = 0; i < start.length; i++)
+ {
+ // If any subexpressions didn't terminate, they don't count
+ // TODO check if this code ever gets hit
+ if ((start[i] == -1) ^ (end[i] == -1))
+ {
+ start[i] = -1;
+ end[i] = -1;
+ }
+ }
+ backtrackStack = null;
+ }
+
+ /** Clears the current match and moves the offset to the new index. */
+ void clear (int index)
+ {
+ offset = index;
+ this.index = 0;
+ for (int i = 0; i < start.length; i++)
+ {
+ start[i] = start1[i] = end[i] = -1;
+ }
+ backtrackStack = null;
+ }
+
+ /**
+ * Returns the string matching the pattern. This makes it convenient
+ * to write code like the following:
+ * <P>
+ * <code>
+ * REMatch myMatch = myExpression.getMatch(myString);<br>
+ * if (myMatch != null) System.out.println("Regexp found: "+myMatch);
+ * </code>
+ */
+ public String toString ()
+ {
+ return matchedText;
+ }
+
+ /**
+ * Returns the index within the input text where the match in its entirety
+ * began.
+ */
+ public int getStartIndex ()
+ {
+ return offset + start[0];
+ }
+
+ /**
+ * Returns the index within the input string where the match in
+ * its entirety ends. The return value is the next position after
+ * the end of the string; therefore, a match created by the
+ * following call:
+ *
+ * <P>
+ * <code>REMatch myMatch = myExpression.getMatch(myString);</code>
+ * <P>
+ * can be viewed (given that myMatch is not null) by creating
+ * <P>
+ * <code>String theMatch = myString.substring(myMatch.getStartIndex(),
+ * myMatch.getEndIndex());</code>
+ * <P>
+ * But you can save yourself that work, since the <code>toString()</code>
+ * method (above) does exactly that for you.
+ */
+ public int getEndIndex ()
+ {
+ return offset + end[0];
+ }
+
+ /**
+ * Returns the string matching the given subexpression. The subexpressions
+ * are indexed starting with one, not zero. That is, the subexpression
+ * identified by the first set of parentheses in a regular expression
+ * could be retrieved from an REMatch by calling match.toString(1).
+ *
+ * @param sub Index of the subexpression.
+ */
+ public String toString (int sub)
+ {
+ if ((sub >= start.length) || sub < 0)
+ throw new IndexOutOfBoundsException ("No group " + sub);
+ if (start[sub] == -1)
+ return null;
+ if (start[sub] >= 0 && end[sub] <= matchedText.length ())
+ return (matchedText.substring (start[sub], end[sub]));
+ else
+ {
+ // This case occurs with RETokenLookAhead or RETokenLookBehind.
+ CPStringBuilder sb = new CPStringBuilder ();
+ int s = start[sub];
+ int e = end[sub];
+ if (s < 0)
+ s += 1;
+ if (e < 0)
+ e += 1;
+ for (int i = start[0] + s; i < start[0] + e; i++)
+ sb.append (matchedCharIndexed.charAt (i));
+ return sb.toString ();
+ }
+ }
+
+ /**
+ * Returns the index within the input string used to generate this match
+ * where subexpression number <i>sub</i> begins, or <code>-1</code> if
+ * the subexpression does not exist. The initial position is zero.
+ *
+ * @param sub Subexpression index
+ * @deprecated Use getStartIndex(int) instead.
+ */
+ public int getSubStartIndex (int sub)
+ {
+ if (sub >= start.length)
+ return -1;
+ int x = start[sub];
+ return (x == -1) ? x : (x >= 0) ? offset + x : offset + x + 1;
+ }
+
+ /**
+ * Returns the index within the input string used to generate this match
+ * where subexpression number <i>sub</i> begins, or <code>-1</code> if
+ * the subexpression does not exist. The initial position is zero.
+ *
+ * @param sub Subexpression index
+ * @since gnu.regexp 1.1.0
+ */
+ public int getStartIndex (int sub)
+ {
+ if (sub >= start.length)
+ return -1;
+ int x = start[sub];
+ return (x == -1) ? x : (x >= 0) ? offset + x : offset + x + 1;
+ }
+
+ /**
+ * Returns the index within the input string used to generate this match
+ * where subexpression number <i>sub</i> ends, or <code>-1</code> if
+ * the subexpression does not exist. The initial position is zero.
+ *
+ * @param sub Subexpression index
+ * @deprecated Use getEndIndex(int) instead
+ */
+ public int getSubEndIndex (int sub)
+ {
+ if (sub >= start.length)
+ return -1;
+ int x = end[sub];
+ return (x == -1) ? x : (x >= 0) ? offset + x : offset + x + 1;
+ }
+
+ /**
+ * Returns the index within the input string used to generate this match
+ * where subexpression number <i>sub</i> ends, or <code>-1</code> if
+ * the subexpression does not exist. The initial position is zero.
+ *
+ * @param sub Subexpression index
+ */
+ public int getEndIndex (int sub)
+ {
+ if (sub >= start.length)
+ return -1;
+ int x = end[sub];
+ return (x == -1) ? x : (x >= 0) ? offset + x : offset + x + 1;
+ }
+
+ /**
+ * Substitute the results of this match to create a new string.
+ * This is patterned after PERL, so the tokens to watch out for are
+ * <code>$0</code> through <code>$9</code>. <code>$0</code> matches
+ * the full substring matched; <code>$<i>n</i></code> matches
+ * subexpression number <i>n</i>.
+ * <code>$10, $11, ...</code> may match the 10th, 11th, ... subexpressions
+ * if such subexpressions exist.
+ *
+ * @param input A string consisting of literals and <code>$<i>n</i></code> tokens.
+ */
+ public String substituteInto (String input)
+ {
+ // a la Perl, $0 is whole thing, $1 - $9 are subexpressions
+ CPStringBuilder output = new CPStringBuilder ();
+ int pos;
+ for (pos = 0; pos < input.length () - 1; pos++)
+ {
+ if ((input.charAt (pos) == '$')
+ && (Character.isDigit (input.charAt (pos + 1))))
+ {
+ int val = Character.digit (input.charAt (++pos), 10);
+ int pos1 = pos + 1;
+ while (pos1 < input.length () &&
+ Character.isDigit (input.charAt (pos1)))
+ {
+ int val1 =
+ val * 10 + Character.digit (input.charAt (pos1), 10);
+ if (val1 >= start.length)
+ break;
+ pos1++;
+ val = val1;
+ }
+ pos = pos1 - 1;
+
+ if (val < start.length)
+ {
+ output.append (toString (val));
+ }
+ }
+ else
+ output.append (input.charAt (pos));
+ }
+ if (pos < input.length ())
+ output.append (input.charAt (pos));
+ return output.toString ();
+ }
+
+/* The following are used for debugging purpose
+ public static String d(REMatch m) {
+ if (m == null) return "null";
+ else return "[" + m.index + "]";
+ }
+
+ public String substringUptoIndex(CharIndexed input) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < index; i++) {
+ sb.append(input.charAt(i));
+ }
+ return sb.toString();
+ }
+*/
+
+}