//--------------------------------------------------------------------------- // RegExp object for Flash5 ActionScript Ver1.01 // Author: Pavils Jurjans // Email : pavils@mailbox.riga.lv // Default source for this file can be found at: // http://www.jurjans.lv/flash/RegExp.html // and an interactive tester at http://www.jurjans.lv/flash/RegExp_test.html //--------------------------------------------------------------------------- // This class is provided for flash community for free with a kind request // to keep the copyright lines in AS file untouched. However, debugging and // development of class takes much time limiting my opportunities to earn // some income on other projects. To overcome this, I have set up an account // with PayPal (http://www.paypal.com). Please, if you find my work valuable, // especially if you use it in commercial projects, make a donation // to pavils@mailbox.riga.lv of amount you feel is right. Please provide your // E-mail address upon payment submission so I can enlist you in my upgrade newslist. //--------------------------------------------------------------------------- /** Based on RegExp object for Flash5 ActionScript Ver1.01
*RegExp is defined in Javascript and Actionscript 3 but is missing in Actionscript 2 (see Actionscript 3 documentation).
*Test Regular Expressions at http://www.jurjans.lv/flash/RegExp_test.html.
*Read a nice summary of their use at http://www.websina.com/bugzero/kb/regexp.html
* Help Document Last Updated: Jan 11, 2010 *@author Pavils Jurjans and Joey Lott with additions by the CLIPS team @email gpclarke@smcdsb.on.ca @url http://www.jurjans.lv/flash/RegExp.html */ class edu.clips.util.RegExp { public var const:String = null; public var source:String = null; public var global:Boolean = false; public var ignoreCase:Boolean = false; public var multiline:Boolean = false; public var lastIndex:Number = null; public static var _xrStatic:Number = null; public var _xr:Number = null; public static var _xp:Number = null; public static var _xxa:Array = null; public static var _xxlp:Number = null; public var _xq:Number = null; public var _xqc:Number = null; public static var d:Number = null; public static var _xiStatic:Number = null; public var _xi:Number = 0; public static var _xxlm:String = null; public static var _xxlc:String = null; public static var _xxrc:String = null; public static var lastMatch:String = null; public static var leftContext:String = null; public static var rightContext:String = null; public static var _xa:Array = new Array(); public static var lastParen:String = null; public static var _xaStatic:Array = new Array(); public static var $1:String = null; public static var $2:String = null; public static var $3:String = null; public static var $4:String = null; public static var $5:String = null; public static var $6:String = null; public static var $7:String = null; public static var $8:String = null; public static var $9:String = null; //this device sets up the String prototype functions immediately private static var _setString:Boolean = RegExp.setStringMethods(); /** * Instantiates a Regular Expression * @usage import edu.clips.util.RegExp;
var thing = new RegExp(string, flags, mystery);
* @param string String defining the pattern * @param flags some subset of "gim" where g indicates a global search, i a case-insensitive one and m a multi-line one * @param mystery - I think this is used only internally by the class * @example import edu.clips.util.RegExp;
var re = new RegExp("\\s+CLIPS","g"); */ function RegExp() { if (arguments[0] == null) { } else { const = "RegExp"; compile.apply(this, arguments); } } /**Used to determine which version of the class is actually stored and used *@returns (String) Details of the current version. */ public function getVersionInfo():String { return "RegExp Version January 26, 2010"; } public function invStr(sVal:String):String { var s = sVal; var l = length(s); var j; var c; var r = ""; for (var i = 1; i<255; i++) { c = chr(i); j = 0; while (j<=l && substring(s, 1+j++, 1) != c) { } if (j>l) { r += c; } } return s; } public function compile() { this.source = arguments[0]; if (arguments.length>1) { var flags = (arguments[1]+'').toLowerCase(); for (var i = 0; i type of match required: 0 = exact 1 = in char set 2 = not in char set 3 = paren 4 = ref to paren 7 = new "OR" section 9 = beginning of line 10 = end of line q[n].s --> character or character set q[n].a --> character has to repeat at least a times q[n].b --> character has to repeat at most b times */ var re = this.source; var ex; var l = length(re); var q = []; var qc = 0; var s; var range = false; var ca; var cb; var atEnd = false; var char; for (i=i; i=(s=chr(ca++))) { thischar += s; } range = false; } else { if (s == "-" && length(thischar)>0) { //Character range is being defined range = true; } else { if (s == "\\") { //Predefined char set may follow s = substring(re, 1+i++, 1); if (s == "d") { thischar += "0123456789"; } else if (s == "D") { thischar += invStr("0123456789"); } else if (s == "s") { thischar += " \f\n\r\t\v"; } else if (s == "S") { thischar += invStr(" \f\n\r\t\v"); } else if (s == "w") { thischar += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; } else if (s == "W") { thischar += invStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"); } else if (s == "b") { thischar += chr(8); } else if (s == "\\") { thischar += s; } } else { thischar += s; } } } } if (range) thischar += "-"; i--; var nextchar = substring(re, i+2, 1); } else if (thischar == "|") { //OR section if (atEnd) { q[qc].t = 10; q[qc].a = 1; q[qc].b = 1; qc++; q[qc] = new Object(); atEnd = false; } q[qc].t = 7; q[qc].a = 1; q[qc].b = 1; qc++; continue; } else if (thischar == ".") { q[qc].t = 2; thischar = "\n"; } else if (thischar == "*" || thischar == "?" || thischar == "+") { continue; } } else { if (thischar>="1" && thischar<="9") { q[qc].t = 4; } else if (thischar == "b") { q[qc].t = 1; thischar = "--wb--"; } else if (thischar == "B") { q[qc].t = 2; thischar = "--wb--"; } else if (thischar == "d") { q[qc].t = 1; thischar = "0123456789"; } else if (thischar == "D") { q[qc].t = 2; thischar = "0123456789"; } else if (thischar == "s") { q[qc].t = 1; thischar = " \f\n\r\t\v"; } else if (thischar == "S") { q[qc].t = 2; thischar = " \f\n\r\t\v"; } else if (thischar == "w") { q[qc].t = 1; thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; } else if (thischar == "W") { q[qc].t = 2; thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; } } //Counting metacharacters if (nextchar == "*") { q[qc].s = thischar; qc++; i++; } else if (nextchar == "?") { q[qc].s = thischar; q[qc].b = 1; qc++; i++; } else if (nextchar == "+") { q[qc].s = thischar; q[qc].a = 1; qc++; i++; } else if (nextchar == "{") { var comma = false; var rangeA = 0; range = ""; i++; while (i+1(String) The string to be searched *@returns Boolean indicating whether the pattern was found *@example nameof = "StandardStart27_mc"
var re = new RegExp("Start","g");
trace("Does the string include 'Start'? "+re.test(nameof)); //outputs true*/ public function test() { if (RegExp._xp++ == 0) { RegExp._xxa = []; //Temp array for storing paren matches RegExp._xxlp = 0; //Last paren } // q[n].c --> count of matches // q[n].i --> index within the string var str = arguments[0]+''; var re; var q = this._xq; var qc = this._xqc; var qb; var c; var cl; var ct; var s; var l = length(str); var ix = this.global ? this.lastIndex : 0; var ix_ = ix; var str_ = str; if (this.ignoreCase) { str = str.toLowerCase(); } var r = new Object(); r.i = -1; var i = -1; while (i=0 && ix>=r.i) { //There is already better match, so quit searching break; } if (q[i].c == -10) { if (RegExp.d) { trace("Lookup #"+i+" at index "+ix+" for \\\\\\\\\\\\\\\\'"+q[i].s+"\\\\\\\\\\\\\\\\' type "+q[i].t); } //Count the # of matches var m = 0; q[i].i = ix; if (q[i].t == 0) { //Exact match c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s; while (m0 && ix0 && ix0) { ix += cl; m++; q[i].ix[m] = ix; } else { m = q[i].a; q[i].ix[m-1] = ix; break; } } if (m == 0) { RegExp._xxlm = ""; } if (re._xr>RegExp._xxlp) { RegExp._xxlp = re._xr; } RegExp._xxa[Number(re._xr)] = RegExp._xxlm; } else if (q[i].t == 4) { //Back reference to paren if (RegExp._xp>=(c=Number(q[i].s))) { c = RegExp._xxa[c]; c = this.ignoreCase ? c.toLowerCase() : c; cl = length(c); q[i].ix = []; q[i].ix[m] = ix; if (cl>0) { while (mqb) { //Retreat back and decrease # of assumed matches i--; q[i].c--; if (q[i].c>=0) { ix = (q[i].t == 3 || q[i].t == 4) ? q[i].ix[q[i].c] : (q[i].i+q[i].c); } if (RegExp.d) { trace("Retreat to #"+i+" c="+q[i].c+" index="+ix); } } else { if (RegExp._xp>1) { //If this is a paren, failing to find first match is fatal break; } if (atStart) { //Match must be at the start of string/line if (this.multiline) { //Jump to the beginning of the next line while (ix<=l) { s = substring(str, 1+ix++, 1); if (s == "\\\\\\\\\\\\\\\\n" || s == "\\\\\\\\\\\\\\\\r") { break; } } q[i].c = -10; } else { //No match break; } } else { //Start a new search from next position ix++; q[i].c = -10; } } } else { if (RegExp.d) { trace(" enough matches!"); } //# of matches ok, proceed to next i++; if (i == qc || q[i].t == 7) { if (RegExp.d) { trace("Saving better result: r.i = q["+qb+"].i = "+q[qb].i); } r.i = q[qb].i; r.li = ix; break; } else { q[i].c = -10; } } } } while (i(String) The string to be pattern-matched *@returns Object with properties index (the position), input (the string) and 0 (the matched character(s))
*Note: previous operations with the RegExp object may affect the last Index being considered and hence the results. Multiple calls to exec are necessary to get all the matches. *@example p2 = new RegExp("\\d+","g");
next_string = "I have 23 ways to list 5 objects on 217 pieces of paper";
var results1:Object = p2.exec(next_string);
while (results1 != null)
{
for (var prop in results1){
trace(" * "+prop+" : "+results1[prop]);
}
results1 = p2.exec(next_string);
}
*/ public function exec() { var str = arguments[0]+''; if (str == '') { return false; } var t = this.test(str); if (t) { var ra = new Array(); ra.index = this._xi; ra.input = str; ra[0] = RegExp.lastMatch; var l = RegExp._xaStatic.length; for (var i = 1; i Use the "g" flag to repeat the process over and over.
Added to String.prototype so that it can be used with any string. Changed on January 26, 2010 to return a string - not sure how that will affect multiple calls with the "g" flag *@usage string.match(re) *@param string (String) The string to be pattern-matched *@returns Array with every matched set of characters *@example nameof = "StandardStart27_mc";
p2 = new RegExp("\\d+","g");
trace("The digits are " + nameof.match(p2)[0]); //output 27
*/ //public function match(re:RegExp):Array{ String.prototype.match = function() { if (typeof (arguments[0]) != "object") { return null; } if (arguments[0].const != "RegExp") { trace("Warning - match not sent a RegExp"); return null; } var re = arguments[0]; var s = this.valueOf(); var ip = 0; var rc = 0; if (re.global) { re.lastIndex = 0; while (re.test(s)) { if (rc == 0) { var ra = new Array(); } ra[rc++] = RegExp.lastMatch; ip = re.lastIndex; } re.lastIndex = ip; } else { var ra = re.exec(s); rc++; } return (rc == 0) ? null : ra; }; /**Replace the characters that match the pattern defined by the regular expression with another string.
*or Replace the given substring with another one (Based on a idea of Davide Beltrame (Broly)) *found on http://www.sephiroth.it/proto_detail.php?id=16
Added to String.prototype so that it can be used with any string. *@usage string.replace(re, new_string); *@usage string.replace(found_string, new_string); *@param re (RegExp) The Regular Expression with the pattern to be matched *@param found_string (String) The string to be matched *@param new_string (String) The string to use in the replacement *@returns String with replacement(s) made. *@example test_txt = " swf Missippi River ";
p1 = new RegExp("\\s+","g");
trace(test_txt.replace(p1,"*")); //output '*swf*Missippi*River*'

*@example test = ".swflib/actions/test.swf is a .swf";
* trace(test+", "+test.replace('.swf', '')); //.swflib/actions/test.swf is a .swf, lib/actions/test is a
*/ //public function replace(re:RegExp, new_string:String):String{ String.prototype.replace = function() { if (typeof (arguments[0]) != "object") { trace("Warning - replace not sent an Object"); //return null; } if (arguments[0].const != "RegExp") { //definition when the first argument is a String var arg_search, arg_replace, position; var endText, preText, newText; arg_search = arguments[0]; arg_replace = arguments[1]; if (arg_search.length == 1) { return this.split(arg_search).join(arg_replace); } position = this.indexOf(arg_search); if (position == -1) { return this; } endText = this; newText = ""; do { position = endText.indexOf(arg_search); preText = endText.substring(0, position); endText = endText.substring(position+arg_search.length); newText += preText+arg_replace; } while (endText.indexOf(arg_search) != -1); newText += endText; trace("replace returning a result based on a string object"); return newText; } var re = arguments[0]; var rs = arguments[1]+''; var s = this; var r = ""; re.lastIndex = 0; if (re.global) { var ip = 0; var ix = 0; while (re.test(s)) { //Replace backreferences in rs var i = 0; var l = length(rs); var c = ""; var pc = ""; var nrs = ""; while (i9) { nrs += "$"+c; } else { nrs += RegExp._xaStatic[Number(c)]; } } else { nrs += c; } pc = c; } r += substring(s, ix+1, re._xi-ix)+nrs; ix = re._xi+length(RegExp.lastMatch); ip = re.lastIndex; } re.lastIndex = ip; } else { if (re.test(s)) { r += RegExp.leftContext+rs; } } r += re.lastIndex == 0 ? s : RegExp.rightContext; return r; }; /**Trim whitespace from the beginning of a string.
*Added to the class, informed by http://www.somacon.com/p355.php
*Added to String.prototype so that it can be used with any string. *@usage string.ltrim(); *@returns trimmed String *@example test_txt = "  swf   Missippi River    ";
trace(test_txt.ltrim()); //output 'swf   Missippi River    '

*/ //public function ltrim():String{ String.prototype.ltrim = function() { var re = new RegExp("^\\s+"); return this.replace(re,""); } /**Trim whitespace from the end of a string.
*Added to the class, informed by http://www.somacon.com/p355.php
*Added to String.prototype so that it can be used with any string. *@usage string.rtrim(); *@returns trimmed String *@example test_txt = "  swf   Missippi River    ";
trace(test_txt.rtrim()); //output '  swf   Missippi River'

*/ //public function rtrim():String{ String.prototype.rtrim = function() { var re = new RegExp("\\s+$") return this.replace(re,""); } /**Trim whitespace from the beginning and end of a string.
*Added to the class by the CLIPS team
*Added to String.prototype so that it can be used with any string. *@usage string.trim(); *@returns trimmed String *@example test_txt = "  swf   Missippi River    ";
trace(test_txt.trim()); //output 'swf   Missippi River'

*/ //public function trim():String{ String.prototype.trim = function() { //This device is used since the RegExp for whitespace at both ends didn't seem to work. return this.rtrim().ltrim(); } /**Tests for a match in a string.
*Added to String.prototype so that it can be used with any string. *@usage string.search(re); *@returns the index of the match, or -1 if the search fails. *@example test_txt = "Therrrre Grrrrrrrrrreat";
re = new RegExp("r+e","g"); trace(test_txt.search(re)); //output 3

*@see test */ //public function search(re:RegExp):String{ String.prototype.search = function() { if (typeof (arguments[0]) != "object") { return null; } if (arguments[0].const != "RegExp") { trace("Warning - search not sent a RegExp"); return null; } var re = arguments[0]; var s = this; re.lastIndex = 0; var t = re.test(s); return t ? re._xi : -1; }; String.prototype.old_split = String.prototype.split; /**Adds the ability to split a string based on a RegExp.
*Added to String.prototype so that it can be used with any string. *@usage string.split(re); *@usage string.split(string_delimiter, limit); *@param re the RegExp *@param string_delimiter the simple string to delimit by *@param limit the number of items to place in the array *@returns an Array of substrings *@example test_txt = "Therrrre Grrrrrrrrrreat";
re = new RegExp("r+e","g");
trace(test_txt.split(re)); //output [The, G,at]
trace(test_txt.split("r"); //output [The,,,,e G,,,,,,,,,,eat]

*/ //public function split(re:RegExp):String{ String.prototype.split = function() { if (typeof (arguments[0]) == "object" && arguments[0].const == "RegExp") { var re = arguments[0]; var lm = arguments[1] == null ? 9999 : Number(arguments[1]); if (isNaN(lm)) { lm = 9999; } var s = this; var ra = new Array(); var rc = 0; var gs = re.global; re.global = true; re.lastIndex = 0; var ip = 0; var ipp = 0; var ix = 0; while (rc0) { ra[rc++] = RegExp.rightContext; } } re.global = gs; return ra; } else { return this.old_split(arguments[0], arguments[1]); } }; return true; } }