whole_func_string: function createMatcher(text) {
  		var memo = {}, m;
  		return {
  			/**
  			 * Test if given position matches opening tag
  			 * @param {Number} i
  			 * @returns {Object} Matched tag object
  			 */
  			open: function(i) {
  				var m = this.matches(i);
  				return m && m.type == 'open' ? m : null;
  			},
  			
  			/**
  			 * Test if given position matches closing tag
  			 * @param {Number} i
  			 * @returns {Object} Matched tag object
  			 */
  			close: function(i) {
  				var m = this.matches(i);
  				return m && m.type == 'close' ? m : null;
  			},
  			
  			/**
  			 * Matches either opening or closing tag for given position
  			 * @param i
  			 * @returns
  			 */
  			matches: function(i) {
  				var key = 'p' + i;
  				
  				if (!(key in memo)) {
  					if (text.charAt(i) == '<') {
  						var substr = text.slice(i);
  						if (m = substr.match(reOpenTag)) {
  							memo[key] = openTag(i, m);
  						} else if (m = substr.match(reCloseTag)) {
  							memo[key] = closeTag(i, m);
  						} else {
  							// remember that given position contains no valid tag
  							memo[key] = false;
  						}
  					}
  				}
  				
  				return memo[key];
  			},
  			
  			/**
  			 * Returns original text
  			 * @returns {String}
  			 */
  			text: function() {
  				return text;
  			}
  		};
  	}
func_code_string: function createMatcher(text) {
  		var memo = {}, m;
  		return {
  			/**
  			 * Test if given position matches opening tag
  			 * @param {Number} i
  			 * @returns {Object} Matched tag object
  			 */
  			open: function(i) {
  				var m = this.matches(i);
  				return m && m.type == 'open' ? m : null;
  			},
  			
  			/**
  			 * Test if given position matches closing tag
  			 * @param {Number} i
  			 * @returns {Object} Matched tag object
  			 */
  			close: function(i) {
  				var m = this.matches(i);
  				return m && m.type == 'close' ? m : null;
  			},
  			
  			/**
  			 * Matches either opening or closing tag for given position
  			 * @param i
  			 * @returns
  			 */
  			matches: function(i) {
  				var key = 'p' + i;
  				
  				if (!(key in memo)) {
  					if (text.charAt(i) == '<') {
  						var substr = text.slice(i);
  						if (m = substr.match(reOpenTag)) {
  							memo[key] = openTag(i, m);
  						} else if (m = substr.match(reCloseTag)) {
  							memo[key] = closeTag(i, m);
  						} else {
  							// remember that given position contains no valid tag
  							memo[key] = false;
  						}
  					}
  				}
  				
  				return memo[key];
  			},
  			
  			/**
  			 * Returns original text
  			 * @returns {String}
  			 */
  			text: function() {
  				return text;
  			}
  		};
  	}
func_documentation_string: Creates new tag matcher session
  @param {String} text