RegExp and String filtering

As I’ve developed my game I’ve written its various descriptions and parts that are filled in with variable miss-match sentence parts and have setup a debugging system that reads what the player writes, both of these things rely on string reading functions and Regular expression process. However, in all this time I’ve never learned the proper way to handle or write a regular expression and I wanted to see if anyone else had any input on their structure or how you’re supposed to use them.

An example of a command I do understand is how to strip an inputted text of all its alphabetical components, leaving only numbers behind. When someone uses the debug command “hp+5” it uses:

output = parseFloat(input.replace(/[^\d]+/g, ""));

where ^\d tells it to strip everything that isn’t a number and the parseFloat converts the remaining numerical string into a usable number for the system, which I can then use to hand off to the variable identified by the “hp” and apply it with the given operand “+”.

I use several other methods to break up commands, or store or change specific parts, but outside of commands I’ve started using things to capitalize the beginning of a word if it appears at the start of a sentence, such as:

newword = (oldword.charAt(0).toUpperCase() + oldword.slice(1));

which is something that basically takes the first character out of a word, capitalizes it and stitches it back onto original word. Not exactly regular express, but works similarly.

Anyways, the reason I’m brining this all up is I wanted to see if anyone out there had any tips or tricks on some good regexp to use. For example, the capitalization one up there is used when you already know that something will need to be capitalized. Like starting a sentance with a variable string. That string might always be used in other sentences uncaptilized but if you know you’re going to be using that variable set to start a sentence, you’ll want to capitalize it in that instance so as to not screw with the other instances. But I don’t have it set up yet to always look out for uncaptilaized beginning sentences. So that’s something I need to look up.

Another point would be spacing. Sometimes I have a sentance that goes “words “+variable+” words” which will look nice when that variable is in there, but say that the variable is supposed to be blank on that draw, so variable = “”;, it’ll display a sentence that looks like “words words” where one can see a second white space that’s left behind.
I use this command to strip out any double spaces.

String.replace(/( {2,})/g, ' ');

which, when used, makes “words words” into “words words”.
Originally I used

String.replace(/\s{2,}/g, ' ');

The issue with that was it stripped out all non single spaced spacing data, including the “\r” line breaks I used. Which meant that everything compressed into one huge paragraph. I couldn’t figure out how to tell it to strip out double spaces and avoid line breaks for some reason.

So, tried out the newer one which seems to work, but I still don’t know how to write exclusions or additions in a RegExp when I’ll likely need to in the future, even if the blank space one works for now. I’m sure I could just google more, but I figured I’d see if we could get a discussion going. lol.

That goes beyond my programming experience unfortunately.

A good source for learning and testing regular expressions would be RegExr: http://regexr.com/

There, you can test your regular expressions as well as hover over aspects of it and see what each individual part is doing.

For instance, if we wanted to determine if the first word of a sentence ending with a period, exclamation mark, or question mark is not capitalized, you could enter this regex in RegExr:

/^[a-z].*(\.|\?|\!)$/g

And then hover over each part to see what its doing. Its been pretty helpful when I need refreshing or exploring a new part of regex, as it is quite extensive.

No problem. Regular expression are kind of a pain regardless of experience level.
When searching for info about it in regards to AS3 (the language I use) there’s almost no help for it as everyone is either “ugh, it’s self explanatory, go read the directory” or they show how to do something but not in a way that I can use for future reference for a different kind of situation. You know, it’s just something that works for that one spot. It’d be like in a math class they tell you how how long division works, but not how to use it on fractions or something, I dunno. lol

Oh, dang, that’s a pretty cool program. Thanks man. Karma+

I think RegExp is pretty neat stuff when you start playing around with it. Given the right combo of filters you can make some really dynamic text processes. But man do I feel like a newbie in the dark with this stuff sometimes. lol

