Creates new tag matcher session
@param {String} text
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;
			}
		};
	}