001: /*=============================================================================
002: * Copyright Texas Instruments 2003-2004. All Rights Reserved.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $
019: */
020:
021: package oscript.data;
022:
023: import oscript.exceptions.*;
024: import oscript.*;
025:
026: /**
027: * A regular expression object.
028: *
029: * @author Rob Clark (rob@ti.com)
030: */
031: public abstract class RegExp extends OObject {
032: /**
033: * The type object for an instance of RegExp... implementing class should
034: * use these values in the class used to construct the {@link BuiltinType}:
035: * <pre>
036: * public final static Value TYPE = BuiltinType.makeBuiltinType("oscript.data.???RegExp");
037: * public final static String PARENT_TYPE_NAME = RegExp.PARENT_TYPE_NAME;
038: * public final static String TYPE_NAME = RegExp.TYPE_NAME;
039: * public final static String[] MEMBER_NAMES = RegExp.MEMBER_NAMES;
040: * </pre>
041: */
042: public final static String PARENT_TYPE_NAME = "oscript.data.OObject";
043: public final static String TYPE_NAME = "RegExp";
044: public final static String[] MEMBER_NAMES = new String[] {
045: "getType", "castToJavaObject", "castToString",
046: "bopInstanceOf", "bopEquals", "bopNotEquals", "getMember",
047: "exec", "test" };
048:
049: /**
050: * The factory for RegExp objects, provided by the implementation of
051: * RegExp
052: */
053: private static RegExpFactory factory;
054:
055: /**
056: * The string representation of the expression
057: */
058: private Value exp;
059:
060: /**
061: * The string representation of the flags, or empty string if no flags
062: */
063: private Value flags;
064:
065: /*=======================================================================*/
066: /**
067: * Class Constructor.
068: */
069: protected RegExp(Value exp, Value flags) {
070: super ();
071:
072: this .exp = exp;
073: this .flags = flags;
074: }
075:
076: /*=======================================================================*/
077: /**
078: * Used by implementations of RegExp to register themselves as being
079: * able to implement RegExp. This will also create a global variable
080: * <code>RegExp</code> which is set to the value returned by factory's
081: * {@link RegExpFactory#getType} method.
082: *
083: * @param factory the factory that can construct a regular
084: * expression object
085: */
086: public static void register(RegExpFactory factory) {
087: RegExp.factory = factory;
088: oscript.OscriptInterpreter.getGlobalScope().createMember(
089: "RegExp", 0).opAssign(factory.getType());
090: }
091:
092: /*=======================================================================*/
093: /**
094: * Create a regular expression.
095: *
096: * @param str the string representation of the regular expression
097: */
098: public static RegExp createRegExp(Value ostr) {
099: String str = ostr.castToString();
100:
101: int idx = str.lastIndexOf('/');
102: String exp = str.substring(1, idx);
103: String flags = (idx < (str.length() - 1)) ? str
104: .substring(idx + 1) : "";
105:
106: // strip out escape chars for escaped spaces:
107: while ((idx = exp.indexOf("\\ ")) != -1)
108: exp = exp.substring(0, idx) + exp.substring(idx + 1);
109:
110: if (factory == null)
111: throw PackagedScriptObjectException
112: .makeExceptionWrapper(new ONoSuchMemberException(
113: UNDEFINED.castToString() + ": RegExp"));
114:
115: return factory.createRegExp(new OString(exp),
116: new OString(flags));
117: }
118:
119: /*=======================================================================*/
120: /**
121: * Interface to be implemented by regular-expression factory
122: */
123: protected interface RegExpFactory {
124: /**
125: * Get the type object, used to construct a RegExp object.
126: */
127: public Value getType();
128:
129: /**
130: * Construct a RegExp object.
131: *
132: * @param exp the expression string
133: * @param flags the string of zero or more flags
134: * @return the RegExp object
135: */
136: public RegExp createRegExp(Value exp, Value flags);
137: }
138:
139: /*=======================================================================*/
140: /**
141: * Get the type of this object. The returned type doesn't have to take
142: * into account the possibility of a script type extending a built-in
143: * type, since that is handled by {@link #getType}.
144: *
145: * @return the object's type
146: */
147: protected Value getTypeImpl() {
148: return factory.getType();
149: }
150:
151: /*=======================================================================*/
152: /**
153: * Execute the search for a match against a string.
154: * <p>
155: * Note that this API is modeled after the JavaScript RegExp API, for
156: * the benefit of users already familiar with JavaScript.
157: *
158: * @param str the string to match
159: * @return the result object
160: */
161: public abstract RegExpResult exec(Value str);
162:
163: /*=======================================================================*/
164: /**
165: * Executes the search for a match between a regular expression and a
166: * specified string.
167: *
168: * @param str the string to match
169: * @return <code>true</code> if match was found
170: */
171: public boolean test(Value str) {
172: return exec(str).getIndex().castToExactNumber() != -1;
173: }
174:
175: /*=======================================================================*/
176: /**
177: * Convert this object to a native java <code>String</code> value.
178: *
179: * @return a String value
180: * @throws PackagedObjectException(NoSuchMethodException)
181: */
182: public String castToString() throws PackagedScriptObjectException {
183: return "/" + exp + "/" + flags;
184: }
185: }
186:
187: /*
188: * Local Variables:
189: * tab-width: 2
190: * indent-tabs-mode: nil
191: * mode: java
192: * c-indentation-style: java
193: * c-basic-offset: 2
194: * eval: (c-set-offset 'substatement-open '0)
195: * eval: (c-set-offset 'case-label '+)
196: * eval: (c-set-offset 'inclass '+)
197: * eval: (c-set-offset 'inline-open '0)
198: * End:
199: */
|