src/vs/editor/standalone/common/monarch/monarchCompile.ts/compileRegExp
function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp {
	// @@ must be interpreted as a literal @, so we replace all occurences of @@ with a placeholder character
	str = str.replace(/@@/g, `\x01`);

	let n = 0;
	let hadExpansion: boolean;
	do {
		hadExpansion = false;
		str = str.replace(/@(\w+)/g, function (s, attr?) {
			hadExpansion = true;
			let sub = '';
			if (typeof (lexer[attr]) === 'string') {
				sub = lexer[attr];
			} else if (lexer[attr] && lexer[attr] instanceof RegExp) {
				sub = lexer[attr].source;
			} else {
				if (lexer[attr] === undefined) {
					throw monarchCommon.createError(lexer, 'language definition does not contain attribute \'' + attr + '\', used at: ' + str);
				} else {
					throw monarchCommon.createError(lexer, 'attribute reference \'' + attr + '\' must be a string, used at: ' + str);
				}
			}
			return (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')');
		});
		n++;
	} while (hadExpansion && n < 5);

	// handle escaped @@
	str = str.replace(/\x01/g, '@');

	const flags = (lexer.ignoreCase ? 'i' : '') + (lexer.unicode ? 'u' : '');
	return new RegExp(str, flags);
}