diff options
author | Mark Wielaard <mark@gcc.gnu.org> | 2006-03-10 21:46:48 +0000 |
---|---|---|
committer | Mark Wielaard <mark@gcc.gnu.org> | 2006-03-10 21:46:48 +0000 |
commit | 8aa540d2f783474d1d2e06f16744bf67b9c1facc (patch) | |
tree | ea38c56431c5d4528fb54254c3f8e50f517bede3 /libjava/classpath/gnu/regexp/RETokenOneOf.java | |
parent | 27079765d00123f8e53d0e1ef7f9d46559266e6d (diff) | |
download | gcc-8aa540d2f783474d1d2e06f16744bf67b9c1facc.zip gcc-8aa540d2f783474d1d2e06f16744bf67b9c1facc.tar.gz gcc-8aa540d2f783474d1d2e06f16744bf67b9c1facc.tar.bz2 |
Imported GNU Classpath 0.90
Imported GNU Classpath 0.90
* scripts/makemake.tcl: Set gnu/java/awt/peer/swing to ignore.
* gnu/classpath/jdwp/VMFrame.java (SIZE): New constant.
* java/lang/VMCompiler.java: Use gnu.java.security.hash.MD5.
* java/lang/Math.java: New override file.
* java/lang/Character.java: Merged from Classpath.
(start, end): Now 'int's.
(canonicalName): New field.
(CANONICAL_NAME, NO_SPACES_NAME, CONSTANT_NAME): New constants.
(UnicodeBlock): Added argument.
(of): New overload.
(forName): New method.
Updated unicode blocks.
(sets): Updated.
* sources.am: Regenerated.
* Makefile.in: Likewise.
From-SVN: r111942
Diffstat (limited to 'libjava/classpath/gnu/regexp/RETokenOneOf.java')
-rw-r--r-- | libjava/classpath/gnu/regexp/RETokenOneOf.java | 181 |
1 files changed, 142 insertions, 39 deletions
diff --git a/libjava/classpath/gnu/regexp/RETokenOneOf.java b/libjava/classpath/gnu/regexp/RETokenOneOf.java index 3f6e89e..260bc4b 100644 --- a/libjava/classpath/gnu/regexp/RETokenOneOf.java +++ b/libjava/classpath/gnu/regexp/RETokenOneOf.java @@ -1,5 +1,5 @@ /* gnu/regexp/RETokenOneOf.java - Copyright (C) 1998-2001, 2004 Free Software Foundation, Inc. + Copyright (C) 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -37,11 +37,35 @@ exception statement from your version. */ package gnu.regexp; import java.util.Vector; +import java.util.Stack; final class RETokenOneOf extends REToken { private Vector options; private boolean negative; + private Vector addition; + // This Vector addition is used to store nested character classes. + // For example, if the original expression is + // [2-7a-c[f-k][m-z]&&[^p-v][st]] + // the basic part /2-7a-c/ is stored in the Vector options, and + // the additional part /[f-k][m-z]&&[^p-v][st]/ is stored in the + // Vector addition in the following order (Reverse Polish Notation): + // -- The matching result of the basic part is assumed here. + // [f-k] -- REToken + // "|" -- or + // [m-z] -- REToken + // "|" -- or + // false + // [^p-v] -- REToken + // "|" -- or + // [st] -- REToken + // "|" -- or + // "&" -- and + // + // As it is clear from the explanation above, the Vector addition is + // effective only when this REToken originates from a character class + // expression. + // This constructor is used for convenience when we know the set beforehand, // e.g. \d --> new RETokenOneOf("0123456789",false, ..) // \D --> new RETokenOneOf("0123456789",true, ..) @@ -60,7 +84,17 @@ final class RETokenOneOf extends REToken { this.negative = negative; } + RETokenOneOf(int subIndex, Vector options, Vector addition, boolean negative) { + super(subIndex); + this.options = options; + this.addition = addition; + this.negative = negative; + } + int getMinimumLength() { + // (negative || addition != null) occurs when this token originates from + // character class expression. + if (negative || addition != null) return 1; int min = Integer.MAX_VALUE; int x; for (int i=0; i < options.size(); i++) { @@ -70,54 +104,123 @@ final class RETokenOneOf extends REToken { return min; } + int getMaximumLength() { + // (negative || addition != null) occurs when this token originates from + // character class expression. + if (negative || addition != null) return 1; + int max = 0; + int x; + for (int i=0; i < options.size(); i++) { + if ((x = ((REToken) options.elementAt(i)).getMaximumLength()) > max) + max = x; + } + return max; + } + boolean match(CharIndexed input, REMatch mymatch) { - if (negative && (input.charAt(mymatch.index) == CharIndexed.OUT_OF_BOUNDS)) + REMatch tryMatch; + boolean tryOnly; + if (addition == null) { + tryMatch = mymatch; + tryOnly = false; + } + else { + tryMatch = (REMatch) mymatch.clone(); + tryOnly = true; + } + boolean b = negative ? + matchN(input, tryMatch, tryOnly) : + matchP(input, tryMatch, tryOnly); + if (addition == null) return b; + + Stack stack = new Stack(); + stack.push(new Boolean(b)); + for (int i=0; i < addition.size(); i++) { + Object obj = addition.elementAt(i); + if (obj instanceof REToken) { + b = ((REToken)obj).match(input, (REMatch)mymatch.clone()); + stack.push(new Boolean(b)); + } + else if (obj instanceof Boolean) { + stack.push(obj); + } + else if (obj.equals("|")) { + b = ((Boolean)stack.pop()).booleanValue(); + b = ((Boolean)stack.pop()).booleanValue() || b; + stack.push(new Boolean(b)); + } + else if (obj.equals("&")) { + b = ((Boolean)stack.pop()).booleanValue(); + b = ((Boolean)stack.pop()).booleanValue() && b; + stack.push(new Boolean(b)); + } + else { + throw new RuntimeException("Invalid object found"); + } + } + b = ((Boolean)stack.pop()).booleanValue(); + if (b) { + ++mymatch.index; + return next(input, mymatch); + } return false; + } - REMatch newMatch = null; - REMatch last = null; - REToken tk; - boolean isMatch; - for (int i=0; i < options.size(); i++) { + private boolean matchN(CharIndexed input, REMatch mymatch, boolean tryOnly) { + if (input.charAt(mymatch.index) == CharIndexed.OUT_OF_BOUNDS) + return false; + + REMatch newMatch = null; + REMatch last = null; + REToken tk; + for (int i=0; i < options.size(); i++) { tk = (REToken) options.elementAt(i); REMatch tryMatch = (REMatch) mymatch.clone(); if (tk.match(input, tryMatch)) { // match was successful - if (negative) return false; - - if (next(input, tryMatch)) { - // Add tryMatch to list of possibilities. - if (last == null) { - newMatch = tryMatch; - last = tryMatch; - } else { - last.next = tryMatch; - last = tryMatch; - } - } // next succeeds - } // is a match - } // try next option - - if (newMatch != null) { - if (negative) { return false; - } else { - // set contents of mymatch equal to newMatch + } // is a match + } // try next option - // try each one that matched - mymatch.assignFrom(newMatch); - return true; - } - } else { - if (negative) { - ++mymatch.index; - return next(input, mymatch); - } else { - return false; - } + if (tryOnly) return true; + ++mymatch.index; + return next(input, mymatch); } - // index+1 works for [^abc] lists, not for generic lookahead (--> index) - } + private boolean matchP(CharIndexed input, REMatch mymatch, boolean tryOnly) { + boolean stopMatchingIfSatisfied = + (mymatch.matchFlags & REMatch.MF_FIND_ALL) == 0; + REMatch.REMatchList newMatch = new REMatch.REMatchList(); + REToken tk; + for (int i=0; i < options.size(); i++) { + // In order that the backtracking can work, + // each option must be chained to the next token. + // But the chain method has some side effect, so + // we use clones. + tk = (REToken)((REToken) options.elementAt(i)).clone(); + if (! tryOnly) { + tk.chain(this.next); + tk.setUncle(this.uncle); + tk.subIndex = this.subIndex; + } + REMatch tryMatch = (REMatch) mymatch.clone(); + if (tk.match(input, tryMatch)) { // match was successful + if (tryOnly) return true; + newMatch.addTail(tryMatch); + if (stopMatchingIfSatisfied) break; + } // is a match + } // try next option + if (tryOnly) return false; + + if (newMatch.head != null) { + // set contents of mymatch equal to newMatch + + // try each one that matched + mymatch.assignFrom(newMatch.head); + return true; + } else { + return false; + } + } void dump(StringBuffer os) { os.append(negative ? "[^" : "(?:"); |