code: function(str) {
  			var curOffset = str.length;
  			var startIndex = -1;
  			var groupCount = 0;
  			var braceCount = 0;
  			var textCount = 0;
  			
  			while (true) {
  				curOffset--;
  				if (curOffset < 0) {
  					// moved to the beginning of the line
  					startIndex = 0;
  					break;
  				}
  				
  				var ch = str.charAt(curOffset);
  				
  				if (ch == ']') {
  					braceCount++;
  				} else if (ch == '[') {
  					if (!braceCount) { // unexpected brace
  						startIndex = curOffset + 1;
  						break;
  					}
  					braceCount--;
  				} else if (ch == '}') {
  					textCount++;
  				} else if (ch == '{') {
  					if (!textCount) { // unexpected brace
  						startIndex = curOffset + 1;
  						break;
  					}
  					textCount--;
  				} else if (ch == ')') {
  					groupCount++;
  				} else if (ch == '(') {
  					if (!groupCount) { // unexpected brace
  						startIndex = curOffset + 1;
  						break;
  					}
  					groupCount--;
  				} else {
  					if (braceCount || textCount) 
  						// respect all characters inside attribute sets or text nodes
  						continue;
  					else if (!abbreviationParser.isAllowedChar(ch) || (ch == '>' && utils.endsWithTag(str.substring(0, curOffset + 1)))) {
  						// found stop symbol
  						startIndex = curOffset + 1;
  						break;
  					}
  				}
  			}
  			
  			if (startIndex != -1 && !textCount && !braceCount && !groupCount) 
  				// found something, remove some invalid symbols from the 
  				// beginning and return abbreviation
  				return str.substring(startIndex).replace(/^[\*\+\>\^]+/, '');
  			else
  				return '';
  		}
docs: Extracts abbreviations from text stream, starting from the end
  @param {String} str
  @return {String} Abbreviation or empty string
  @memberOf emmet.actionUtils