src/vs/workbench/services/textMate/common/TMGrammarFactory.ts/TMGrammarFactory/createGrammar
class TMGrammarFactory:	public async createGrammar(languageId: string, encodedLanguageId: number): Promise<ICreateGrammarResult> {
		const scopeName = this._languageToScope.get(languageId);
		if (typeof scopeName !== 'string') {
			// No TM grammar defined
			throw new Error(missingTMGrammarErrorMessage);
		}

		const grammarDefinition = this._scopeRegistry.getGrammarDefinition(scopeName);
		if (!grammarDefinition) {
			// No TM grammar defined
			throw new Error(missingTMGrammarErrorMessage);
		}

		const embeddedLanguages = grammarDefinition.embeddedLanguages;
		if (this._injectedEmbeddedLanguages[scopeName]) {
			const injectedEmbeddedLanguages = this._injectedEmbeddedLanguages[scopeName];
			for (const injected of injectedEmbeddedLanguages) {
				for (const scope of Object.keys(injected)) {
					embeddedLanguages[scope] = injected[scope];
				}
			}
		}

		const containsEmbeddedLanguages = (Object.keys(embeddedLanguages).length > 0);

		let grammar: IGrammar | null;

		try {
			grammar = await this._grammarRegistry.loadGrammarWithConfiguration(
				scopeName,
				encodedLanguageId,
				{
					embeddedLanguages,
					tokenTypes: <any>grammarDefinition.tokenTypes,
					balancedBracketSelectors: grammarDefinition.balancedBracketSelectors,
					unbalancedBracketSelectors: grammarDefinition.unbalancedBracketSelectors,
				}
			);
		} catch (err) {
			if (err.message && err.message.startsWith('No grammar provided for')) {
				// No TM grammar defined
				throw new Error(missingTMGrammarErrorMessage);
			}
			throw err;
		}

		return {
			languageId: languageId,
			grammar: grammar,
			initialState: this._initialState,
			containsEmbeddedLanguages: containsEmbeddedLanguages
		};
	}