static tokenize( str ) {
		let output  = [];
		let buffer  = "";
		let escaped = false;
		let quote   = false;

		function clearBuffer() {
			if ( !buffer.length ) { return; }
			let Token = quote && tokenQuoteMap[ quote ] || SubstitutionTokenNoQuote;
			output.push( new Token( buffer ) );
			buffer = "";
			quote = false;
		}

		// tokenize string
		for ( let char, i = 0, l = str.length; i < l; i++ ) {
			char = str.charAt( i );

			// detect escaped characters
			if ( escaped ) {
				buffer += strEscape + char;
				escaped = false;
				continue;
			} else if ( char === strEscape ) {
				escaped = true;
				continue;
			}

			// detect quoted strings
			if ( reQuote.test( char ) ) {
				// not in quoted mode
				if ( !quote ) {
					clearBuffer();
					buffer += char;
					quote = char;
					continue;

					// closing quotation mark
				} else if ( char === quote ) {
					buffer += char;
					clearBuffer();
					continue;
				}
			}

			// add char to buffer
			buffer += char;
		}

		if ( buffer.length ) {
			if ( escaped ) {
				buffer += strEscape;
			}
			clearBuffer();
		}

		return output;
	}
Tokenize a string
@param {String} str
@returns {SubstitutionToken[]}