function tokenize(glob) {
	return glob.split(/([@?+*]\(|\/\*\*\/|\*\*|[?*]|\[[\!\^]?(?:[^\]\\]|\\.)+\]|\{|,|\/|[|)}])/g).map(function(item) {
		if(!item)
			return null;
		var t = SIMPLE_TOKENS[item];
		if(t) {
			return {
				type: t
			};
		}
		if(item[0] === "[") {
			if(item[1] === "^" || item[1] === "!") {
				return {
					type: "inverted-char-set",
					value: item.substr(2, item.length - 3)
				};
			} else {
				return {
					type: "char-set",
					value: item.substr(1, item.length - 2)
				};
			}
		}
		return {
			type: "string",
			value: item
		};
	}).filter(Boolean).concat({
		type: "end"
	});
}
/ /.+/
	// ^* \./.+ (concord special)
	// ? [^\\\/]
	// [!...] [^...]
	// [^...] [^...]
	// / [\\\/]
	// {...,...} (...|...)
	// ?(...|...) (...|...)?
	// +(...|...) (...|...)+
	// *(...|...) (...|...)*
	// @(...|...) (...|...)
	if(/^\(.+\)$/.test(glob)) {
		// allow to pass an RegExp in brackets
		return new RegExp(glob.substr(1, glob.length - 2));
	}
	var tokens = tokenize(glob);
	var process = createRoot();
	var regExpStr = tokens.map(process).join("");
	return new RegExp("^" + regExpStr + "$");
}

var SIMPLE_TOKENS = {
	"@(": "one",
	"?(": "zero-one",
	"+(": "one-many",
	"*(": "zero-many",
	"|": "segment-sep",
	"/*