EDIT: Added refactored version 2.0 to the end!
Refactored version:
NOTES:
I've kept camelCase naming for private methods names. The official naming convention talks only about public methods and camelCase really helps me with readability.
I've separated parseNewExpression to it's own method as it seemed to me that there was too much code repetition.
ParseExpression() is still without parameters because one should be able to Reparse previously added expression without the need to set it again (e.g. after SkipInvalidTokens settings change).
Significantly reduced ParseExpression methods (there was quite a lot of overlapping cuntionality). Now it's slower but waaay nicer (and who cares about speed anyway...)
public void ParseExpression() { ParsedSubstringType lastType = ParsedSubstringType.NotSet; parsedExpression.Clear(); parsedTypes.Clear(); StringBuilder charBuffer = new StringBuilder(avgTokenLength); foreach (char token in rawExpression) { ParsedSubstringType currentType = getTokenType(token); if(IsCoumpnoundable(lastType) && currentType != lastType) { parseNewExpression(charBuffer, lastType); } lastType = currentType; if (IsCoumpnoundable(currentType)) { charBuffer.Append(token); continue; } if (currentType == ParsedSubstringType.Invalid && SkipInvalidChars) { continue; } charBuffer.Append(token); parseNewExpression(charBuffer, currentType); } if (charBuffer.Length > 0) { parseNewExpression(charBuffer, lastType); } } private void parseNewExpression(StringBuilder charBuffer, ParsedSubstringType currentType) { string expression = (isTrashable(currentType)) ? string.Empty : charBuffer.ToString(); parsedTypes.Add(currentType); parsedExpression.Add(expression); charBuffer.Clear(); } private bool IsCoumpnoundable(ParsedSubstringType type) { return ( type == ParsedSubstringType.Num || type == ParsedSubstringType.Name || type == ParsedSubstringType.WhiteSpace ); } private bool isTrashable(ParsedSubstringType type) { return (type == ParsedSubstringType.WhiteSpace); }