Regular expression are just straight up hard. I program professionally, and the stuff you end up with will look like complete and utter nonsense. I mean look at the “proper” regex for email verification:

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t] )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?: \r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:( ?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0 31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\ ](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+ (?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?: (?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z |(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n) ?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\ r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n) ?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t] )*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])* )(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t] )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*) *:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+ |\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r \n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?: \r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t ]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031 ]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\]( ?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(? :(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(? :\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(? :(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)? [ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]| \\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<> @,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|" (?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t] )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(? :[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[ \]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000- \031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|( ?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,; :\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([ ^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\" .\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\ ]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\ [\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\ r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\] |\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0 00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\ .|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@, ;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(? :[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])* (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\". \[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[ ^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\] ]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*( ?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:( ?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[ \["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t ])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t ])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(? :\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+| \Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?: [^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\ ]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n) ?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[" ()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n) ?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<> @,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@, ;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t] )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)? (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\". \[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?: \r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[ "()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t]) *))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]) +|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\ .(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z |(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:( ?:\r\n)?[ \t])*))*)?;\s*)

I still only know the top layers of it. Stuff’s crazy powerful though.

By the gods. Ha! :-X
That is some crazy shit, it looks like a bunch of random junk that wouldn’t do anything at all.

Whenever you think you need to use regex, chances are there’s a string function built into your language that already does what you want. Using regex adds the burden of extra documentation since most people reading your code will not know how to decipher your regex off the top of their head. So I typically try to avoid it.

For example, to strip a variable of alphabetical characters php has a function called filter_var() and you can feed it constants to tell it to do just that. Or for removing extra whitespace from a string, you can use trim(). And these functions would run faster than regex since they’re built into the php library.

However there are some cases where using regex is the best option if you’re looking to do custom things, for example extracting variables inside curly brackets in a string (preg_match_all takes in regex as input):

public static function extractVariables($text){
	if(preg_match_all('/{(.*?)}/', $text, $matches)){
		foreach($matches[1] as $key => $value){
			$text = str_replace($matches[0][$key], $_SESSION['objRPGCharacter']->$value(), $text);
		}
	}
	return $text;
}

Or deciding whether to use “a” or “an” based on if the next word in the string begins with a vowel or not ($1 being ‘a’ and $2 being the word which follows):

return ($a == true) ? preg_replace('/\b(a)\s+([aeiou])/i', '$1n $2', 'a ' . $strReturn) : $strReturn;

I think I’m with Cryptic on this one. Writing regex is useful as a quick and dirty way of doing something; I do it a lot when writing scripts or using the editor vi. If you are going to be doing it a lot then there’s usually a better way. Plus you’ll find there’s lots of different flavours of regex to deal with.

Looking at the original “hp+5” example, you actually need to extract three things; the variable, the operator, and the number. You could write three regex, or you could tackle it as a good old-fashioned input parsing. Not sure about AS3, but most languages have some facility where you could basically call readWord, readChar, readNumber successively, each starting where the previous left off.

For all the text processing Yaffaif does, there’s only one regex (I checked), and it’s a old work around for the game file parsing. Having said that, the TextBuilder that is used to produce the output has a full-on parser, and is one of the most complicated bits. It takes care of all the articles, variable substitutions, pronouns, can re-order adjectives, and more. Not necessarily the best solution either.

As far as I’m aware AS3 doesn’t seem to have those functions built in. It does have things like “charat” or “charcodeat” which works similarly. Either way it’s rather embarrassing to talk about my code just because of how improper and inexperienced it is. lol. My current methods are probably not efficient at all, but there’s simply so many things that as3 does that aren’t readily available unless you read through the countless hours of manual information. Unless you know exactly what you should be looking up, it’s harder to find a tutorial.

The way my debug text current works is like this, When the player enters the text, it goes to a temporary variable, gets its excess spaces striped out and is then broken into a reference string (with it’s operand intact) and then its number is extracted into a secondary variable. The debug function checks the reference string against the command trigger, like if it has “hp” is at the start of the command etc.

