@mirascript/textmate 0.1.81 → 0.1.83

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