@mirascript/textmate 0.1.82 → 0.1.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/grammar.ts ADDED
@@ -0,0 +1,1157 @@
1
+ import type { LanguageRegistration } from '@shikijs/types';
2
+ import {
3
+ CONSTANT_KEYWORDS,
4
+ CONTROL_KEYWORDS,
5
+ KEYWORDS,
6
+ NUMERIC_KEYWORDS,
7
+ REG_IDENTIFIER,
8
+ RESERVED_KEYWORDS,
9
+ } from '@mirascript/constants';
10
+ import { mirascriptDocLanguage, mirascriptLanguage, mirascriptTemplateLanguage } from './language.ts';
11
+
12
+ const SCOPE_SUFFIX = 'mira';
13
+ const IDENTIFIER = REG_IDENTIFIER.source;
14
+ const IDENTIFIER_START = String.raw`(?<!\p{XID_Continue})`;
15
+ const IDENTIFIER_END = String.raw`(?!\p{XID_Continue})`;
16
+ const MAX_VERBATIM_LENGTH = 16;
17
+ const BUILT_IN_TYPES = [
18
+ 'any',
19
+ 'unknown',
20
+ 'never',
21
+
22
+ 'boolean',
23
+ 'true',
24
+ 'false',
25
+
26
+ 'number',
27
+ 'string',
28
+
29
+ 'record',
30
+ 'array',
31
+ 'extern',
32
+ 'module',
33
+
34
+ 'nil',
35
+ ];
36
+ const DOC_CONSTANT_IDENTIFIER = String.raw`(?:@+\p{XID_Continue}+|\p{Lu}[\p{XID_Continue}]*)`;
37
+ const DOC_TAG_NAME = String.raw`[^>\r\n]*[^>\s]`;
38
+ const DOC_TAG_CONTENT = String.raw`(?:module|function|extern)(?:[ \t]+${DOC_TAG_NAME})?`;
39
+ const DOC_FIELD_NAME = String.raw`(?:${IDENTIFIER}|\d+|"(?:\\.|[^"\\\r\n])*"|'(?:\\.|[^'\\\r\n])*')`;
40
+ const DOC_TAG_NUMBER = String.raw`\d[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?[\d_]*\d)?`;
41
+
42
+ /**
43
+ * Escape a literal value for insertion into an Oniguruma regular expression.
44
+ */
45
+ function escapeRegex(value: string): string {
46
+ return value.replaceAll(/[\\^$.*+?()[\]{}|]/g, String.raw`\$&`).replaceAll(/\s+/g, String.raw`\s+`);
47
+ }
48
+
49
+ /**
50
+ * Build a longest-first regular-expression alternation.
51
+ */
52
+ function alternatives(values: Iterable<string>): string {
53
+ return [...values]
54
+ .sort((a, b) => b.length - a.length)
55
+ .map(escapeRegex)
56
+ .join('|');
57
+ }
58
+
59
+ const numericKeywordSet = new Set<string>(NUMERIC_KEYWORDS);
60
+ const constantKeywords = CONSTANT_KEYWORDS.filter((keyword) => !numericKeywordSet.has(keyword));
61
+ const languageVariables = ['_', 'global'];
62
+ const wordOperators = ['in', 'is', 'and', 'or', 'not'];
63
+ const declarationKeywords = ['fn', 'op', 'let', 'const', 'mut', 'where'];
64
+ const moduleKeywords = ['mod', 'pub', 'use'];
65
+ const classifiedKeywords = new Set([
66
+ ...CONSTANT_KEYWORDS,
67
+ ...CONTROL_KEYWORDS,
68
+ ...languageVariables,
69
+ ...wordOperators,
70
+ ...declarationKeywords,
71
+ ...moduleKeywords,
72
+ ...RESERVED_KEYWORDS,
73
+ 'type',
74
+ ]);
75
+ const otherKeywords = KEYWORDS.filter((keyword) => !classifiedKeywords.has(keyword));
76
+ const mirascriptFenceTags = alternatives([mirascriptLanguage.name, ...mirascriptLanguage.aliases]);
77
+ const documentationMiraFenceBegin = String.raw`^(\s*\*\s?)(\x60{3,})\s*((?i:${mirascriptFenceTags}))?\s*$`;
78
+ const documentationOtherFenceBegin = String.raw`^(\s*\*\s?)(\x60{3,})\s*(\S+)(?:\s+.*)?\s*$`;
79
+ const documentationFenceEnd = String.raw`^(?:(\s*\*\s?)(\2\x60*)\s*$)|(?=\*/)`;
80
+ const documentationMiraLine = String.raw`^(?!\s*\*\s*\x60{3,}\s*$)(?!.*\*/)(\s*\*\s?)`;
81
+ const documentationInjectionSelector =
82
+ 'L:comment.block.documentation.mira -markup.fenced_code.block.mira -meta.documentation.inline.mira';
83
+
84
+ /**
85
+ * Create interpolation rules for one exact dollar-sign width.
86
+ */
87
+ function interpolationPatterns(dollarCount: number) {
88
+ const dollars = String.raw`\$`.repeat(dollarCount);
89
+ return [
90
+ {
91
+ name: `meta.interpolation.simple.${SCOPE_SUFFIX}`,
92
+ match: `(${dollars})(${IDENTIFIER})`,
93
+ captures: {
94
+ 1: { name: `punctuation.definition.template-expression.begin.${SCOPE_SUFFIX}` },
95
+ 2: { name: `variable.other.${SCOPE_SUFFIX}` },
96
+ },
97
+ },
98
+ {
99
+ name: `meta.interpolation.block.${SCOPE_SUFFIX}`,
100
+ begin: String.raw`(${dollars}\{)`,
101
+ beginCaptures: { 1: { name: `punctuation.definition.template-expression.begin.${SCOPE_SUFFIX}` } },
102
+ end: String.raw`\}`,
103
+ endCaptures: { 0: { name: `punctuation.definition.template-expression.end.${SCOPE_SUFFIX}` } },
104
+ patterns: [{ include: '#braced-content' }],
105
+ },
106
+ {
107
+ name: `meta.interpolation.expression.${SCOPE_SUFFIX}`,
108
+ begin: String.raw`(${dollars}\()`,
109
+ beginCaptures: { 1: { name: `punctuation.definition.template-expression.begin.${SCOPE_SUFFIX}` } },
110
+ end: String.raw`\)`,
111
+ endCaptures: { 0: { name: `punctuation.definition.template-expression.end.${SCOPE_SUFFIX}` } },
112
+ patterns: [
113
+ {
114
+ begin: ':(?!:)',
115
+ beginCaptures: { 0: { name: `punctuation.separator.format.${SCOPE_SUFFIX}` } },
116
+ end: String.raw`(?=\))`,
117
+ contentName: `string.unquoted.format.${SCOPE_SUFFIX}`,
118
+ patterns: [{ include: '#format-content' }],
119
+ },
120
+ { include: '#interpolation-expression-content' },
121
+ ],
122
+ },
123
+ ];
124
+ }
125
+
126
+ /**
127
+ * Create a quoted-string rule with escapes and single-dollar interpolation.
128
+ */
129
+ function normalString(quote: string, label: string) {
130
+ const escapedQuote = escapeRegex(quote);
131
+ return {
132
+ name: `string.quoted.${label}.${SCOPE_SUFFIX}`,
133
+ begin: escapedQuote,
134
+ beginCaptures: { 0: { name: `punctuation.definition.string.begin.${SCOPE_SUFFIX}` } },
135
+ end: escapedQuote,
136
+ endCaptures: { 0: { name: `punctuation.definition.string.end.${SCOPE_SUFFIX}` } },
137
+ patterns: [
138
+ { name: `constant.character.escape.unicode.${SCOPE_SUFFIX}`, match: String.raw`\\u\{[0-9A-Fa-f]+\}` },
139
+ { name: `constant.character.escape.hex.${SCOPE_SUFFIX}`, match: String.raw`\\x[0-9A-Fa-f]{2}` },
140
+ { name: `constant.character.escape.${SCOPE_SUFFIX}`, match: '\\\\[\\\\\'"\\`$rntbfv0]' },
141
+ { name: `invalid.illegal.escape.${SCOPE_SUFFIX}`, match: String.raw`\\.` },
142
+ ...interpolationPatterns(1),
143
+ ],
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Create an exact-width MiraScript verbatim-string rule.
149
+ */
150
+ function verbatimString(atCount: number, quote: string, label: string) {
151
+ const ats = '@'.repeat(atCount);
152
+ const escapedQuote = escapeRegex(quote);
153
+ return {
154
+ name: `string.quoted.${label}.verbatim.${SCOPE_SUFFIX}`,
155
+ begin: `(?<!@)${ats}${escapedQuote}`,
156
+ beginCaptures: { 0: { name: `punctuation.definition.string.begin.${SCOPE_SUFFIX}` } },
157
+ end: `${escapedQuote}${ats}(?!@)`,
158
+ endCaptures: { 0: { name: `punctuation.definition.string.end.${SCOPE_SUFFIX}` } },
159
+ patterns: interpolationPatterns(atCount),
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Build normal and 1-16 marker verbatim-string rules for every quote style.
165
+ */
166
+ function stringPatterns() {
167
+ const quotes = [
168
+ ['"', 'double'],
169
+ ["'", 'single'],
170
+ ['`', 'backtick'],
171
+ ] as const;
172
+ return [
173
+ ...Array.from({ length: MAX_VERBATIM_LENGTH }, (_, index) => MAX_VERBATIM_LENGTH - index).flatMap((atCount) =>
174
+ quotes.map(([quote, label]) => verbatimString(atCount, quote, label)),
175
+ ),
176
+ ...quotes.map(([quote, label]) => normalString(quote, label)),
177
+ ];
178
+ }
179
+
180
+ /**
181
+ * Build the documentation-comment rules shared by source and doc grammars.
182
+ */
183
+ function documentationRepository(sourceInclude = '#source') {
184
+ return {
185
+ documentation: {
186
+ patterns: [
187
+ { include: '#documentation-mirascript-fence' },
188
+ { include: '#documentation-other-fence' },
189
+ { include: '#documentation-line' },
190
+ { include: '#documentation-fragment' },
191
+ ],
192
+ },
193
+ 'documentation-inline': {
194
+ patterns: [
195
+ {
196
+ name: `storage.type.class.documentation.${SCOPE_SUFFIX}`,
197
+ match: String.raw`@(param|returns)\b`,
198
+ },
199
+ {
200
+ name: `markup.bold.documentation.${SCOPE_SUFFIX}`,
201
+ match: String.raw`\*\*[^*]+\*\*`,
202
+ },
203
+ { name: `markup.italic.documentation.${SCOPE_SUFFIX}`, match: String.raw`\*[^*]+\*` },
204
+ { name: `constant.character.escape.documentation.${SCOPE_SUFFIX}`, match: String.raw`\\\*` },
205
+ ],
206
+ },
207
+ 'documentation-line': {
208
+ patterns: [
209
+ {
210
+ match: String.raw`^(?!\s*\*/)(\s*\*\s?)(.*?)(?=\*/|$)`,
211
+ captures: {
212
+ 1: { name: `comment.block.documentation.${SCOPE_SUFFIX}` },
213
+ 2: {
214
+ name: `meta.documentation.inline.${SCOPE_SUFFIX}`,
215
+ patterns: [{ include: '#documentation-inline' }],
216
+ },
217
+ },
218
+ },
219
+ ],
220
+ },
221
+ 'documentation-fragment': {
222
+ patterns: [
223
+ {
224
+ match: String.raw`(?!\*/)(.+?)(?=\*/|$)`,
225
+ captures: {
226
+ 1: {
227
+ name: `meta.documentation.inline.${SCOPE_SUFFIX}`,
228
+ patterns: [{ include: '#documentation-inline' }],
229
+ },
230
+ },
231
+ },
232
+ ],
233
+ },
234
+ 'documentation-mirascript-fence': {
235
+ patterns: [
236
+ {
237
+ name: `markup.fenced_code.block.${SCOPE_SUFFIX}`,
238
+ begin: documentationMiraFenceBegin,
239
+ beginCaptures: {
240
+ 1: { name: `comment.block.documentation.${SCOPE_SUFFIX}` },
241
+ 2: { name: `punctuation.definition.markdown.${SCOPE_SUFFIX}` },
242
+ 3: { name: `fenced_code.block.language.${SCOPE_SUFFIX}` },
243
+ },
244
+ end: documentationFenceEnd,
245
+ endCaptures: {
246
+ 1: { name: `comment.block.documentation.${SCOPE_SUFFIX}` },
247
+ 2: { name: `punctuation.definition.markdown.${SCOPE_SUFFIX}` },
248
+ },
249
+ patterns: [
250
+ {
251
+ name: `meta.embedded.block.${SCOPE_SUFFIX}`,
252
+ contentName: `source.${SCOPE_SUFFIX}`,
253
+ begin: documentationMiraLine,
254
+ beginCaptures: {
255
+ 1: { name: `comment.block.documentation.${SCOPE_SUFFIX}` },
256
+ },
257
+ while: documentationMiraLine,
258
+ whileCaptures: {
259
+ 1: { name: `comment.block.documentation.${SCOPE_SUFFIX}` },
260
+ },
261
+ patterns: [{ include: sourceInclude }],
262
+ },
263
+ {
264
+ name: `comment.block.documentation.${SCOPE_SUFFIX}`,
265
+ match: String.raw`^(?!\s*\*/)(\s*\*\s?)`,
266
+ },
267
+ ],
268
+ },
269
+ ],
270
+ },
271
+ 'documentation-other-fence': {
272
+ patterns: [
273
+ {
274
+ name: `markup.fenced_code.block.${SCOPE_SUFFIX}`,
275
+ contentName: `markup.raw.block.${SCOPE_SUFFIX}`,
276
+ begin: documentationOtherFenceBegin,
277
+ beginCaptures: {
278
+ 1: { name: `comment.block.documentation.${SCOPE_SUFFIX}` },
279
+ 2: { name: `punctuation.definition.markdown.${SCOPE_SUFFIX}` },
280
+ 3: { name: `fenced_code.block.language.${SCOPE_SUFFIX}` },
281
+ },
282
+ end: documentationFenceEnd,
283
+ endCaptures: {
284
+ 1: { name: `comment.block.documentation.${SCOPE_SUFFIX}` },
285
+ 2: { name: `punctuation.definition.markdown.${SCOPE_SUFFIX}` },
286
+ },
287
+ patterns: [
288
+ {
289
+ name: `comment.block.documentation.${SCOPE_SUFFIX}`,
290
+ match: String.raw`^(?!\s*\*/)(\s*\*\s?)`,
291
+ },
292
+ ],
293
+ },
294
+ ],
295
+ },
296
+ };
297
+ }
298
+
299
+ /**
300
+ * Build the shared repository used by source and template grammars.
301
+ */
302
+ function sourceRepository(): LanguageRegistration['repository'] {
303
+ /**
304
+ * Create a boundary-aware TextMate keyword rule.
305
+ */
306
+ const keywordRule = (values: readonly string[], name: string) => ({
307
+ name: `${name}.${SCOPE_SUFFIX}`,
308
+ match: `${IDENTIFIER_START}(?:${alternatives(values)})${IDENTIFIER_END}`,
309
+ });
310
+ const keywordPatterns = [
311
+ keywordRule(NUMERIC_KEYWORDS, 'constant.numeric.language'),
312
+ keywordRule(constantKeywords, 'constant.language'),
313
+ keywordRule(CONTROL_KEYWORDS, 'keyword.control'),
314
+ keywordRule(wordOperators, 'keyword.operator.wordlike'),
315
+ keywordRule(declarationKeywords, 'keyword.declaration'),
316
+ keywordRule(moduleKeywords, 'keyword.control.module'),
317
+ keywordRule(RESERVED_KEYWORDS, 'keyword.reserved'),
318
+ keywordRule(languageVariables, 'variable.language'),
319
+ keywordRule(otherKeywords, 'keyword.other'),
320
+ ];
321
+
322
+ return {
323
+ source: {
324
+ patterns: [
325
+ { include: '#comments' },
326
+ { include: '#strings' },
327
+ { include: '#function-declarations' },
328
+ { include: '#module-declarations' },
329
+ { include: '#for-bindings' },
330
+ { include: '#record-properties' },
331
+ { include: '#member-access' },
332
+ { include: '#type-keyword' },
333
+ { include: '#keywords' },
334
+ { include: '#function-calls' },
335
+ { include: '#numbers' },
336
+ { include: '#identifiers' },
337
+ { include: '#operators' },
338
+ { include: '#punctuation' },
339
+ ],
340
+ },
341
+ comments: {
342
+ patterns: [
343
+ { name: `comment.line.double-slash.${SCOPE_SUFFIX}`, match: '//.*$' },
344
+ {
345
+ name: `comment.block.documentation.${SCOPE_SUFFIX}`,
346
+ begin: String.raw`/\*\*`,
347
+ end: String.raw`\*/`,
348
+ },
349
+ { name: `comment.block.${SCOPE_SUFFIX}`, begin: String.raw`/\*`, end: String.raw`\*/` },
350
+ ],
351
+ },
352
+ ...documentationRepository(),
353
+ 'format-content': {
354
+ patterns: [
355
+ { name: `constant.character.escape.format.${SCOPE_SUFFIX}`, match: String.raw`\\.` },
356
+ {
357
+ begin: String.raw`\[`,
358
+ end: String.raw`\]`,
359
+ name: `string.unquoted.format.character-class.${SCOPE_SUFFIX}`,
360
+ patterns: [{ name: `constant.character.escape.format.${SCOPE_SUFFIX}`, match: String.raw`\\.` }],
361
+ },
362
+ {
363
+ begin: String.raw`\(`,
364
+ end: String.raw`\)`,
365
+ name: `string.unquoted.format.group.${SCOPE_SUFFIX}`,
366
+ patterns: [{ include: '#format-content' }],
367
+ },
368
+ ],
369
+ },
370
+ strings: { patterns: stringPatterns() },
371
+ 'function-declarations': {
372
+ patterns: [
373
+ {
374
+ name: `meta.function.declaration.${SCOPE_SUFFIX}`,
375
+ begin: String.raw`${IDENTIFIER_START}(fn)(\s+)(${IDENTIFIER})(\s*)(\()`,
376
+ beginCaptures: {
377
+ 1: { name: `keyword.declaration.function.${SCOPE_SUFFIX}` },
378
+ 3: { name: `entity.name.function.${SCOPE_SUFFIX}` },
379
+ 5: { name: `punctuation.section.parameters.begin.${SCOPE_SUFFIX}` },
380
+ },
381
+ end: String.raw`\)`,
382
+ endCaptures: { 0: { name: `punctuation.section.parameters.end.${SCOPE_SUFFIX}` } },
383
+ patterns: [{ include: '#parameters' }],
384
+ },
385
+ {
386
+ name: `meta.function.declaration.${SCOPE_SUFFIX}`,
387
+ match: String.raw`${IDENTIFIER_START}(fn)(\s+)(${IDENTIFIER})`,
388
+ captures: {
389
+ 1: { name: `keyword.declaration.function.${SCOPE_SUFFIX}` },
390
+ 3: { name: `entity.name.function.${SCOPE_SUFFIX}` },
391
+ },
392
+ },
393
+ {
394
+ name: `meta.function.expression.parameters.${SCOPE_SUFFIX}`,
395
+ begin: String.raw`${IDENTIFIER_START}(fn)(\s*)(\()`,
396
+ beginCaptures: {
397
+ 1: { name: `keyword.declaration.function.${SCOPE_SUFFIX}` },
398
+ 3: { name: `punctuation.section.parameters.begin.${SCOPE_SUFFIX}` },
399
+ },
400
+ end: String.raw`\)`,
401
+ endCaptures: { 0: { name: `punctuation.section.parameters.end.${SCOPE_SUFFIX}` } },
402
+ patterns: [{ include: '#parameters' }],
403
+ },
404
+ ],
405
+ },
406
+ parameters: {
407
+ patterns: [
408
+ {
409
+ match: String.raw`${IDENTIFIER_START}(mut)(\s+)(${IDENTIFIER})`,
410
+ captures: {
411
+ 1: { name: `keyword.declaration.mutable.${SCOPE_SUFFIX}` },
412
+ 3: { name: `variable.emphasis.${SCOPE_SUFFIX}` },
413
+ },
414
+ },
415
+ {
416
+ name: `keyword.declaration.mutable.${SCOPE_SUFFIX}`,
417
+ match: `${IDENTIFIER_START}mut${IDENTIFIER_END}`,
418
+ },
419
+ { name: `keyword.operator.spread.${SCOPE_SUFFIX}`, match: String.raw`\.\.` },
420
+ { name: `variable.other.constant.emphasis.${SCOPE_SUFFIX}`, match: IDENTIFIER },
421
+ { name: `punctuation.separator.parameter.${SCOPE_SUFFIX}`, match: ',' },
422
+ {
423
+ begin: String.raw`\(`,
424
+ end: String.raw`\)`,
425
+ patterns: [{ include: '#parameters' }],
426
+ },
427
+ {
428
+ begin: String.raw`\[`,
429
+ end: String.raw`\]`,
430
+ patterns: [{ include: '#parameters' }],
431
+ },
432
+ { include: '#record-properties' },
433
+ ],
434
+ },
435
+ 'module-declarations': {
436
+ patterns: [
437
+ {
438
+ match: String.raw`${IDENTIFIER_START}(mod)(\s+)(${IDENTIFIER})`,
439
+ captures: {
440
+ 1: { name: `keyword.control.module.${SCOPE_SUFFIX}` },
441
+ 3: { name: `entity.name.namespace.${SCOPE_SUFFIX}` },
442
+ },
443
+ },
444
+ ],
445
+ },
446
+ 'for-bindings': {
447
+ patterns: [
448
+ {
449
+ match: String.raw`${IDENTIFIER_START}(for)(\s+)(mut)(\s+)(${IDENTIFIER})(\s+)(in)${IDENTIFIER_END}`,
450
+ captures: {
451
+ 1: { name: `keyword.control.loop.${SCOPE_SUFFIX}` },
452
+ 3: { name: `keyword.declaration.mutable.${SCOPE_SUFFIX}` },
453
+ 5: { name: `variable.other.readwrite.${SCOPE_SUFFIX}` },
454
+ 7: { name: `keyword.control.loop.${SCOPE_SUFFIX}` },
455
+ },
456
+ },
457
+ {
458
+ match: String.raw`${IDENTIFIER_START}(for)(\s+)(${IDENTIFIER})(\s+)(in)${IDENTIFIER_END}`,
459
+ captures: {
460
+ 1: { name: `keyword.control.loop.${SCOPE_SUFFIX}` },
461
+ 3: { name: `variable.other.${SCOPE_SUFFIX}` },
462
+ 5: { name: `keyword.control.loop.${SCOPE_SUFFIX}` },
463
+ },
464
+ },
465
+ ],
466
+ },
467
+ 'record-properties': {
468
+ patterns: [
469
+ {
470
+ match: String.raw`(${IDENTIFIER})(\s*)(\??:)(?!:)`,
471
+ captures: {
472
+ 1: { name: `variable.other.property.${SCOPE_SUFFIX}` },
473
+ 3: { name: `punctuation.separator.key-value.${SCOPE_SUFFIX}` },
474
+ },
475
+ },
476
+ ],
477
+ },
478
+ 'member-access': {
479
+ patterns: [
480
+ {
481
+ match: String.raw`(\.)(\s*)(\d+)`,
482
+ captures: {
483
+ 1: { name: `punctuation.accessor.${SCOPE_SUFFIX}` },
484
+ 3: { name: `variable.other.property.${SCOPE_SUFFIX}` },
485
+ },
486
+ },
487
+ {
488
+ match: `(\\.)(\\s*)(${IDENTIFIER})(\\s*)(!?)(?=\\s*(?:\\(|@*["'\`]))`,
489
+ captures: {
490
+ 1: { name: `punctuation.accessor.${SCOPE_SUFFIX}` },
491
+ 3: { name: `entity.name.function.member.${SCOPE_SUFFIX}` },
492
+ 5: { name: `keyword.operator.non-null.${SCOPE_SUFFIX}` },
493
+ },
494
+ },
495
+ {
496
+ match: String.raw`(\.)(\s*)(${IDENTIFIER})`,
497
+ captures: {
498
+ 1: { name: `punctuation.accessor.${SCOPE_SUFFIX}` },
499
+ 3: { name: `variable.other.property.${SCOPE_SUFFIX}` },
500
+ },
501
+ },
502
+ ],
503
+ },
504
+ 'function-calls': {
505
+ patterns: [
506
+ {
507
+ match: `(${IDENTIFIER})(\\s*)(!?)(?=\\s*(?:\\(|@*["'\`]))`,
508
+ captures: {
509
+ 1: { name: `entity.name.function.${SCOPE_SUFFIX}` },
510
+ 3: { name: `keyword.operator.non-null.${SCOPE_SUFFIX}` },
511
+ },
512
+ },
513
+ ],
514
+ },
515
+ 'type-keyword': {
516
+ patterns: [
517
+ {
518
+ name: `keyword.operator.expression.${SCOPE_SUFFIX}`,
519
+ match: String.raw`${IDENTIFIER_START}type${IDENTIFIER_END}(?=\s*\(|\s+${IDENTIFIER})`,
520
+ },
521
+ ],
522
+ },
523
+ numbers: {
524
+ patterns: [
525
+ {
526
+ name: `constant.numeric.hex.${SCOPE_SUFFIX}`,
527
+ match: `0[xX][0-9A-Fa-f](?:[0-9A-Fa-f_]*[0-9A-Fa-f])?${IDENTIFIER_END}`,
528
+ },
529
+ {
530
+ name: `constant.numeric.octal.${SCOPE_SUFFIX}`,
531
+ match: `0[oO][0-7](?:[0-7_]*[0-7])?${IDENTIFIER_END}`,
532
+ },
533
+ {
534
+ name: `constant.numeric.binary.${SCOPE_SUFFIX}`,
535
+ match: `0[bB][01](?:[01_]*[01])?${IDENTIFIER_END}`,
536
+ },
537
+ {
538
+ name: `invalid.illegal.numeric.${SCOPE_SUFFIX}`,
539
+ match: String.raw`0[xXoObB]\p{XID_Continue}*`,
540
+ },
541
+ {
542
+ name: `constant.numeric.float.${SCOPE_SUFFIX}`,
543
+ match: String.raw`\d[\d_]*(?:\.[\d_]+)?(?:[eE][+-]?[\d_]*\d)?${IDENTIFIER_END}`,
544
+ },
545
+ ],
546
+ },
547
+ keywords: { patterns: keywordPatterns },
548
+ identifiers: {
549
+ patterns: [
550
+ { name: `variable.other.constant.${SCOPE_SUFFIX}`, match: String.raw`@+\p{XID_Continue}+` },
551
+ { name: `variable.other.${SCOPE_SUFFIX}`, match: IDENTIFIER },
552
+ ],
553
+ },
554
+ operators: {
555
+ patterns: [
556
+ { name: `keyword.operator.spread.${SCOPE_SUFFIX}`, match: String.raw`\.\.<|\.\.` },
557
+ { name: `keyword.operator.bind.${SCOPE_SUFFIX}`, match: '::' },
558
+ { name: `keyword.operator.conditional.${SCOPE_SUFFIX}`, match: String.raw`\?:` },
559
+ {
560
+ name: `keyword.operator.assignment.${SCOPE_SUFFIX}`,
561
+ match: String.raw`&&=|\|\|=|\?\?=|\+=|-=|\*=|/=|%=|\^=|=`,
562
+ },
563
+ {
564
+ name: `keyword.operator.comparison.${SCOPE_SUFFIX}`,
565
+ match: '===|!==|>=|<=|==|!=|=~|!~|>|<',
566
+ },
567
+ { name: `keyword.operator.logical.${SCOPE_SUFFIX}`, match: String.raw`&&|\|\||\?\?|!` },
568
+ { name: `keyword.operator.arithmetic.${SCOPE_SUFFIX}`, match: String.raw`\+|-|\*|/|%|\^` },
569
+ ],
570
+ },
571
+ punctuation: {
572
+ patterns: [
573
+ { name: `punctuation.section.braces.${SCOPE_SUFFIX}`, match: '[{}]' },
574
+ { name: `punctuation.section.brackets.${SCOPE_SUFFIX}`, match: String.raw`[\[\]]` },
575
+ { name: `punctuation.section.parens.${SCOPE_SUFFIX}`, match: '[()]' },
576
+ { name: `punctuation.separator.${SCOPE_SUFFIX}`, match: '[,;:]' },
577
+ { name: `punctuation.accessor.${SCOPE_SUFFIX}`, match: String.raw`\.` },
578
+ ],
579
+ },
580
+ 'braced-content': {
581
+ patterns: [
582
+ { begin: String.raw`\{`, end: String.raw`\}`, patterns: [{ include: '#braced-content' }] },
583
+ { begin: String.raw`\(`, end: String.raw`\)`, patterns: [{ include: '#parenthesized-content' }] },
584
+ { begin: String.raw`\[`, end: String.raw`\]`, patterns: [{ include: '#bracketed-content' }] },
585
+ { include: '#source' },
586
+ ],
587
+ },
588
+ 'interpolation-expression-content': {
589
+ patterns: [
590
+ { begin: String.raw`\(`, end: String.raw`\)`, patterns: [{ include: '#parenthesized-content' }] },
591
+ { begin: String.raw`\{`, end: String.raw`\}`, patterns: [{ include: '#braced-content' }] },
592
+ { begin: String.raw`\[`, end: String.raw`\]`, patterns: [{ include: '#bracketed-content' }] },
593
+ { include: '#comments' },
594
+ { include: '#strings' },
595
+ { include: '#function-declarations' },
596
+ { include: '#module-declarations' },
597
+ { include: '#for-bindings' },
598
+ { include: '#member-access' },
599
+ { include: '#type-keyword' },
600
+ { include: '#keywords' },
601
+ { include: '#function-calls' },
602
+ { include: '#numbers' },
603
+ { include: '#identifiers' },
604
+ { include: '#operators' },
605
+ { include: '#punctuation' },
606
+ ],
607
+ },
608
+ 'parenthesized-content': {
609
+ patterns: [
610
+ { begin: String.raw`\(`, end: String.raw`\)`, patterns: [{ include: '#parenthesized-content' }] },
611
+ { begin: String.raw`\{`, end: String.raw`\}`, patterns: [{ include: '#braced-content' }] },
612
+ { begin: String.raw`\[`, end: String.raw`\]`, patterns: [{ include: '#bracketed-content' }] },
613
+ { include: '#source' },
614
+ ],
615
+ },
616
+ 'bracketed-content': {
617
+ patterns: [
618
+ { begin: String.raw`\[`, end: String.raw`\]`, patterns: [{ include: '#bracketed-content' }] },
619
+ { begin: String.raw`\{`, end: String.raw`\}`, patterns: [{ include: '#braced-content' }] },
620
+ { begin: String.raw`\(`, end: String.raw`\)`, patterns: [{ include: '#parenthesized-content' }] },
621
+ { include: '#source' },
622
+ ],
623
+ },
624
+ };
625
+ }
626
+
627
+ /**
628
+ * Create the ordinary MiraScript TextMate grammar.
629
+ */
630
+ export function createMiraScriptGrammar(): LanguageRegistration {
631
+ return {
632
+ ...mirascriptLanguage,
633
+ patterns: [{ include: '#source' }],
634
+ repository: sourceRepository(),
635
+ injections: {
636
+ [documentationInjectionSelector]: {
637
+ patterns: [{ include: '#documentation' }],
638
+ },
639
+ },
640
+ };
641
+ }
642
+
643
+ /**
644
+ * Create the MiraScript template TextMate grammar.
645
+ */
646
+ export function createMiraScriptTemplateGrammar(): LanguageRegistration {
647
+ return {
648
+ ...mirascriptTemplateLanguage,
649
+ patterns: [
650
+ ...interpolationPatterns(1),
651
+ { name: 'string.unquoted.template.mira', match: '[^$]+' },
652
+ { name: 'string.unquoted.template.mira', match: String.raw`\$` },
653
+ ],
654
+ repository: sourceRepository(),
655
+ };
656
+ }
657
+
658
+ /**
659
+ * Create the generated-document and type-signature TextMate grammar.
660
+ */
661
+ export function createMiraScriptDocGrammar(): LanguageRegistration {
662
+ return {
663
+ ...mirascriptDocLanguage,
664
+ patterns: [{ include: '#doc' }],
665
+ injections: {
666
+ [documentationInjectionSelector]: {
667
+ patterns: [{ include: '#documentation' }],
668
+ },
669
+ },
670
+ repository: {
671
+ ...documentationRepository('source.mira#source'),
672
+ doc: {
673
+ patterns: [
674
+ { include: '#tag' },
675
+ { include: '#global-value' },
676
+ { include: '#global-constants' },
677
+ { include: '#inline-parameter' },
678
+ { include: '#properties' },
679
+ { include: '#inline-label' },
680
+ { include: '#binding-value' },
681
+ { include: '#bindings' },
682
+ { include: '#function-signatures' },
683
+ { include: '#generic-types' },
684
+ { include: '#parameters' },
685
+ { include: '#return-type' },
686
+ { include: '#tag-comment' },
687
+ { include: 'source.mira' },
688
+ ],
689
+ },
690
+ tag: {
691
+ patterns: [
692
+ {
693
+ name: 'meta.documentation.tag.mira',
694
+ contentName: 'meta.documentation.tag.content.mira',
695
+ begin: `(<)(?=${DOC_TAG_CONTENT}>)`,
696
+ beginCaptures: { 1: { name: 'punctuation.definition.tag.begin.mira' } },
697
+ end: '(>)',
698
+ endCaptures: { 1: { name: 'punctuation.definition.tag.end.mira' } },
699
+ patterns: [{ include: '#tag-content' }],
700
+ },
701
+ ],
702
+ },
703
+ 'global-value': {
704
+ patterns: [
705
+ {
706
+ name: 'meta.documentation.global-value.mira',
707
+ begin: String.raw`^(\x00)?(\(global\))(\s+)(${IDENTIFIER})(\s*)(=)`,
708
+ beginCaptures: {
709
+ 2: { name: 'entity.name.label.mira' },
710
+ 4: { name: 'variable.other.mira' },
711
+ 6: { name: 'keyword.operator.assignment.mira' },
712
+ },
713
+ end: '$',
714
+ patterns: [{ include: '#doc-value' }],
715
+ },
716
+ ],
717
+ },
718
+ 'global-constants': {
719
+ patterns: [
720
+ {
721
+ match: String.raw`^(\x00)?(\(global\))(\s+)(${DOC_CONSTANT_IDENTIFIER})(?=\s*(?:=|;|$))`,
722
+ captures: {
723
+ 2: { name: 'entity.name.label.mira' },
724
+ 4: { name: 'variable.other.constant.mira' },
725
+ },
726
+ },
727
+ {
728
+ match: String.raw`^(\x00)?(${DOC_CONSTANT_IDENTIFIER})(?=\s*(?:=|;|$))`,
729
+ captures: { 2: { name: 'variable.other.constant.mira' } },
730
+ },
731
+ ],
732
+ },
733
+ 'inline-parameter': {
734
+ patterns: [
735
+ {
736
+ match: String.raw`^(\x00)?(\(parameter(?:\s+pattern)?\))(\s+)(\.\.)?(mut)(\s+)(${IDENTIFIER})`,
737
+ captures: {
738
+ 2: { name: 'entity.name.label.mira' },
739
+ 4: { name: 'keyword.operator.spread.mira' },
740
+ 5: { name: 'keyword.declaration.mutable.mira' },
741
+ 7: { name: 'variable.emphasis.mira' },
742
+ },
743
+ },
744
+ {
745
+ match: String.raw`^(\x00)?(\(parameter(?:\s+pattern)?\))(\s+)(\.\.)?(\s*)(${IDENTIFIER})`,
746
+ captures: {
747
+ 2: { name: 'entity.name.label.mira' },
748
+ 4: { name: 'keyword.operator.spread.mira' },
749
+ 6: { name: 'variable.other.constant.emphasis.mira' },
750
+ },
751
+ },
752
+ ],
753
+ },
754
+ 'inline-label': {
755
+ patterns: [
756
+ {
757
+ match: String.raw`^(\x00)?(\([^():,\[\]<>|&\r\n]+\))(?=\s+\S)`,
758
+ captures: { 2: { name: 'entity.name.label.mira' } },
759
+ },
760
+ ],
761
+ },
762
+ bindings: {
763
+ patterns: [
764
+ {
765
+ match: String.raw`${IDENTIFIER_START}(let)(\s+)(mut)(\s+)(${IDENTIFIER})`,
766
+ captures: {
767
+ 1: { name: 'keyword.declaration.variable.mira' },
768
+ 3: { name: 'keyword.declaration.mutable.mira' },
769
+ 5: { name: 'variable.other.readwrite.mira' },
770
+ },
771
+ },
772
+ {
773
+ match: String.raw`${IDENTIFIER_START}(let|const)(\s+)(${IDENTIFIER})`,
774
+ captures: {
775
+ 1: { name: 'keyword.declaration.variable.mira' },
776
+ 3: { name: 'variable.other.constant.mira' },
777
+ },
778
+ },
779
+ ],
780
+ },
781
+ 'binding-value': {
782
+ patterns: [
783
+ {
784
+ begin: String.raw`${IDENTIFIER_START}(let)(\s+)(mut)(\s+)(${IDENTIFIER})(\s*)(=)`,
785
+ beginCaptures: {
786
+ 1: { name: 'keyword.declaration.variable.mira' },
787
+ 3: { name: 'keyword.declaration.mutable.mira' },
788
+ 5: { name: 'variable.other.readwrite.mira' },
789
+ 7: { name: 'keyword.operator.assignment.mira' },
790
+ },
791
+ end: '$',
792
+ patterns: [{ include: '#doc-value' }],
793
+ },
794
+ {
795
+ begin: String.raw`${IDENTIFIER_START}(let|const)(\s+)(${IDENTIFIER})(\s*)(=)`,
796
+ beginCaptures: {
797
+ 1: { name: 'keyword.declaration.variable.mira' },
798
+ 3: { name: 'variable.other.constant.mira' },
799
+ 5: { name: 'keyword.operator.assignment.mira' },
800
+ },
801
+ end: '$',
802
+ patterns: [{ include: '#doc-value' }],
803
+ },
804
+ ],
805
+ },
806
+ 'function-signatures': {
807
+ patterns: [
808
+ {
809
+ match: String.raw`${IDENTIFIER_START}(?:(pub)(\s+))?(fn)(\s+)(${IDENTIFIER})(?=\s*(?:<|\())`,
810
+ captures: {
811
+ 1: { name: 'keyword.control.module.mira' },
812
+ 3: { name: 'keyword.declaration.function.mira' },
813
+ 5: { name: 'entity.name.function.mira' },
814
+ },
815
+ },
816
+ ],
817
+ },
818
+ properties: {
819
+ patterns: [
820
+ {
821
+ name: 'meta.documentation.field.mira',
822
+ begin: String.raw`^(\x00)?(?:(\(field\))(\s+))?(${DOC_FIELD_NAME})(\s*)(\??:)(?=[ \t]*/\*[ \t]*<extern[ \t]+(?:(?:async[ \t]+)?function\*?)(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
823
+ beginCaptures: {
824
+ 2: { name: 'entity.name.label.mira' },
825
+ 4: { name: 'entity.name.function.mira' },
826
+ 6: { name: 'punctuation.separator.type.mira' },
827
+ },
828
+ end: '$',
829
+ patterns: [
830
+ { include: '#tag-comment' },
831
+ { include: '#tag' },
832
+ { include: '#doc-record-value' },
833
+ { include: '#doc-array-value' },
834
+ { include: '#type-context' },
835
+ ],
836
+ },
837
+ {
838
+ name: 'meta.documentation.field.mira',
839
+ begin: String.raw`^(\x00)?(?:(\(field\))(\s+))?(${DOC_FIELD_NAME})(\s*)(\??:)(?=[ \t]*/\*[ \t]*<extern[ \t]+class(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
840
+ beginCaptures: {
841
+ 2: { name: 'entity.name.label.mira' },
842
+ 4: { name: 'entity.name.type.mira' },
843
+ 6: { name: 'punctuation.separator.type.mira' },
844
+ },
845
+ end: '$',
846
+ patterns: [
847
+ { include: '#tag-comment' },
848
+ { include: '#tag' },
849
+ { include: '#doc-record-value' },
850
+ { include: '#doc-array-value' },
851
+ { include: '#type-context' },
852
+ ],
853
+ },
854
+ {
855
+ name: 'meta.documentation.field.mira',
856
+ begin: String.raw`^(\x00)?(?:(\(field\))(\s+))?(${DOC_FIELD_NAME})(\s*)(\??:)`,
857
+ beginCaptures: {
858
+ 2: { name: 'entity.name.label.mira' },
859
+ 4: { name: 'variable.other.property.mira' },
860
+ 6: { name: 'punctuation.separator.type.mira' },
861
+ },
862
+ end: '$',
863
+ patterns: [
864
+ { include: '#tag-comment' },
865
+ { include: '#tag' },
866
+ { include: '#doc-record-value' },
867
+ { include: '#doc-array-value' },
868
+ { include: '#type-context' },
869
+ ],
870
+ },
871
+ ],
872
+ },
873
+ 'doc-value': {
874
+ patterns: [
875
+ { include: '#tag-properties' },
876
+ { include: '#tag-comment' },
877
+ { include: '#tag' },
878
+ { include: '#doc-record-value' },
879
+ { include: '#doc-array-value' },
880
+ { include: 'source.mira' },
881
+ ],
882
+ },
883
+ 'doc-record-value': {
884
+ patterns: [
885
+ {
886
+ begin: String.raw`\(`,
887
+ beginCaptures: { 0: { name: 'punctuation.section.parens.begin.mira' } },
888
+ end: String.raw`\)`,
889
+ endCaptures: { 0: { name: 'punctuation.section.parens.end.mira' } },
890
+ patterns: [{ include: '#doc-value' }],
891
+ },
892
+ ],
893
+ },
894
+ 'doc-array-value': {
895
+ patterns: [
896
+ {
897
+ begin: String.raw`\[`,
898
+ beginCaptures: { 0: { name: 'punctuation.section.brackets.begin.mira' } },
899
+ end: String.raw`\]`,
900
+ endCaptures: { 0: { name: 'punctuation.section.brackets.end.mira' } },
901
+ patterns: [{ include: '#doc-value' }],
902
+ },
903
+ ],
904
+ },
905
+ 'tag-properties': {
906
+ patterns: [
907
+ {
908
+ match: String.raw`(${DOC_FIELD_NAME})(\s*)(:)(?=[ \t]*/\*[ \t]*<extern[ \t]+(?:(?:async[ \t]+)?function\*?)(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
909
+ captures: {
910
+ 1: { name: 'entity.name.function.mira' },
911
+ 3: { name: 'punctuation.separator.key-value.mira' },
912
+ },
913
+ },
914
+ {
915
+ match: String.raw`(${DOC_FIELD_NAME})(\s*)(:)(?=[ \t]*/\*[ \t]*<extern[ \t]+class(?:[ \t]+${DOC_TAG_NAME})?>[ \t]*\*/)`,
916
+ captures: {
917
+ 1: { name: 'entity.name.type.mira' },
918
+ 3: { name: 'punctuation.separator.key-value.mira' },
919
+ },
920
+ },
921
+ ],
922
+ },
923
+ 'tag-comment': {
924
+ patterns: [
925
+ {
926
+ name: 'comment.block.mira',
927
+ contentName: 'meta.documentation.tag.mira',
928
+ begin: String.raw`(/\*)([ \t]*)(<)(?=${DOC_TAG_CONTENT}>[ \t]*\*/)`,
929
+ beginCaptures: {
930
+ 1: { name: 'punctuation.definition.comment.begin.mira' },
931
+ 3: { name: 'punctuation.definition.tag.begin.mira' },
932
+ },
933
+ end: String.raw`(>)([ \t]*)(\*/)`,
934
+ endCaptures: {
935
+ 1: { name: 'punctuation.definition.tag.end.mira' },
936
+ 3: { name: 'punctuation.definition.comment.end.mira' },
937
+ },
938
+ patterns: [{ include: '#tag-content' }],
939
+ },
940
+ ],
941
+ },
942
+ 'tag-content': {
943
+ patterns: [
944
+ {
945
+ match: String.raw`(extern)([ \t]+)(?:(async)([ \t]+))?(function)(\*)?(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
946
+ captures: {
947
+ 1: { name: 'keyword.declaration.extern.mira' },
948
+ 3: { name: 'keyword.js' },
949
+ 5: { name: 'keyword.js' },
950
+ 6: { name: 'keyword.operator.generator.js' },
951
+ 8: { name: 'entity.name.function.js' },
952
+ },
953
+ },
954
+ {
955
+ match: String.raw`(extern)([ \t]+)(class)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
956
+ captures: {
957
+ 1: { name: 'keyword.declaration.extern.mira' },
958
+ 3: { name: 'keyword.js' },
959
+ 5: { name: 'entity.name.type.js' },
960
+ },
961
+ },
962
+ {
963
+ match: String.raw`(extern)([ \t]+)(${DOC_TAG_NAME})(\()(${DOC_TAG_NUMBER})(\))(?=>)`,
964
+ captures: {
965
+ 1: { name: 'keyword.declaration.extern.mira' },
966
+ 3: { name: 'entity.name.type.js' },
967
+ 4: { name: 'punctuation.section.parens.begin.mira' },
968
+ 5: { name: 'constant.numeric.mira' },
969
+ 6: { name: 'punctuation.section.parens.end.mira' },
970
+ },
971
+ },
972
+ {
973
+ match: String.raw`(extern)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
974
+ captures: {
975
+ 1: { name: 'keyword.declaration.extern.mira' },
976
+ 3: { name: 'entity.name.type.js' },
977
+ },
978
+ },
979
+ {
980
+ match: String.raw`(module)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
981
+ captures: {
982
+ 1: { name: 'keyword.declaration.module.mira' },
983
+ 3: { name: 'entity.name.namespace.mira' },
984
+ },
985
+ },
986
+ {
987
+ match: String.raw`(function)(?:([ \t]+)(${DOC_TAG_NAME}))?(?=>)`,
988
+ captures: {
989
+ 1: { name: 'keyword.declaration.function.mira' },
990
+ 3: { name: 'entity.name.function.mira' },
991
+ },
992
+ },
993
+ ],
994
+ },
995
+ 'reflection-type': {
996
+ patterns: [
997
+ {
998
+ match: String.raw`${IDENTIFIER_START}(type)(\s*)(\()(\s*)(${IDENTIFIER})(\s*)(\))`,
999
+ captures: {
1000
+ 1: { name: 'support.type.type.mira' },
1001
+ 3: { name: 'punctuation.section.parens.begin.mira' },
1002
+ 5: { name: 'variable.other.mira' },
1003
+ 7: { name: 'punctuation.section.parens.end.mira' },
1004
+ },
1005
+ },
1006
+ ],
1007
+ },
1008
+ 'type-context': {
1009
+ patterns: [
1010
+ { include: '#reflection-type' },
1011
+ { include: '#function-type' },
1012
+ { include: '#generic-types' },
1013
+ { include: '#type-grouping' },
1014
+ { include: '#type-brackets' },
1015
+ { include: '#type-atoms' },
1016
+ ],
1017
+ },
1018
+ 'function-type': {
1019
+ patterns: [
1020
+ {
1021
+ begin: String.raw`${IDENTIFIER_START}(fn)${IDENTIFIER_END}(?=\s*(?:<|\())`,
1022
+ beginCaptures: { 1: { name: 'support.type.function.mira' } },
1023
+ end: String.raw`(?=\s*(?:,|\)|$))`,
1024
+ patterns: [
1025
+ { include: '#generic-types' },
1026
+ { include: '#parameters' },
1027
+ { include: '#return-type' },
1028
+ { include: '#type-context' },
1029
+ ],
1030
+ },
1031
+ ],
1032
+ },
1033
+ 'generic-types': {
1034
+ patterns: [
1035
+ {
1036
+ begin: '<',
1037
+ beginCaptures: { 0: { name: 'punctuation.definition.type-parameters.begin.mira' } },
1038
+ end: '>',
1039
+ endCaptures: { 0: { name: 'punctuation.definition.type-parameters.end.mira' } },
1040
+ patterns: [
1041
+ { include: '#reflection-type' },
1042
+ { include: '#function-type' },
1043
+ { include: '#generic-types' },
1044
+ { include: '#type-grouping' },
1045
+ { include: '#type-brackets' },
1046
+ { include: '#type-atoms' },
1047
+ ],
1048
+ },
1049
+ ],
1050
+ },
1051
+ parameters: {
1052
+ patterns: [
1053
+ {
1054
+ begin: String.raw`\(`,
1055
+ beginCaptures: { 0: { name: 'punctuation.section.parameters.begin.mira' } },
1056
+ end: String.raw`\)`,
1057
+ endCaptures: { 0: { name: 'punctuation.section.parameters.end.mira' } },
1058
+ patterns: [
1059
+ {
1060
+ begin: String.raw`(\.\.)?(\s*)(mut)?(\s*)(${IDENTIFIER})(\s*)(\??:)(?=\s*fn${IDENTIFIER_END})`,
1061
+ beginCaptures: {
1062
+ 1: { name: 'keyword.operator.spread.mira' },
1063
+ 3: { name: 'keyword.declaration.mutable.mira' },
1064
+ 5: { name: 'entity.name.function.emphasis.mira' },
1065
+ 7: { name: 'punctuation.separator.type.mira' },
1066
+ },
1067
+ end: String.raw`(?=,|\))`,
1068
+ patterns: [{ include: '#type-context' }],
1069
+ },
1070
+ {
1071
+ begin: String.raw`(\.\.)?(\s*)(mut)?(\s*)(${IDENTIFIER})(\s*)(\??:)`,
1072
+ beginCaptures: {
1073
+ 1: { name: 'keyword.operator.spread.mira' },
1074
+ 3: { name: 'keyword.declaration.mutable.mira' },
1075
+ 5: { name: 'variable.emphasis.mira' },
1076
+ 7: { name: 'punctuation.separator.type.mira' },
1077
+ },
1078
+ end: String.raw`(?=,|\))`,
1079
+ patterns: [{ include: '#type-context' }],
1080
+ },
1081
+ {
1082
+ match: String.raw`(\.\.)?(\s*)(mut)(\s+)(${IDENTIFIER})`,
1083
+ captures: {
1084
+ 1: { name: 'keyword.operator.spread.mira' },
1085
+ 3: { name: 'keyword.declaration.mutable.mira' },
1086
+ 5: { name: 'variable.emphasis.mira' },
1087
+ },
1088
+ },
1089
+ { name: 'keyword.operator.spread.mira', match: String.raw`\.\.` },
1090
+ { name: 'variable.emphasis.mira', match: IDENTIFIER },
1091
+ { name: 'punctuation.separator.parameter.mira', match: ',' },
1092
+ ],
1093
+ },
1094
+ ],
1095
+ },
1096
+ 'type-grouping': {
1097
+ patterns: [
1098
+ {
1099
+ begin: String.raw`\(`,
1100
+ beginCaptures: { 0: { name: 'punctuation.section.parens.begin.mira' } },
1101
+ end: String.raw`\)`,
1102
+ endCaptures: { 0: { name: 'punctuation.section.parens.end.mira' } },
1103
+ patterns: [
1104
+ {
1105
+ begin: String.raw`(${IDENTIFIER})(\s*)(\??:)`,
1106
+ beginCaptures: {
1107
+ 1: { name: 'variable.other.property.mira' },
1108
+ 3: { name: 'punctuation.separator.type.mira' },
1109
+ },
1110
+ end: String.raw`(?=,|\))`,
1111
+ patterns: [{ include: '#type-context' }],
1112
+ },
1113
+ { include: '#type-context' },
1114
+ ],
1115
+ },
1116
+ ],
1117
+ },
1118
+ 'type-brackets': {
1119
+ patterns: [
1120
+ {
1121
+ begin: String.raw`\[`,
1122
+ beginCaptures: { 0: { name: 'punctuation.section.brackets.begin.mira' } },
1123
+ end: String.raw`\]`,
1124
+ endCaptures: { 0: { name: 'punctuation.section.brackets.end.mira' } },
1125
+ patterns: [{ include: '#type-context' }],
1126
+ },
1127
+ ],
1128
+ },
1129
+ 'return-type': {
1130
+ patterns: [
1131
+ {
1132
+ begin: '->',
1133
+ beginCaptures: { 0: { name: 'keyword.operator.type.mira' } },
1134
+ end: String.raw`(?=,|\)|$)`,
1135
+ patterns: [{ include: '#type-context' }],
1136
+ },
1137
+ ],
1138
+ },
1139
+ 'type-atoms': {
1140
+ patterns: [
1141
+ { include: '#reflection-type' },
1142
+ {
1143
+ name: 'support.type.builtin.mira',
1144
+ match: `${IDENTIFIER_START}(?:${alternatives(BUILT_IN_TYPES)})${IDENTIFIER_END}`,
1145
+ },
1146
+ { name: 'keyword.operator.type.mira', match: '[&|]' },
1147
+ { name: 'keyword.operator.spread.mira', match: String.raw`\.\.` },
1148
+ { name: 'entity.name.type.mira', match: IDENTIFIER },
1149
+ { name: 'punctuation.section.brackets.mira', match: String.raw`[\[\]]` },
1150
+ { name: 'punctuation.separator.type.mira', match: '[,.?:]' },
1151
+ { include: 'source.mira#strings' },
1152
+ { include: 'source.mira#numbers' },
1153
+ ],
1154
+ },
1155
+ },
1156
+ };
1157
+ }