... var DEBUGtemp:String = DEBUGtemp.replace(/\s+/g, " "); var DEBUGtemp2:Number =parseFloat(DEBUGtemp.replace(/[^\d]+/g, "")); ... if(DEBUGtemp.indexOf("hp")==0){//Health point manipulation if(DEBUGtemp.indexOf("+")!=-1||DEBUGtemp.indexOf("-")!=-1){curHP+= DEBUGtemp2;} else if(DEBUGtemp.indexOf("*")!=-1){curHP*= DEBUGtemp2;} else if(DEBUGtemp.indexOf("/")!=-1){curHP/= DEBUGtemp2;} else if(DEBUGtemp.indexOf("%")!=-1){curHP*=(DEBUGtemp2*.01);} else if(DEBUGtemp.indexOf("=")!=-1||DEBUGtemp.indexOf(" ")!=-1){curHP = DEBUGtemp2;} else if(DEBUGtemp.indexOf("max")!=-1){curHP = maxHP;} else if(DEBUGtemp.indexOf("min")!=-1){curHP = 0;} }

It gets the job done I guess. :-\

I think that’s actually the best way you can do things in ActionScript3 after doing a bit of searching.

In php you can make a string variable that stores the name of a function then call that function on an object:

$object = new Object();
$function = "setHP";
$amount = 5;
$object->$function($amount);

So you could do the whole “debug hp+5” thing in about 1/10th the code. I’m not actually sure what the technical name for this procedure is but it’s pretty neat. You really have to be careful which object methods you make public if you choose to do things this way though.

[quote=“Atticus.Arc, post:9, topic:716”]As far as I’m aware AS3 doesn’t seem to have those functions built in. It does have things like “charat” or “charcodeat” which works similarly. Either way it’s rather embarrassing to talk about my code just because of how improper and inexperienced it is. lol. My current methods are probably not efficient at all, but there’s simply so many things that as3 does that aren’t readily available unless you read through the countless hours of manual information. Unless you know exactly what you should be looking up, it’s harder to find a tutorial.

The way my debug text current works is like this, When the player enters the text, it goes to a temporary variable, gets its excess spaces striped out and is then broken into a reference string (with it’s operand intact) and then its number is extracted into a secondary variable. The debug function checks the reference string against the command trigger, like if it has “hp” is at the start of the command etc.

(snip)[/quote]

Disclaimer: If you have some code that’s working for you, keep it until it becomes too cumbersome to modify. Otherwise you can end up down an endless rabbithole of refactoring.

For the debug command parser, it sounds like you’re looking for a tokenizer. Here’s a quick one I tossed off based on your above. It relies on the fact that ECMAScript-derived languages have “bracket syntax” that lets you address properties by their names.

This example, if expanded, would let you modify any of the properties on a given object, if passed a string of the form: “+”, “-”, “/”, “*”, “%”, “=”, or " " (with this last one being an alias for ‘=’).

And it’s a bit easier to maintain than a giant if-else logic tree. :slight_smile:

// Splits an input string of the form "<property><operator><value>" into its components
// Supports +, -, / (and \), *, %, and = (with space as an alias for =)
function tokenize(str) {
	var splitStr = /([^\+\-\*\\\/\=\%]+)([\+\-\*\\\/\=\% ])(.+)/g.exec(str);
	return splitStr;
}

// Applies the modification specified in "debugStr" to the object passed in as "objToModify"
function parseDebugString(objToModify, debugStr) {
	// First reject bad input
	if(!debugStr) { return; } // No input
	debugStr = debugStr.trim();
	if(!debugStr) { return; } // All-space input

	// Figure out what our property, operator and value are
	var tokens = tokenize(debugStr);
	if(!tokens || tokens.length != 4) { return; } // Something went weird, or input was invalid

	// Extract into human-readable names for convenience
	var variableToModify = tokens[1];
	var operation = tokens[2];
	var valueToModifyBy = tokens[3].parseInt(); // Use parseFloat if you want to allow decimals

	if(Number.isNaN(valueToModifyBy)) { return; } // Unable to parse value


 	// Translate the string the user typed into the name of the variable/property in your code.
	// If you wanted to be fancy, you could even do this in a method on the object. ;)
	var propertyToModify;
	switch(variableToModify) {
		case "hp":
			propertyToModify = "hitPoints"; break;
		case "hpMax":
			propertyToModify = "hitPointsMax"; break;
		// ... more here ...
		default:
			propertyToModify = undefined;
	}

	if(!propertyToModify) { return; } // Invalid property name

	// Apply the operation to the property
	switch(operation) {
		case "+":
			objToModify[propertyToModify] += valueToModifyBy;
			break;
		case "-":
			objToModify[propertyToModify] -= valueToModifyBy;
			break;
		case "*":
			objToModify[propertyToModify] *= valueToModifyBy;
			break;
		case "/":
		case "\\":
			objToModify[propertyToModify] /= valueToModifyBy;
			break;
		case " ":
		case "=":
			objToModify[propertyToModify] = valueToModifyBy;
			break;
		case "%":
			// Is this supposed to be modulus or percentage?
			objToModify[propertyToModify] = objToModify[propertyToModify] % valueToModifyBy;
			break;
		default:
			// Error, no idea what to do! Log something?
			return;
	}
	// All done!
}

Now, the other bit – responsively reformatting a text template based on object data – that’s a bit more in depth and isn’t suited a quick fifty-line example.

Thanks for the input Cloacked-Ghost, I really appreciate it.
I’ll have to give that a thorough run through when I find some time. Looks nice.

Oddly enough I actually use something similar already. I built in a back-end debug system for when I don’t setup trigger names. by placing a “[/b]" at the front of a command it'll check the contents of that command to the game's full list of variables. If it finds the approximate variable the game uses, it'll active the command as it's parts delineate. So, I created the command "[b]hp+#[/b]" because it's short and convenient for the player, but if I hadn't they could also use "[b]curHP+#” to do the same effect. Provided one knows a variable or gets its name close enough, the game can modify it even if I hadn’t prewritten it.

[quote=“kilif, post:5, topic:716”]Regular expression are just straight up hard. I program professionally, and the stuff you end up with will look like complete and utter nonsense. I mean look at the “proper” regex for email verification:

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t] )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?: \r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:( ?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0 31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\ ](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+ (?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?: (?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z |(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n) ?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\ r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n) ?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t] )*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])* )(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t] )+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*) *:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+ |\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r \n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?: \r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t ]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031 ]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\]( ?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(? :(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(? :\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(? :(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)? [ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]| \\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<> @,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|" (?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t] )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(? :[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[ \]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000- \031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|( ?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,; :\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([ ^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\" .\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\ ]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\ [\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\ r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\] |\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0 00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\ .|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@, ;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(? :[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])* (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\". \[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[ ^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\] ]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*( ?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:( ?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[ \["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t ])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t ])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(? :\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+| \Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?: [^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\ ]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n) ?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[" ()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n) ?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<> @,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@, ;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t] )*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\ ".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)? (?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\". \[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?: \r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[ "()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t]) *))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]) +|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\ .(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z |(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:( ?:\r\n)?[ \t])*))*)?;\s*)

I still only know the top layers of it. Stuff’s crazy powerful though.[/quote]

as someone who play a lot of dwarf fortress, this string of symbols looks especially strange. All i see is a bunch of arrows laying in the ground, discarded socks, adventurers, and some piles of liquids

This is what got me started:

http://www.regular-expressions.info/

They’re pretty portable between programming languages, with some tweaks and improvements in each.

Here’s the AS3 reference for regular expressions:

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/RegExp.html

I’m usually in IRC, so feel free to jump in and ask questions, no matter how dumb they may sound.