whole_func_string: function parseAbbreviation(abbr) {
  		abbr = require('utils').trim(abbr);
  		
  		var root = new AbbreviationNode;
  		var context = root.addChild(), ch;
  		
  		/** @type StringStream */
  		var stream = require('stringStream').create(abbr);
  		var loopProtector = 1000, multiplier;
  		
  		while (!stream.eol() && --loopProtector > 0) {
  			ch = stream.peek();
  			
  			switch (ch) {
  				case '(': // abbreviation group
  					stream.start = stream.pos;
  					if (stream.skipToPair('(', ')')) {
  						var inner = parseAbbreviation(stripped(stream.current()));
  						if (multiplier = stream.match(/^\*(\d+)?/, true)) {
  							context._setRepeat(multiplier[1]);
  						}
  						
  						_.each(inner.children, function(child) {
  							context.addChild(child);
  						});
  					} else {
  						throw 'Invalid abbreviation: mo matching ")" found for character at ' + stream.pos;
  					}
  					break;
  					
  				case '>': // child operator
  					context = context.addChild();
  					stream.next();
  					break;
  					
  				case '+': // sibling operator
  					context = context.parent.addChild();
  					stream.next();
  					break;
  					
  				case '^': // climb up operator
  					var parent = context.parent || context;
  					context = (parent.parent || parent).addChild();
  					stream.next();
  					break;
  					
  				default: // consume abbreviation
  					stream.start = stream.pos;
  					stream.eatWhile(function(c) {
  						if (c == '[' || c == '{') {
  							if (stream.skipToPair(c, pairs[c])) {
  								stream.backUp(1);
  								return true;
  							}
  							
  							throw 'Invalid abbreviation: mo matching "' + pairs[c] + '" found for character at ' + stream.pos;
  						}
  						
  						if (c == '+') {
  							// let's see if this is an expando marker
  							stream.next();
  							var isMarker = stream.eol() ||  ~'+>^*'.indexOf(stream.peek());
  							stream.backUp(1);
  							return isMarker;
  						}
  						
  						return c != '(' && isAllowedChar(c);
  					});
  					
  					context.setAbbreviation(stream.current());
  					stream.start = stream.pos;
  			}
  		}
  		
  		if (loopProtector < 1)
  			throw 'Endless loop detected';
  		
  		return root;
  	}
func_code_string: function parseAbbreviation(abbr) {
  		abbr = require('utils').trim(abbr);
  		
  		var root = new AbbreviationNode;
  		var context = root.addChild(), ch;
  		
  		/** @type StringStream */
  		var stream = require('stringStream').create(abbr);
  		var loopProtector = 1000, multiplier;
  		
  		while (!stream.eol() && --loopProtector > 0) {
  			ch = stream.peek();
  			
  			switch (ch) {
  				case '(': // abbreviation group
  					stream.start = stream.pos;
  					if (stream.skipToPair('(', ')')) {
  						var inner = parseAbbreviation(stripped(stream.current()));
  						if (multiplier = stream.match(/^\*(\d+)?/, true)) {
  							context._setRepeat(multiplier[1]);
  						}
  						
  						_.each(inner.children, function(child) {
  							context.addChild(child);
  						});
  					} else {
  						throw 'Invalid abbreviation: mo matching ")" found for character at ' + stream.pos;
  					}
  					break;
  					
  				case '>': // child operator
  					context = context.addChild();
  					stream.next();
  					break;
  					
  				case '+': // sibling operator
  					context = context.parent.addChild();
  					stream.next();
  					break;
  					
  				case '^': // climb up operator
  					var parent = context.parent || context;
  					context = (parent.parent || parent).addChild();
  					stream.next();
  					break;
  					
  				default: // consume abbreviation
  					stream.start = stream.pos;
  					stream.eatWhile(function(c) {
  						if (c == '[' || c == '{') {
  							if (stream.skipToPair(c, pairs[c])) {
  								stream.backUp(1);
  								return true;
  							}
  							
  							throw 'Invalid abbreviation: mo matching "' + pairs[c] + '" found for character at ' + stream.pos;
  						}
  						
  						if (c == '+') {
  							// let's see if this is an expando marker
  							stream.next();
  							var isMarker = stream.eol() ||  ~'+>^*'.indexOf(stream.peek());
  							stream.backUp(1);
  							return isMarker;
  						}
  						
  						return c != '(' && isAllowedChar(c);
  					});
  					
  					context.setAbbreviation(stream.current());
  					stream.start = stream.pos;
  			}
  		}
  		
  		if (loopProtector < 1)
  			throw 'Endless loop detected';
  		
  		return root;
  	}
func_documentation_string: Parses abbreviation into a tree
  @param {String} abbr
  @returns {AbbreviationNode}