-
Notifications
You must be signed in to change notification settings - Fork 92
Expand file tree
/
Copy pathgrammar-serializer.ts
More file actions
63 lines (56 loc) · 2.94 KB
/
grammar-serializer.ts
File metadata and controls
63 lines (56 loc) · 2.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/******************************************************************************
* Copyright 2021 TypeFox GmbH
* This program and the accompanying materials are made available under the
* terms of the MIT License, which is available in the project root.
******************************************************************************/
/* eslint-disable @stylistic/indent */
import type { Grammar, LangiumCoreServices } from 'langium';
import { expandToNode, joinToNode, normalizeEOL, toString } from 'langium/generate';
import type { URI } from 'vscode-uri';
import type { LangiumConfig } from '../package-types.js';
import { generatedHeader } from './node-util.js';
export function serializeGrammar(services: LangiumCoreServices, grammars: Grammar[], config: LangiumConfig): string {
const node = expandToNode`
${generatedHeader}
`.appendNewLine(
).appendTemplateIf(!!config.langiumInternal)`
import type { Grammar } from '../../languages/generated/ast${config.importExtension}';
import { loadGrammarFromJson } from '../../utils/grammar-loader${config.importExtension}';
`.appendTemplateIf(!config.langiumInternal)`
import type { Grammar } from 'langium';
import { loadGrammarFromJson } from 'langium';
`.appendNewLine();
node.append(
joinToNode(
grammars.filter(grammar => grammar.name),
grammar => {
const production = config.mode === 'production';
const delimiter = production ? "'" : '`';
const uriConverter = (uri: URI) => {
// We expect the grammar to be self-contained after the transformations we've done before
throw new Error(`Unexpected reference to element in document: ${uri.toString()}`);
};
const serializedGrammar = services.serializer.JsonSerializer.serialize(grammar, {
space: production ? undefined : 2,
comments: true,
uriConverter
});
// The json serializer returns strings with \n line delimiter by default
// We need to translate these line endings to the OS specific line ending
let json = normalizeEOL(serializedGrammar
.replace(/\\/g, '\\\\')
.replace(new RegExp(delimiter, 'g'), '\\' + delimiter));
if (!production) {
// Escape ${ in template strings
json = json.replace(/\${/g, '\\${');
}
return expandToNode`
let loaded${grammar.name}Grammar: Grammar | undefined;
export const ${grammar.name}Grammar = (): Grammar => loaded${grammar.name}Grammar ?? (loaded${grammar.name}Grammar = loadGrammarFromJson(${delimiter}${json}${delimiter}));
`;
},
{ appendNewLineIfNotEmpty: true }
)
);
return toString(node);
}