Merged gcj-eclipse branch to trunk.

From-SVN: r120621
This commit is contained in:
Tom Tromey
2007-01-09 19:58:05 +00:00
parent c648dedbde
commit 97b8365caf
17478 changed files with 606493 additions and 100744 deletions
@@ -76,6 +76,13 @@ public interface CharIndexed {
*/
boolean move(int index);
/**
* Shifts the input buffer by a given number of positions. Returns
* true if the new cursor position is valid or cursor position is at
* the end of input.
*/
boolean move1(int index); // I cannot think of a better name for this.
/**
* Returns true if the most recent move() operation placed the cursor
* position at a valid position in the input.
@@ -104,6 +111,16 @@ public interface CharIndexed {
*/
REMatch getLastMatch();
/**
* Sets the information used for hitEnd().
*/
void setHitEnd(REMatch match);
/**
* Returns whether the matcher has hit the end of input.
*/
boolean hitEnd();
/**
* Returns the anchor.
*/
@@ -62,6 +62,10 @@ class CharIndexedCharSequence implements CharIndexed, Serializable {
return ((anchor += index) < len);
}
public boolean move1(int index) {
return ((anchor += index) <= len);
}
public CharIndexed lookBehind(int index, int length) {
if (length > (anchor + index)) length = anchor + index;
return new CharIndexedCharSequence(s, anchor + index - length);
@@ -77,6 +81,15 @@ class CharIndexedCharSequence implements CharIndexed, Serializable {
lastMatch.anchor = anchor;
}
public REMatch getLastMatch() { return lastMatch; }
private int rightmostTriedPosition = 0;
public void setHitEnd(REMatch match) {
int pos = anchor + match.index;
if (pos > rightmostTriedPosition) rightmostTriedPosition = pos;
}
public boolean hitEnd() { return rightmostTriedPosition >= len; }
public int getAnchor() { return anchor; }
public void setAnchor(int anchor) { this.anchor = anchor; }
}
@@ -166,6 +166,16 @@ class CharIndexedInputStream implements CharIndexed {
"difficult to support getLastMatch for an input stream");
}
public void setHitEnd(REMatch match) {
throw new UnsupportedOperationException(
"difficult to support setHitEnd for an input stream");
}
public boolean hitEnd() {
throw new UnsupportedOperationException(
"difficult to support hitEnd for an input stream");
}
public int getAnchor() {
throw new UnsupportedOperationException(
"difficult to support getAnchor for an input stream");
@@ -176,6 +186,10 @@ class CharIndexedInputStream implements CharIndexed {
"difficult to support setAnchor for an input stream");
}
public boolean move1(int index) {
throw new UnsupportedOperationException(
"difficult to support move1 for an input stream");
}
}
+30 -4
View File
@@ -130,7 +130,11 @@ public class RE extends REToken {
private static final String VERSION = "1.1.5-dev";
// The localized strings are kept in a separate file
private static ResourceBundle messages = PropertyResourceBundle.getBundle("gnu/java/util/regex/MessagesBundle", Locale.getDefault());
// Used by getLocalizedMessage().
private static ResourceBundle messages;
// Name of the bundle that contains the localized messages.
private static final String bundle = "gnu/java/util/regex/MessagesBundle";
// These are, respectively, the first and last tokens in our linked list
// If there is only one token, firstToken == lastToken
@@ -252,6 +256,13 @@ public class RE extends REToken {
*/
public static final int REG_ICASE_USASCII = 0x0800;
/**
* Execution flag.
* Do not move the position at which the search begins. If not set,
* the starting position will be moved until a match is found.
*/
public static final int REG_FIX_STARTING_POSITION = 0x1000;
/** Returns a string representing the version of the gnu.regexp package. */
public static final String version() {
return VERSION;
@@ -259,6 +270,8 @@ public class RE extends REToken {
// Retrieves a message from the ResourceBundle
static final String getLocalizedMessage(String key) {
if (messages == null)
messages = PropertyResourceBundle.getBundle(bundle, Locale.getDefault());
return messages.getString(key);
}
@@ -1643,6 +1656,7 @@ public class RE extends REToken {
/* Implements abstract method REToken.match() */
boolean match(CharIndexed input, REMatch mymatch) {
input.setHitEnd(mymatch);
if (firstToken == null) {
return next(input, mymatch);
}
@@ -1720,15 +1734,23 @@ public class RE extends REToken {
REMatch getMatchImpl(CharIndexed input, int anchor, int eflags, StringBuffer buffer) {
boolean tryEntireMatch = ((eflags & REG_TRY_ENTIRE_MATCH) != 0);
boolean doMove = ((eflags & REG_FIX_STARTING_POSITION) == 0);
RE re = (tryEntireMatch ? (RE) this.clone() : this);
if (tryEntireMatch) {
re.chain(new RETokenEnd(0, null));
RETokenEnd reEnd = new RETokenEnd(0, null);
reEnd.setFake(true);
re.chain(reEnd);
}
// Create a new REMatch to hold results
REMatch mymatch = new REMatch(numSubs, anchor, eflags);
do {
/* The following potimization is commented out because
the matching should be tried even if the length of
input is obviously too short in order that
java.util.regex.Matcher#hitEnd() may work correctly.
// Optimization: check if anchor + minimumLength > length
if (minimumLength == 0 || input.charAt(minimumLength-1) != CharIndexed.OUT_OF_BOUNDS) {
*/
if (re.match(input, mymatch)) {
REMatch best = mymatch;
// We assume that the match that coms first is the best.
@@ -1749,13 +1771,17 @@ public class RE extends REToken {
input.setLastMatch(best);
return best;
}
}
/* End of the optimization commented out
}
*/
mymatch.clear(++anchor);
// Append character to buffer if needed
if (buffer != null && input.charAt(0) != CharIndexed.OUT_OF_BOUNDS) {
buffer.append(input.charAt(0));
}
} while (input.move(1));
// java.util.regex.Matcher#hitEnd() requires that the search should
// be tried at the end of input, so we use move1(1) instead of move(1)
} while (doMove && input.move1(1));
// Special handling at end of input for e.g. "$"
if (minimumLength == 0) {
@@ -307,12 +307,12 @@ public final class REMatch implements Serializable, Cloneable {
}
/* The following are used for debugging purpose
static String d(REMatch m) {
public static String d(REMatch m) {
if (m == null) return "null";
else return "[" + m.index + "]";
}
String substringUptoIndex(CharIndexed input) {
public String substringUptoIndex(CharIndexed input) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < index; i++) {
sb.append(input.charAt(i));
@@ -54,8 +54,6 @@ import java.util.BitSet;
public final class RESyntax implements Serializable {
static final String DEFAULT_LINE_SEPARATOR = System.getProperty("line.separator");
private static final String SYNTAX_IS_FINAL = RE.getLocalizedMessage("syntax.final");
private BitSet bits;
// true for the constant defined syntaxes
@@ -513,7 +511,8 @@ public final class RESyntax implements Serializable {
* @return a reference to this object for easy chaining.
*/
public RESyntax set(int index) {
if (isFinal) throw new IllegalAccessError(SYNTAX_IS_FINAL);
if (isFinal)
throw new IllegalAccessError(RE.getLocalizedMessage("syntax.final"));
bits.set(index);
return this;
}
@@ -525,7 +524,8 @@ public final class RESyntax implements Serializable {
* @return a reference to this object for easy chaining.
*/
public RESyntax clear(int index) {
if (isFinal) throw new IllegalAccessError(SYNTAX_IS_FINAL);
if (isFinal)
throw new IllegalAccessError(RE.getLocalizedMessage("syntax.final"));
bits.clear(index);
return this;
}
@@ -548,7 +548,8 @@ public final class RESyntax implements Serializable {
* @return this object for convenient chaining
*/
public RESyntax setLineSeparator(String aSeparator) {
if (isFinal) throw new IllegalAccessError(SYNTAX_IS_FINAL);
if (isFinal)
throw new IllegalAccessError(RE.getLocalizedMessage("syntax.final"));
lineSeparator = aSeparator;
return this;
}
@@ -72,6 +72,16 @@ abstract class REToken implements Serializable, Cloneable {
/** Returns true if the match succeeded, false if it failed. */
boolean match(CharIndexed input, REMatch mymatch) {
return match(input, mymatch, false);
}
boolean matchFake(CharIndexed input, REMatch mymatch) {
return match(input, mymatch, true);
}
private boolean match(CharIndexed input, REMatch mymatch, boolean fake) {
if (!fake) {
setHitEnd(input, mymatch);
}
REMatch m = matchThis(input, mymatch);
if (m == null) return false;
if (next(input, m)) {
@@ -81,6 +91,11 @@ abstract class REToken implements Serializable, Cloneable {
return false;
}
/** Sets whether the matching occurs at the end of input */
void setHitEnd(CharIndexed input, REMatch mymatch) {
input.setHitEnd(mymatch);
}
/** Returns true if the match succeeded, false if it failed.
* The matching is done against this REToken only. Chained
* tokens are not checked.
@@ -58,15 +58,20 @@ final class RETokenChar extends REToken {
}
REMatch matchThis(CharIndexed input, REMatch mymatch) {
int z = ch.length;
if (matchOneString(input, mymatch.index)) {
mymatch.index += z;
mymatch.index += matchedLength;
return mymatch;
}
// java.util.regex.Matcher#hitEnd() requires that the length of
// partial match be counted.
mymatch.index += matchedLength;
input.setHitEnd(mymatch);
return null;
}
boolean matchOneString(CharIndexed input, int index) {
private int matchedLength;
private boolean matchOneString(CharIndexed input, int index) {
matchedLength = 0;
int z = ch.length;
char c;
for (int i=0; i<z; i++) {
@@ -74,6 +79,7 @@ final class RETokenChar extends REToken {
if (! charEquals(c, ch[i])) {
return false;
}
++matchedLength;
}
return true;
}
@@ -45,6 +45,12 @@ final class RETokenEnd extends REToken {
private String newline;
private boolean check_java_line_terminators;
/**
* Indicates whether this token is a real one generated at compile time,
* or a fake one temporarily added by RE#getMatchImpl.
*/
private boolean fake = false;
RETokenEnd(int subIndex,String newline) {
super(subIndex);
this.newline = newline;
@@ -57,10 +63,19 @@ final class RETokenEnd extends REToken {
this.check_java_line_terminators = b;
}
void setFake(boolean fake) {
this.fake = fake;
}
int getMaximumLength() {
return 0;
}
boolean match(CharIndexed input, REMatch mymatch) {
if (!fake) return super.match(input, mymatch);
return super.matchFake(input, mymatch);
}
REMatch matchThis(CharIndexed input, REMatch mymatch) {
char ch = input.charAt(mymatch.index);
if (ch == CharIndexed.OUT_OF_BOUNDS)
@@ -58,6 +58,10 @@ final class RETokenEndSub extends REToken {
return super.findMatch(input, mymatch);
}
void setHitEnd(CharIndexed input, REMatch mymatch) {
// Do nothing
}
void dump(StringBuffer os) {
// handled by RE
// But add something for debugging.
@@ -260,6 +260,14 @@ final class RETokenNamedProperty extends REToken {
return new UnicodeCategoryHandler(Character.UNASSIGNED);
if (name.equals("Lu"))
return new UnicodeCategoryHandler(Character.UPPERCASE_LETTER);
if (name.equals("all"))
return new Handler()
{
public boolean includes(char c)
{
return true;
}
};
throw new REException("unsupported name " + name, REException.REG_ESCAPE, 0);
}
@@ -120,6 +120,7 @@ final class RETokenOneOf extends REToken {
}
boolean match(CharIndexed input, REMatch mymatch) {
setHitEnd(input, mymatch);
if (matchesOneChar) return matchOneChar(input, mymatch);
else return matchOneRE(input, mymatch);
}
@@ -38,8 +38,7 @@ exception statement from your version. */
package gnu.java.util.regex;
// import java.util.Vector;
// import java.util.Stack;
import java.util.ArrayList;
final class RETokenRepeated extends REToken {
private REToken token;
@@ -168,19 +167,63 @@ final class RETokenRepeated extends REToken {
}
}
private static class FindMatchControlStack extends ArrayList {
private void push(FindMatchControl control) {
add(control);
}
private FindMatchControl pop() {
return (FindMatchControl)remove(size()-1);
}
private boolean empty() {
return isEmpty();
}
}
private static class FindMatchControl {
DoablesFinder finder;
FindMatchControl(DoablesFinder finder) {
this.finder = finder;
}
}
private REMatch findMatch(BacktrackStack stack) {
// Avoid using recursive calls.
return findMatch(stack, new FindMatchControlStack());
}
private REMatch findMatch(BacktrackStack stack,
FindMatchControlStack controlStack) {
REMatch result = null;
StackedInfo si = null;
CharIndexed input = null;
int numRepeats = 0;
REMatch mymatch = null;
int[] visited = null;
DoablesFinder finder = null;
// Avoid using recursive calls because a match can be very long.
// This is the first entry point of this method.
// If you want to call this method recursively and you need the
// result returned, save necessary information in a FindMatchControl
// object and push it to controlStack, then continue from this point.
// You can check the result after exiting MAIN_LOOP.
MAIN_LOOP0:
while (true) {
// This is the second entry point of this method.
// If you want to call this method recursively but you do not need the
// result returned, just continue from this point.
MAIN_LOOP:
while (true) {
if (stack.empty()) return null;
StackedInfo si = (StackedInfo)(stack.peek());
CharIndexed input = si.input;
int numRepeats = si.numRepeats;
REMatch mymatch = si.match;
int[] visited = si.visited;
DoablesFinder finder = si.finder;
if (stack.empty()) break MAIN_LOOP;
si = (StackedInfo)(stack.peek());
input = si.input;
numRepeats = si.numRepeats;
mymatch = si.match;
visited = si.visited;
finder = si.finder;
if (mymatch.backtrackStack == null)
mymatch.backtrackStack = new BacktrackStack();
@@ -192,12 +235,13 @@ final class RETokenRepeated extends REToken {
m1.backtrackStack.push(new BacktrackStack.Backtrack(
this, input, mymatch, stack));
}
return m1;
result = m1;
break MAIN_LOOP;
}
if (stingy) {
continue MAIN_LOOP;
}
return null;
break MAIN_LOOP;
}
if (finder == null) {
@@ -238,7 +282,8 @@ final class RETokenRepeated extends REToken {
m1.backtrackStack.push(new BacktrackStack.Backtrack(
this, input, mymatch, stack));
}
return m1;
result = m1;
break MAIN_LOOP;
}
else {
continue MAIN_LOOP;
@@ -247,8 +292,82 @@ final class RETokenRepeated extends REToken {
visited = addVisited(mymatch.index, visited);
TryAnotherResult taresult = tryAnother(stack, input, mymatch, numRepeats, finder, visited);
visited = taresult.visited;
switch (taresult.status) {
case TryAnotherResult.TRY_FURTHER:
controlStack.push(new FindMatchControl(
finder));
continue MAIN_LOOP0;
case TryAnotherResult.RESULT_FOUND:
result = taresult.result;
break MAIN_LOOP;
}
if (!stack.empty()) {
stack.pop();
}
if (possessive) {
stack.clear();
}
REMatch m1 = matchRest(input, mymatch);
if (m1 != null) {
if (! stack.empty()) {
m1.backtrackStack.push(new BacktrackStack.Backtrack(
this, input, mymatch, stack));
}
result = m1;
break MAIN_LOOP;
}
} // MAIN_LOOP
if (controlStack.empty()) return result;
FindMatchControl control = controlStack.pop();
if (possessive) {
return result;
}
if (result != null) {
result.backtrackStack.push(new BacktrackStack.Backtrack(
this, input, mymatch, stack));
return result;
}
finder = control.finder;
TryAnotherResult taresult = tryAnother(stack, input, mymatch, numRepeats, finder, visited);
visited = taresult.visited;
switch (taresult.status) {
case TryAnotherResult.TRY_FURTHER:
controlStack.push(new FindMatchControl(
finder));
continue MAIN_LOOP0;
case TryAnotherResult.RESULT_FOUND:
return taresult.result;
}
continue MAIN_LOOP0;
} // MAIN_LOOP0
}
private static class TryAnotherResult {
REMatch result;
int status;
static final int RESULT_FOUND = 1;
static final int TRY_FURTHER = 2;
static final int NOTHING_FOUND = 3;
int[] visited;
}
private TryAnotherResult tryAnother(BacktrackStack stack,
CharIndexed input, REMatch mymatch, int numRepeats,
DoablesFinder finder, int[] visited) {
TryAnotherResult taresult = new TryAnotherResult();
taresult.visited = visited;
DO_THIS:
do {
{
boolean emptyMatchFound = false;
@@ -263,61 +382,45 @@ final class RETokenRepeated extends REToken {
if (!emptyMatchFound) {
int n = doable.index;
if (! visitedContains(n, visited)) {
visited = addVisited(n, visited);
}
else {
if (visitedContains(n, visited)) {
continue DO_ONE_DOABLE;
}
visited = addVisited(n, visited);
stack.push(new StackedInfo(
input, numRepeats + 1, doable, visited, null));
REMatch m1 = findMatch(stack);
if (possessive) {
return m1;
}
if (m1 != null) {
m1.backtrackStack.push(new BacktrackStack.Backtrack(
this, input, mymatch, stack));
return m1;
}
input, numRepeats + 1, doable, visited, null));
taresult.visited = visited;
taresult.status = TryAnotherResult.TRY_FURTHER;
return taresult;
}
else {
REMatch m1 = matchRest(input, doable);
if (possessive) {
return m1;
taresult.result = m1;
taresult.status = TryAnotherResult.RESULT_FOUND;
return taresult;
}
if (m1 != null) {
if (! stack.empty()) {
m1.backtrackStack.push(new BacktrackStack.Backtrack(
this, input, mymatch, stack));
}
return m1;
}
taresult.result = m1;
taresult.status = TryAnotherResult.RESULT_FOUND;
return taresult;
}
}
} // DO_ONE_DOABLE
} while (false); // DO_THIS only once;
} // DO_THIS
if (!stack.empty()) {
stack.pop();
}
if (possessive) {
stack.clear();
}
REMatch m1 = matchRest(input, mymatch);
if (m1 != null) {
if (! stack.empty()) {
m1.backtrackStack.push(new BacktrackStack.Backtrack(
this, input, mymatch, stack));
}
return m1;
}
taresult.status = TryAnotherResult.NOTHING_FOUND;
return taresult;
} // MAIN_LOOP
}
boolean match(CharIndexed input, REMatch mymatch) {
setHitEnd(input, mymatch);
REMatch m1 = findMatch(input, mymatch);
if (m1 != null) {
mymatch.assignFrom(m1);