PageRenderTime 119ms CodeModel.GetById 16ms app.highlight 90ms RepoModel.GetById 1ms app.codeStats 0ms

/flash/Shared/RegExp.as

https://bitbucket.org/theit8514/expfavmenu
ActionScript | 1262 lines | 1150 code | 4 blank | 108 comment | 68 complexity | 0831b78cd17969b11b346d1044bc053b MD5 | raw file
   1//---------------------------------------------------------------------------
   2// RegExp object for Flash5 ActionScript Ver1.01
   3//Author: Pavils Jurjans
   4//Email : pavils@mailbox.riga.lv
   5//      Default source for this file can be found at:
   6//              http://www.jurjans.lv/flash/RegExp.html
   7//and an interactive tester at http://www.jurjans.lv/flash/RegExp_test.html
   8//---------------------------------------------------------------------------
   9// This class is provided for flash community for free with a kind request 
  10// to keep the copyright lines in AS file untouched. However, debugging and 
  11// development of class takes much time limiting my opportunities to earn 
  12// some income on other projects. To overcome this, I have set up an account 
  13// with PayPal (http://www.paypal.com). Please, if you find my work valuable,
  14// especially if you use it in commercial projects, make a donation 
  15// to pavils@mailbox.riga.lv of amount you feel is right. Please provide your
  16// E-mail address upon payment submission so I can enlist you in my upgrade newslist.
  17//---------------------------------------------------------------------------
  18
  19/** Based on RegExp object for Flash5 ActionScript Ver1.01<br/>
  20*RegExp is defined in Javascript and Actionscript 3 but is missing in Actionscript 2 (see Actionscript 3 documentation).<br>
  21*Test Regular Expressions at <a href='http://www.jurjans.lv/flash/RegExp_test.html'>http://www.jurjans.lv/flash/RegExp_test.html</a>.<br>
  22*Read a nice summary of their use at <a href='http://www.websina.com/bugzero/kb/regexp.html'>http://www.websina.com/bugzero/kb/regexp.html</a><br>
  23* Help Document Last Updated:  Jan 11, 2010
  24*@author Pavils Jurjans and Joey Lott with additions by the CLIPS team 
  25@email gpclarke@smcdsb.on.ca 
  26@url http://www.jurjans.lv/flash/RegExp.html
  27
  28*/
  29class Shared.RegExp
  30{
  31	public var const:String = null;
  32	public var source:String = null;
  33	public var global:Boolean = false;
  34	public var ignoreCase:Boolean = false;
  35	public var multiline:Boolean = false;
  36	public var lastIndex:Number = null;
  37	public static var _xrStatic:Number = null;
  38	public var _xr:Number = null;
  39	public static var _xp:Number = null;
  40	public static var _xxa:Array = null;
  41	public static var _xxlp:Number = null;
  42	public var _xq:Number = null;
  43	public var _xqc:Number = null;
  44	public static var d:Number = null;
  45	public static var _xiStatic:Number = null;
  46	public var _xi:Number = 0;
  47	public static var _xxlm:String = null;
  48	public static var _xxlc:String = null;
  49	public static var _xxrc:String = null;
  50	public static var lastMatch:String = null;
  51	public static var leftContext:String = null;
  52	public static var rightContext:String = null;
  53	public static var _xa:Array = new Array();
  54	public static var lastParen:String = null;
  55	public static var _xaStatic:Array = new Array();
  56	public static var $1:String = null;
  57	public static var $2:String = null;
  58	public static var $3:String = null;
  59	public static var $4:String = null;
  60	public static var $5:String = null;
  61	public static var $6:String = null;
  62	public static var $7:String = null;
  63	public static var $8:String = null;
  64	public static var $9:String = null;
  65	//this device sets up the String prototype functions immediately
  66	private static var _setString:Boolean = RegExp.setStringMethods();
  67	/**
  68	 * Instantiates a Regular Expression
  69	 * @usage import edu.clips.util.RegExp;<BR>var thing = new RegExp(string, flags, mystery); <BR>
  70	 * @param string String defining the pattern 
  71	 * @param flags some subset of "gim" where g indicates a global search, i a case-insensitive one and m a multi-line one
  72	 * @param mystery - I think this is used only internally by the class
  73	 * @example import edu.clips.util.RegExp;<BR>var re = new RegExp("\\s+CLIPS","g");
  74	 */
  75
  76	function RegExp()
  77	{
  78		if (arguments[0] == null)
  79		{
  80		}
  81		else
  82		{
  83			const = "RegExp";
  84			compile.apply(this,arguments);
  85		}
  86	}
  87	/**Used to determine which version of the class is actually stored and used
  88	*@returns <code>(String)</code> Details of the current version. */
  89	public function getVersionInfo():String
  90	{
  91		return "RegExp Version January 26, 2010";
  92	}
  93	public function invStr(sVal:String):String
  94	{
  95		var s = sVal;
  96		var l = length(s);
  97		var j;
  98		var c;
  99		var r = "";
 100		for (var i = 1; i < 255; i++)
 101		{
 102			c = chr(i);
 103			j = 0;
 104			while (j <= l && substring(s, 1 + j++, 1) != c)
 105			{
 106			}
 107			if (j > l)
 108			{
 109				r += c;
 110			}
 111		}
 112		return s;
 113	}
 114	public function compile()
 115	{
 116		this.source = arguments[0];
 117		if (arguments.length > 1)
 118		{
 119			var flags = (arguments[1] + '').toLowerCase();
 120			for (var i = 0; i < length(flags); i++)
 121			{
 122				if (substring(flags, i + 1, 1) == "g")
 123				{
 124					this.global = true;
 125				}
 126				if (substring(flags, i + 1, 1) == "i")
 127				{
 128					this.ignoreCase = true;
 129				}
 130				if (substring(flags, i + 1, 1) == "m")
 131				{
 132					this.multiline = true;
 133				}
 134			}
 135		}
 136		if (arguments.length < 3)
 137		{
 138			var root = true;
 139			RegExp._xrStatic = 1;
 140			//Paren counter
 141			var i = 0;
 142		}
 143		else
 144		{
 145			var root = false;
 146			this._xr = RegExp._xrStatic++;
 147			var i = arguments[2];
 148		}
 149		this.lastIndex = 0;
 150		/*
 151		Compile the regular expression
 152		The array of character definition objects will be created:
 153		  q[n].t    -->  type of match required: 0  = exact
 154		                                         1  = in char set
 155		 2  = not in char set
 156		 3  = paren
 157		 4  = ref to paren
 158		 7  = new "OR" section
 159		 9  = beginning of line
 160		 10 = end of line
 161		  q[n].s    -->  character or character set
 162		  q[n].a    -->  character has to repeat at least a times
 163		  q[n].b    -->  character has to repeat at most b times
 164		*/
 165		var re = this.source;
 166		var ex;
 167		var l = length(re);
 168		var q = [];
 169		var qc = 0;
 170		var s;
 171		var range = false;
 172		var ca;
 173		var cb;
 174		var atEnd = false;
 175		var char;
 176		for (i = i; i < l; ++i)
 177		{
 178			var thischar = substring(re, i + 1, 1);
 179			if (thischar == "\\")
 180			{
 181				i++;
 182				char = false;
 183				thischar = substring(re, i + 1, 1);
 184			}
 185			else
 186			{
 187				char = true;
 188			}
 189			var nextchar = substring(re, i + 2, 1);
 190			q[qc] = new Object();
 191			q[qc].t = 0;
 192			q[qc].a = 0;
 193			q[qc].b = 999;
 194			q[qc].c = -10;
 195			if (char)
 196			{
 197				// Handle special characters
 198				if (thischar == "(")
 199				{
 200					//Opening paren
 201					ex = new RegExp(re, (this.ignoreCase ? "gi" : "g"), i + 1);
 202					i = RegExp._xiStatic;
 203					q[qc].t = 3;
 204					thischar = ex;
 205					nextchar = substring(re, i + 2, 1);
 206				}
 207				else if (!root && thischar == ")")
 208				{
 209					//Closing paren
 210					break;
 211				}
 212				else if (thischar == "^")
 213				{
 214					//Must be located at the beginning of string/line
 215					if (qc == 0 || q[qc - 1].t == 7)
 216					{
 217						q[qc].t = 9;
 218						q[qc].a = 1;
 219						q[qc].b = 1;
 220						qc++;
 221					}
 222					continue;
 223				}
 224				else if (thischar == "$")
 225				{
 226					//Must be located at the end of string/line
 227					if (root)
 228					{
 229						atEnd = true;
 230					}
 231					continue;
 232				}
 233				else if (thischar == "[")
 234				{
 235					//This is a character set
 236					i++;
 237					if (nextchar == "^")
 238					{
 239						q[qc].t = 2;
 240						i++;
 241					}
 242					else
 243					{
 244						q[qc].t = 1;
 245					}
 246					thischar = "";
 247					range = false;
 248					while (i < l && (s = substring(re, 1 + i++, 1)) != "]")
 249					{
 250						if (range)
 251						{
 252							//Previous char was "-", so create a range
 253							if (s == "\\")
 254							{
 255							}
 256							cb = s == "\\" ? (s == "b" ? chr(8) : substring(re, 1 + i++, 1)) : s;
 257							ca = ord(substring(thischar, length(thischar), 1)) + 1;
 258							while (cb >= (s = chr(ca++)))
 259							{
 260								thischar += s;
 261							}
 262							range = false;
 263						}
 264						else
 265						{
 266							if (s == "-" && length(thischar) > 0)
 267							{
 268								//Character range is being defined
 269								range = true;
 270							}
 271							else
 272							{
 273								if (s == "\\")
 274								{
 275									//Predefined char set may follow
 276									s = substring(re, 1 + i++, 1);
 277									if (s == "d")
 278									{
 279										thischar += "0123456789";
 280									}
 281									else if (s == "D")
 282									{
 283										thischar += invStr("0123456789");
 284									}
 285									else if (s == "s")
 286									{
 287										thischar += " \f\n\r\t\v";
 288									}
 289									else if (s == "S")
 290									{
 291										thischar += invStr(" \f\n\r\t\v");
 292									}
 293									else if (s == "w")
 294									{
 295										thischar += "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
 296									}
 297									else if (s == "W")
 298									{
 299										thischar += invStr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
 300									}
 301									else if (s == "b")
 302									{
 303										thischar += chr(8);
 304									}
 305									else if (s == "\\")
 306									{
 307										thischar += s;
 308									}
 309								}
 310								else
 311								{
 312									thischar += s;
 313								}
 314							}
 315						}
 316					}
 317					if (range)
 318					{
 319						thischar += "-";
 320					}
 321					i--;
 322					var nextchar = substring(re, i + 2, 1);
 323				}
 324				else if (thischar == "|")
 325				{
 326					//OR section
 327					if (atEnd)
 328					{
 329						q[qc].t = 10;
 330						q[qc].a = 1;
 331						q[qc].b = 1;
 332						qc++;
 333						q[qc] = new Object();
 334						atEnd = false;
 335					}
 336					q[qc].t = 7;
 337					q[qc].a = 1;
 338					q[qc].b = 1;
 339					qc++;
 340					continue;
 341				}
 342				else if (thischar == ".")
 343				{
 344					q[qc].t = 2;
 345					thischar = "\n";
 346				}
 347				else if (thischar == "*" || thischar == "?" || thischar == "+")
 348				{
 349					continue;
 350				}
 351			}
 352			else
 353			{
 354				if (thischar >= "1" && thischar <= "9")
 355				{
 356					q[qc].t = 4;
 357				}
 358				else if (thischar == "b")
 359				{
 360					q[qc].t = 1;
 361					thischar = "--wb--";
 362				}
 363				else if (thischar == "B")
 364				{
 365					q[qc].t = 2;
 366					thischar = "--wb--";
 367				}
 368				else if (thischar == "d")
 369				{
 370					q[qc].t = 1;
 371					thischar = "0123456789";
 372				}
 373				else if (thischar == "D")
 374				{
 375					q[qc].t = 2;
 376					thischar = "0123456789";
 377				}
 378				else if (thischar == "s")
 379				{
 380					q[qc].t = 1;
 381					thischar = " \f\n\r\t\v";
 382				}
 383				else if (thischar == "S")
 384				{
 385					q[qc].t = 2;
 386					thischar = " \f\n\r\t\v";
 387				}
 388				else if (thischar == "w")
 389				{
 390					q[qc].t = 1;
 391					thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
 392				}
 393				else if (thischar == "W")
 394				{
 395					q[qc].t = 2;
 396					thischar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
 397				}
 398			}
 399			//Counting metacharacters
 400			if (nextchar == "*")
 401			{
 402				q[qc].s = thischar;
 403				qc++;
 404				i++;
 405			}
 406			else if (nextchar == "?")
 407			{
 408				q[qc].s = thischar;
 409				q[qc].b = 1;
 410				qc++;
 411				i++;
 412			}
 413			else if (nextchar == "+")
 414			{
 415				q[qc].s = thischar;
 416				q[qc].a = 1;
 417				qc++;
 418				i++;
 419			}
 420			else if (nextchar == "{")
 421			{
 422				var comma = false;
 423				var rangeA = 0;
 424				range = "";
 425				i++;
 426				while (i + 1 < l && (s = substring(re, 2 + i++, 1)) != "}")
 427				{
 428					if (!comma && s == ",")
 429					{
 430						comma = true;
 431						rangeA = Number(range);
 432						rangeA = Math.floor(isNaN(rangeA) ? 0 : rangeA);
 433						if (rangeA < 0)
 434						{
 435							rangeA = 0;
 436						}
 437						range = "";
 438					}
 439					else
 440					{
 441						range += s;
 442					}
 443				}
 444				var rangeB = Number(range);
 445				rangeB = Math.floor(isNaN(rangeB) ? 0 : rangeB);
 446				if (rangeB < 1)
 447				{
 448					rangeB = 999;
 449				}
 450				if (rangeB < rangeA)
 451				{
 452					rangeB = rangeA;
 453				}
 454				q[qc].s = thischar;
 455				q[qc].b = rangeB;
 456				q[qc].a = comma ? rangeA : rangeB;
 457				qc++;
 458			}
 459			else
 460			{
 461				q[qc].s = thischar;
 462				q[qc].a = 1;
 463				q[qc].b = 1;
 464				qc++;
 465			}
 466		}
 467		if (root && atEnd)
 468		{
 469			q[qc] = new Object();
 470			q[qc].t = 10;
 471			q[qc].a = 1;
 472			q[qc].b = 1;
 473			qc++;
 474		}
 475		if (!root)
 476		{
 477			RegExp._xiStatic = i;
 478			this.source = substring(re, arguments[2] + 1, i - arguments[2]);
 479		}
 480		if (RegExp.d)
 481		{
 482			for (var i = 0; i < qc; i++)
 483			{
 484				trace("xr" + this._xr + ' ' + q[i].t + " : " + q[i].a + " : " + q[i].b + " : " + q[i].s);
 485			}
 486		}
 487		this._xq = q;
 488		this._xqc = qc;
 489		RegExp._xp = 0;
 490	}
 491
 492	/**Used to test whether a string has a pattern defined by the Regular Expression 
 493	*@usage re.test(string) 
 494	*@param string   <code>(String)</code> The string to be searched
 495	*@returns Boolean indicating whether the pattern was found
 496	*@example nameof = "StandardStart27_mc"<BR>var re = new RegExp("Start","g");<BR>trace("Does the string include 'Start'? "+re.test(nameof)); //outputs true*/
 497	public function test()
 498	{
 499		if (RegExp._xp++ == 0)
 500		{
 501			RegExp._xxa = [];
 502			//Temp array for storing paren matches
 503			RegExp._xxlp = 0;
 504			//Last paren
 505		}
 506		//  q[n].c  -->  count of matches 
 507		//  q[n].i  -->  index within the string
 508		var str = arguments[0] + '';
 509		var re;
 510		var q = this._xq;
 511		var qc = this._xqc;
 512		var qb;
 513		var c;
 514		var cl;
 515		var ct;
 516		var s;
 517		var l = length(str);
 518		var ix = this.global ? this.lastIndex : 0;
 519		var ix_ = ix;
 520		var str_ = str;
 521		if (this.ignoreCase)
 522		{
 523			str = str.toLowerCase();
 524		}
 525		var r = new Object();
 526		r.i = -1;
 527		var i = -1;
 528		while (i < qc - 1)
 529		{
 530			i++;
 531			if (RegExp.d)
 532			{
 533				trace("New section started at i=" + i);
 534			}
 535			ix = ix_;
 536			qb = i;
 537			q[qb].c = -10;
 538			var atEnd = false;
 539			while (i > qb || ix < l + 1)
 540			{
 541				if (q[i].t == 7)
 542				{
 543					//New "OR" section coming
 544					break;
 545				}
 546				else if (q[i].t == 9)
 547				{
 548					i++;
 549					if (i == qb + 1)
 550					{
 551						var atStart = true;
 552						qb = i;
 553					}
 554					q[qb].c = -10;
 555					continue;
 556				}
 557				else
 558				{
 559					if (r.i >= 0 && ix >= r.i)
 560					{
 561						//There is already better match, so quit searching
 562						break;
 563					}
 564					if (q[i].c == -10)
 565					{
 566						if (RegExp.d)
 567						{
 568							trace("Lookup #" + i + " at index " + ix + " for \\\\\\\\\\\\\\\\'" + q[i].s + "\\\\\\\\\\\\\\\\' type " + q[i].t);
 569						}
 570						//Count the # of matches 
 571						var m = 0;
 572						q[i].i = ix;
 573						if (q[i].t == 0)
 574						{
 575							//Exact match
 576							c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
 577							while (m < q[i].b && ix < l)
 578							{
 579								if (substring(str, 1 + ix, 1) == c)
 580								{
 581									m++;
 582									ix++;
 583								}
 584								else
 585								{
 586									break;
 587								}
 588							}
 589						}
 590						else if (q[i].t == 1)
 591						{
 592							//In char set
 593							if (q[i].s == "--wb--")
 594							{
 595								q[i].a = 1;
 596								if (ix > 0 && ix < l)
 597								{
 598									ct = substring(str, ix, 1);
 599									if (ct == " " || ct == "\\\\\\\\\\\\\\\\n")
 600									{
 601										m = 1;
 602									}
 603									if (m == 0)
 604									{
 605										ct = substring(str, 1 + ix, 1);
 606										if (ct == " " || ct == "\\\\\\\\\\\\\\\\n")
 607										{
 608											m = 1;
 609										}
 610									}
 611								}
 612								else
 613								{
 614									m = 1;
 615								}
 616							}
 617							else
 618							{
 619								c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
 620								cl = length(c);
 621								var cs;
 622								while (m < q[i].b && ix < l)
 623								{
 624									ct = substring(str, 1 + ix, 1);
 625									cs = 0;
 626									while (cs <= cl && substring(c, 1 + cs++, 1) != ct)
 627									{
 628									}
 629									if (cs <= cl)
 630									{
 631										m++;
 632										ix++;
 633									}
 634									else
 635									{
 636										break;
 637									}
 638								}
 639							}
 640						}
 641						else if (q[i].t == 2)
 642						{
 643							//Not in char set
 644							c = this.ignoreCase ? q[i].s.toLowerCase() : q[i].s;
 645							cl = length(c);
 646							if (q[i].s == "--wb--")
 647							{
 648								q[i].a = 1;
 649								if (ix > 0 && ix < l)
 650								{
 651									ct = substring(str, ix, 1);
 652									s = substring(str, 1 + ix, 1);
 653									if (ct != " " && ct != "\\\\\\\\\\\\\\\\n" && s != " " && s != "\\\\\\\\\\\\\\\\n")
 654									{
 655										m = 1;
 656									}
 657								}
 658								else
 659								{
 660									m = 0;
 661								}
 662							}
 663							else
 664							{
 665								while (m < q[i].b && ix < l)
 666								{
 667									ct = substring(str, 1 + ix, 1);
 668									cs = 0;
 669									while (cs <= cl && substring(c, 1 + cs++, 1) != ct)
 670									{
 671									}
 672									if (cs <= cl)
 673									{
 674										break;
 675									}
 676									else
 677									{
 678										m++;
 679										ix++;
 680									}
 681								}
 682							}
 683						}
 684						else if (q[i].t == 10)
 685						{
 686							//End of string/line must be next
 687							s = substring(str, 1 + ix, 1);
 688							m = (this.multiline && (s == "\\\\\\\\\\\\\\\\n" || s == "\\\\\\\\\\\\\\\\r")) || ix == l ? 1 : 0;
 689						}
 690						else if (q[i].t == 3)
 691						{
 692							//Regular expression in parens
 693							re = q[i].s;
 694							q[i].ix = [];
 695							q[i].ix[m] = ix;
 696							//Save index if need to retreat
 697							re.lastIndex = ix;
 698							while (m < q[i].b && re.test(str_))
 699							{
 700								cl = length(RegExp._xxlm);
 701								if (cl > 0)
 702								{
 703									ix += cl;
 704									m++;
 705									q[i].ix[m] = ix;
 706								}
 707								else
 708								{
 709									m = q[i].a;
 710									q[i].ix[m - 1] = ix;
 711									break;
 712								}
 713							}
 714							if (m == 0)
 715							{
 716								RegExp._xxlm = "";
 717							}
 718							if (re._xr > RegExp._xxlp)
 719							{
 720								RegExp._xxlp = re._xr;
 721							}
 722							RegExp._xxa[Number(re._xr)] = RegExp._xxlm;
 723						}
 724						else if (q[i].t == 4)
 725						{
 726							//Back reference to paren
 727							if (RegExp._xp >= (c = Number(q[i].s)))
 728							{
 729								c = RegExp._xxa[c];
 730								c = this.ignoreCase ? c.toLowerCase() : c;
 731								cl = length(c);
 732								q[i].ix = [];
 733								q[i].ix[m] = ix;
 734								if (cl > 0)
 735								{
 736									while (m < q[i].b && ix < l)
 737									{
 738										if (substring(str, 1 + ix, cl) == c)
 739										{
 740											m++;
 741											ix += cl;
 742											q[i].ix[m] = ix;
 743										}
 744										else
 745										{
 746											break;
 747										}
 748									}
 749								}
 750								else
 751								{
 752									m = 0;
 753									q[i].a = 0;
 754								}
 755							}
 756							else
 757							{
 758								//Paren is not ready, treat number as charcode
 759								c = chr(c);
 760								q[i].ix = [];
 761								q[i].ix[m] = ix;
 762								while (m < q[i].b && ix < l)
 763								{
 764									if (substring(str, 1 + ix, 1) == c)
 765									{
 766										m++;
 767										ix++;
 768										q[i].ix[m] = ix;
 769									}
 770									else
 771									{
 772										break;
 773									}
 774								}
 775							}
 776						}
 777						q[i].c = m;
 778						if (RegExp.d)
 779						{
 780							trace("   " + m + " matches found");
 781						}
 782					}
 783					if (q[i].c < q[i].a)
 784					{
 785						if (RegExp.d)
 786						{
 787							trace("   not enough matches");
 788						}
 789						//Not enough matches 
 790						if (i > qb)
 791						{
 792							//Retreat back and decrease # of assumed matches
 793							i--;
 794							q[i].c--;
 795							if (q[i].c >= 0)
 796							{
 797								ix = (q[i].t == 3 || q[i].t == 4) ? q[i].ix[q[i].c] : (q[i].i + q[i].c);
 798							}
 799							if (RegExp.d)
 800							{
 801								trace("Retreat to #" + i + " c=" + q[i].c + " index=" + ix);
 802							}
 803						}
 804						else
 805						{
 806							if (RegExp._xp > 1)
 807							{
 808								//If this is a paren, failing to find first match is fatal
 809								break;
 810							}
 811							if (atStart)
 812							{
 813								//Match must be at the start of string/line
 814								if (this.multiline)
 815								{
 816									//Jump to the beginning of the next line
 817									while (ix <= l)
 818									{
 819										s = substring(str, 1 + ix++, 1);
 820										if (s == "\\\\\\\\\\\\\\\\n" || s == "\\\\\\\\\\\\\\\\r")
 821										{
 822											break;
 823										}
 824									}
 825									q[i].c = -10;
 826								}
 827								else
 828								{
 829									//No match
 830									break;
 831								}
 832							}
 833							else
 834							{
 835								//Start a new search from next position
 836								ix++;
 837								q[i].c = -10;
 838							}
 839						}
 840					}
 841					else
 842					{
 843						if (RegExp.d)
 844						{
 845							trace("   enough matches!");
 846						}
 847						//# of matches ok, proceed to next 
 848						i++;
 849						if (i == qc || q[i].t == 7)
 850						{
 851							if (RegExp.d)
 852							{
 853								trace("Saving better result: r.i = q[" + qb + "].i = " + q[qb].i);
 854							}
 855							r.i = q[qb].i;
 856							r.li = ix;
 857							break;
 858						}
 859						else
 860						{
 861							q[i].c = -10;
 862						}
 863					}
 864				}
 865			}
 866			while (i < qc && q[i].t != 7)
 867			{
 868				i++;
 869			}
 870			//Jump to the next "OR" section
 871		}
 872		if (r.i < 0)
 873		{
 874			this.lastIndex = 0;
 875			if (RegExp._xp-- == 1)
 876			{
 877				RegExp._xxa = [];
 878				RegExp._xxlp = 0;
 879			}
 880			return false;
 881		}
 882		else
 883		{
 884			ix = r.li;
 885			this._xi = r.i;
 886			RegExp._xxlm = substring(str_, r.i + 1, ix - r.i);
 887			RegExp._xxlc = substring(str_, 1, r.i);
 888			RegExp._xxrc = substring(str_, ix + 1, l - ix);
 889			if (ix == r.i)
 890			{
 891				ix++;
 892			}
 893			this.lastIndex = ix;
 894			if (RegExp._xp-- == 1)
 895			{
 896				RegExp.lastMatch = RegExp._xxlm;
 897				RegExp.leftContext = RegExp._xxlc;
 898				RegExp.rightContext = RegExp._xxrc;
 899				RegExp._xaStatic = RegExp._xxa;
 900				RegExp.lastParen = RegExp._xxa[Number(RegExp._xxlp)];
 901				for (i = 1; i < 10; i++)
 902				{
 903					RegExp["$" + i] = RegExp._xaStatic[Number(i)];
 904				}
 905			}
 906			return true;
 907		}
 908	}
 909	/**A RegExp method that executes a search for a match in a string. 
 910	*@usage re.exec(string) 
 911	*@param string   <code>(String)</code> The string to be pattern-matched
 912	*@returns Object with properties index (the position), input (the string) and 0 (the matched character(s))<br>
 913	*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.
 914	*@example p2 = new RegExp("\\d+","g");<br>
 915	next_string = "I have 23 ways to list 5 objects on 217 pieces of paper";<br>
 916	var results1:Object = p2.exec(next_string);<br>
 917	while (results1 != null)<br>
 918	{<br>
 919	for (var prop in results1){<br>
 920	trace("   * "+prop+" : "+results1[prop]);<br>
 921	}<br>
 922	results1 = p2.exec(next_string);<br>
 923	}<br>*/
 924	public function exec()
 925	{
 926		var str = arguments[0] + '';
 927		if (str == '')
 928		{
 929			return false;
 930		}
 931		var t = this.test(str);
 932		if (t)
 933		{
 934			var ra = new Array();
 935			ra.index = this._xi;
 936			ra.input = str;
 937			ra[0] = RegExp.lastMatch;
 938			var l = RegExp._xaStatic.length;
 939			for (var i = 1; i < l; i++)
 940			{
 941				ra[i] = RegExp._xaStatic[Number(i)];
 942			}
 943		}
 944		else
 945		{
 946			var ra = null;
 947		}
 948		return ra;
 949	}
 950	public static function setStringMethods()
 951	{
 952		trace("setStringMethods being defined");
 953		if (String.prototype.match != undefined)
 954		{
 955			trace("Warning - match is already defined, String.prototype functions will be overridden");
 956			//return;
 957		}
 958		if (String.prototype.replace != undefined)
 959		{
 960			trace("Warning - replace is being replaced");
 961		}
 962		/**Finds the characters that match the pattern defined by the regular expression.<br>
 963		Use the "g" flag to repeat the process over and over. <br>
 964		Added to String.prototype so that it can be used with any string.
 965		Changed on January 26, 2010 to return a string - not sure how that will affect multiple calls with the "g" flag
 966		*@usage string.match(re) 
 967		*@param string   <code>(String)</code> The string to be pattern-matched
 968		*@returns Array with every matched set of characters
 969		*@example nameof = "StandardStart27_mc"; <br>
 970		p2 = new RegExp("\\d+","g");<br>
 971		trace("The digits are " + nameof.match(p2)[0]); //output 27<br>*/ 
 972		//public function match(re:RegExp):Array{
 973		String.prototype.match = function()
 974		{
 975			if (typeof (arguments[0]) != "object")
 976			{
 977				return null;
 978			}
 979			if (arguments[0].const != "RegExp")
 980			{
 981				trace("Warning - match not sent a RegExp");
 982				return null;
 983			}
 984			var re = arguments[0];
 985			var s = this.valueOf();
 986			var ip = 0;
 987			var rc = 0;
 988			if (re.global)
 989			{
 990				re.lastIndex = 0;
 991				while (re.test(s))
 992				{
 993					if (rc == 0)
 994					{
 995						var ra = new Array();
 996					}
 997					ra[rc++] = RegExp.lastMatch;
 998					ip = re.lastIndex;
 999				}
1000				re.lastIndex = ip;
1001			}
1002			else
1003			{
1004				var ra = re.exec(s);
1005				rc++;
1006			}
1007			return (rc == 0) ? null : ra;
1008		};
1009
1010		/**Replace the characters that match the pattern defined by the regular expression with another string.<br>
1011		*or Replace the given substring with another one (Based on a idea of Davide Beltrame (Broly))
1012		*found on <a href='http://www.sephiroth.it/proto_detail.php?id=16'>http://www.sephiroth.it/proto_detail.php?id=16</a><br>
1013		Added to String.prototype so that it can be used with any string.
1014		*@usage string.replace(re, new_string);
1015		*@usage string.replace(found_string, new_string);
1016		*@param re <code>(RegExp)</code> The Regular Expression with the pattern to be matched
1017		*@param found_string <code>(String)</code> The string to be matched
1018		*@param new_string <code>(String)</code> The string to use in the replacement
1019		*@returns String with replacement(s) made.
1020		*@example test_txt = "  swf  Missippi River   "; <br>
1021		p1 = new RegExp("\\s+","g");<br>
1022		trace(test_txt.replace(p1,"*")); //output '*swf*Missippi*River*'<br><br>
1023		*@example test = ".swflib/actions/test.swf is a .swf";<br>
1024		* trace(test+", "+test.replace('.swf', ''));  //.swflib/actions/test.swf is a .swf, lib/actions/test is a<br>
1025		*/
1026		//public function replace(re:RegExp, new_string:String):String{
1027		String.prototype.replace = function()
1028		{
1029			if (typeof (arguments[0]) != "object")
1030			{
1031				trace("Warning - replace not sent an Object");
1032				//return null;
1033			}
1034			if (arguments[0].const != "RegExp")
1035			{
1036				//definition when the first argument is a String
1037				var arg_search, arg_replace, position;
1038				var endText, preText, newText;
1039				arg_search = arguments[0];
1040				arg_replace = arguments[1];
1041				if (arg_search.length == 1)
1042				{
1043					return this.split(arg_search).join(arg_replace);
1044				}
1045				position = this.indexOf(arg_search);
1046				if (position == -1)
1047				{
1048					return this;
1049				}
1050				endText = this;
1051				newText = "";
1052				do
1053				{
1054					position = endText.indexOf(arg_search);
1055					preText = endText.substring(0, position);
1056					endText = endText.substring(position + arg_search.length);
1057					newText += preText + arg_replace;
1058				} while (endText.indexOf(arg_search) != -1);
1059				newText += endText;
1060				trace("replace returning a result based on a string object");
1061				return newText;
1062			}
1063			var re = arguments[0];
1064			var rs = arguments[1] + '';
1065			var s = this;
1066			var r = "";
1067			re.lastIndex = 0;
1068			if (re.global)
1069			{
1070				var ip = 0;
1071				var ix = 0;
1072				while (re.test(s))
1073				{
1074					//Replace backreferences in rs
1075					var i = 0;
1076					var l = length(rs);
1077					var c = "";
1078					var pc = "";
1079					var nrs = "";
1080					while (i < l)
1081					{
1082						c = substring(rs, 1 + i++, 1);
1083						if (c == "$" && pc != "\\")
1084						{
1085							c = substring(rs, 1 + i++, 1);
1086							if (isNaN(Number(c)) || Number(c) > 9)
1087							{
1088								nrs += "$" + c;
1089							}
1090							else
1091							{
1092								nrs += RegExp._xaStatic[Number(c)];
1093							}
1094						}
1095						else
1096						{
1097							nrs += c;
1098						}
1099						pc = c;
1100					}
1101					r += substring(s, ix + 1, re._xi - ix) + nrs;
1102					ix = re._xi + length(RegExp.lastMatch);
1103					ip = re.lastIndex;
1104				}
1105				re.lastIndex = ip;
1106			}
1107			else
1108			{
1109				if (re.test(s))
1110				{
1111					r += RegExp.leftContext + rs;
1112				}
1113			}
1114			r += re.lastIndex == 0 ? s : RegExp.rightContext;
1115			return r;
1116		};
1117
1118		/**Trim whitespace from the beginning of a string.<br>
1119		*Added to the class, informed by <a href='http://www.somacon.com/p355.php'>http://www.somacon.com/p355.php</a><br>
1120		*Added to String.prototype so that it can be used with any string.
1121		*@usage string.ltrim();
1122		*@returns trimmed String
1123		*@example test_txt = "&nbsp;&nbsp;swf&nbsp;&nbsp;&nbsp;Missippi&nbsp;River&nbsp;&nbsp;&nbsp;&nbsp;"; <br>
1124		trace(test_txt.ltrim()); //output 'swf&nbsp;&nbsp;&nbsp;Missippi&nbsp;River&nbsp;&nbsp;&nbsp;&nbsp;'<br><br>
1125		*/
1126		//public function ltrim():String{
1127		String.prototype.ltrim = function()
1128		{
1129			var re = new RegExp("^\\s+");
1130			return this.replace(re, "");
1131		};
1132		/**Trim whitespace from the end of a string.<br>
1133		*Added to the class, informed by <a href='http://www.somacon.com/p355.php'>http://www.somacon.com/p355.php</a><br>
1134		*Added to String.prototype so that it can be used with any string.
1135		*@usage string.rtrim();
1136		*@returns trimmed String
1137		*@example test_txt = "&nbsp;&nbsp;swf&nbsp;&nbsp;&nbsp;Missippi&nbsp;River&nbsp;&nbsp;&nbsp;&nbsp;"; <br>
1138		trace(test_txt.rtrim()); //output '&nbsp;&nbsp;swf&nbsp;&nbsp;&nbsp;Missippi&nbsp;River'<br><br>
1139		*/
1140		//public function rtrim():String{
1141		String.prototype.rtrim = function()
1142		{
1143			var re = new RegExp("\\s+$");
1144			return this.replace(re, "");
1145		};
1146		/**Trim whitespace from the beginning and end of a string.<br>
1147		*Added to the class by the CLIPS team<br>
1148		*Added to String.prototype so that it can be used with any string.
1149		*@usage string.trim();
1150		*@returns trimmed String
1151		*@example test_txt = "&nbsp;&nbsp;swf&nbsp;&nbsp;&nbsp;Missippi&nbsp;River&nbsp;&nbsp;&nbsp;&nbsp;"; <br>
1152		trace(test_txt.trim()); //output 'swf&nbsp;&nbsp;&nbsp;Missippi&nbsp;River'<br><br>
1153		*/
1154		//public function trim():String{
1155		String.prototype.trim = function()
1156		{
1157			//This device is used since the RegExp for whitespace at both ends didn't seem to work.
1158			return this.rtrim().ltrim();
1159		};
1160		/**Tests for a match in a string.<br>
1161		*Added to String.prototype so that it can be used with any string.
1162		*@usage string.search(re);
1163		*@returns the index of the match, or -1 if the search fails.
1164		*@example test_txt = "Therrrre Grrrrrrrrrreat"; <br>
1165		re = new RegExp("r+e","g");
1166		trace(test_txt.search(re)); //output 3<br><br>
1167		*@see test
1168		*/
1169		//public function search(re:RegExp):String{
1170
1171		String.prototype.search = function()
1172		{
1173			if (typeof (arguments[0]) != "object")
1174			{
1175				return null;
1176			}
1177			if (arguments[0].const != "RegExp")
1178			{
1179				trace("Warning - search not sent a RegExp");
1180				return null;
1181			}
1182			var re = arguments[0];
1183			var s = this;
1184			re.lastIndex = 0;
1185			var t = re.test(s);
1186			return t ? re._xi : -1;
1187		};
1188		String.prototype.old_split = String.prototype.split;
1189		/**Adds the ability to split a string based on a RegExp.<br>
1190		*Added to String.prototype so that it can be used with any string.
1191		*@usage string.split(re);
1192		*@usage string.split(string_delimiter, limit);
1193		*@param re the RegExp
1194		*@param string_delimiter the simple string to delimit by
1195		*@param limit the number of items to place in the array
1196		*@returns an Array of substrings
1197		*@example test_txt = "Therrrre Grrrrrrrrrreat"; <br>
1198		re = new RegExp("r+e","g");<br>
1199		trace(test_txt.split(re)); //output [The, G,at]<br>
1200		trace(test_txt.split("r"); //output [The,,,,e G,,,,,,,,,,eat]<br><br>
1201		*/
1202		//public function split(re:RegExp):String{
1203		String.prototype.split = function()
1204		{
1205			if (typeof (arguments[0]) == "object" && arguments[0].const == "RegExp")
1206			{
1207				var re = arguments[0];
1208				var lm = arguments[1] == null ? 9999 : Number(arguments[1]);
1209				if (isNaN(lm))
1210				{
1211					lm = 9999;
1212				}
1213				var s = this;
1214				var ra = new Array();
1215				var rc = 0;
1216				var gs = re.global;
1217				re.global = true;
1218				re.lastIndex = 0;
1219				var ip = 0;
1220				var ipp = 0;
1221				var ix = 0;
1222				while (rc < lm && re.test(s))
1223				{
1224					//trace(re._xi + " " + ix + " " + RegExp.lastMatch);
1225					if (re._xi != ix)
1226					{
1227						ra[rc++] = substring(s, ix + 1, re._xi - ix);
1228					}
1229					ix = re._xi + length(RegExp.lastMatch);
1230					ipp = ip;
1231					ip = re.lastIndex;
1232				}
1233				if (rc == lm)
1234				{
1235					re.lastIndex = ipp;
1236				}
1237				else
1238				{
1239					re.lastIndex = ip;
1240				}
1241				if (rc == 0)
1242				{
1243					ra[rc] = s;
1244				}
1245				else
1246				{
1247					if (rc < lm && length(RegExp.rightContext) > 0)
1248					{
1249						ra[rc++] = RegExp.rightContext;
1250					}
1251				}
1252				re.global = gs;
1253				return ra;
1254			}
1255			else
1256			{
1257				return this.old_split(arguments);
1258			}
1259		};
1260		return true;
1261	}
1262}