]> luflow.net public git repositories - flow-web.git/blob - static/highlight/es/languages/swift.js
Initial commit.
[flow-web.git] / static / highlight / es / languages / swift.js
1 /*! `swift` grammar compiled for Highlight.js 11.11.1 */
2 var hljsGrammar = (function () {
3 'use strict';
4
5 /**
6 * @param {string} value
7 * @returns {RegExp}
8 * */
9
10 /**
11 * @param {RegExp | string } re
12 * @returns {string}
13 */
14 function source(re) {
15 if (!re) return null;
16 if (typeof re === "string") return re;
17
18 return re.source;
19 }
20
21 /**
22 * @param {RegExp | string } re
23 * @returns {string}
24 */
25 function lookahead(re) {
26 return concat('(?=', re, ')');
27 }
28
29 /**
30 * @param {...(RegExp | string) } args
31 * @returns {string}
32 */
33 function concat(...args) {
34 const joined = args.map((x) => source(x)).join("");
35 return joined;
36 }
37
38 /**
39 * @param { Array<string | RegExp | Object> } args
40 * @returns {object}
41 */
42 function stripOptionsFromArgs(args) {
43 const opts = args[args.length - 1];
44
45 if (typeof opts === 'object' && opts.constructor === Object) {
46 args.splice(args.length - 1, 1);
47 return opts;
48 } else {
49 return {};
50 }
51 }
52
53 /** @typedef { {capture?: boolean} } RegexEitherOptions */
54
55 /**
56 * Any of the passed expresssions may match
57 *
58 * Creates a huge this | this | that | that match
59 * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args
60 * @returns {string}
61 */
62 function either(...args) {
63 /** @type { object & {capture?: boolean} } */
64 const opts = stripOptionsFromArgs(args);
65 const joined = '('
66 + (opts.capture ? "" : "?:")
67 + args.map((x) => source(x)).join("|") + ")";
68 return joined;
69 }
70
71 const keywordWrapper = keyword => concat(
72 /\b/,
73 keyword,
74 /\w$/.test(keyword) ? /\b/ : /\B/
75 );
76
77 // Keywords that require a leading dot.
78 const dotKeywords = [
79 'Protocol', // contextual
80 'Type' // contextual
81 ].map(keywordWrapper);
82
83 // Keywords that may have a leading dot.
84 const optionalDotKeywords = [
85 'init',
86 'self'
87 ].map(keywordWrapper);
88
89 // should register as keyword, not type
90 const keywordTypes = [
91 'Any',
92 'Self'
93 ];
94
95 // Regular keywords and literals.
96 const keywords = [
97 // strings below will be fed into the regular `keywords` engine while regex
98 // will result in additional modes being created to scan for those keywords to
99 // avoid conflicts with other rules
100 'actor',
101 'any', // contextual
102 'associatedtype',
103 'async',
104 'await',
105 /as\?/, // operator
106 /as!/, // operator
107 'as', // operator
108 'borrowing', // contextual
109 'break',
110 'case',
111 'catch',
112 'class',
113 'consume', // contextual
114 'consuming', // contextual
115 'continue',
116 'convenience', // contextual
117 'copy', // contextual
118 'default',
119 'defer',
120 'deinit',
121 'didSet', // contextual
122 'distributed',
123 'do',
124 'dynamic', // contextual
125 'each',
126 'else',
127 'enum',
128 'extension',
129 'fallthrough',
130 /fileprivate\(set\)/,
131 'fileprivate',
132 'final', // contextual
133 'for',
134 'func',
135 'get', // contextual
136 'guard',
137 'if',
138 'import',
139 'indirect', // contextual
140 'infix', // contextual
141 /init\?/,
142 /init!/,
143 'inout',
144 /internal\(set\)/,
145 'internal',
146 'in',
147 'is', // operator
148 'isolated', // contextual
149 'nonisolated', // contextual
150 'lazy', // contextual
151 'let',
152 'macro',
153 'mutating', // contextual
154 'nonmutating', // contextual
155 /open\(set\)/, // contextual
156 'open', // contextual
157 'operator',
158 'optional', // contextual
159 'override', // contextual
160 'package',
161 'postfix', // contextual
162 'precedencegroup',
163 'prefix', // contextual
164 /private\(set\)/,
165 'private',
166 'protocol',
167 /public\(set\)/,
168 'public',
169 'repeat',
170 'required', // contextual
171 'rethrows',
172 'return',
173 'set', // contextual
174 'some', // contextual
175 'static',
176 'struct',
177 'subscript',
178 'super',
179 'switch',
180 'throws',
181 'throw',
182 /try\?/, // operator
183 /try!/, // operator
184 'try', // operator
185 'typealias',
186 /unowned\(safe\)/, // contextual
187 /unowned\(unsafe\)/, // contextual
188 'unowned', // contextual
189 'var',
190 'weak', // contextual
191 'where',
192 'while',
193 'willSet' // contextual
194 ];
195
196 // NOTE: Contextual keywords are reserved only in specific contexts.
197 // Ideally, these should be matched using modes to avoid false positives.
198
199 // Literals.
200 const literals = [
201 'false',
202 'nil',
203 'true'
204 ];
205
206 // Keywords used in precedence groups.
207 const precedencegroupKeywords = [
208 'assignment',
209 'associativity',
210 'higherThan',
211 'left',
212 'lowerThan',
213 'none',
214 'right'
215 ];
216
217 // Keywords that start with a number sign (#).
218 // #(un)available is handled separately.
219 const numberSignKeywords = [
220 '#colorLiteral',
221 '#column',
222 '#dsohandle',
223 '#else',
224 '#elseif',
225 '#endif',
226 '#error',
227 '#file',
228 '#fileID',
229 '#fileLiteral',
230 '#filePath',
231 '#function',
232 '#if',
233 '#imageLiteral',
234 '#keyPath',
235 '#line',
236 '#selector',
237 '#sourceLocation',
238 '#warning'
239 ];
240
241 // Global functions in the Standard Library.
242 const builtIns = [
243 'abs',
244 'all',
245 'any',
246 'assert',
247 'assertionFailure',
248 'debugPrint',
249 'dump',
250 'fatalError',
251 'getVaList',
252 'isKnownUniquelyReferenced',
253 'max',
254 'min',
255 'numericCast',
256 'pointwiseMax',
257 'pointwiseMin',
258 'precondition',
259 'preconditionFailure',
260 'print',
261 'readLine',
262 'repeatElement',
263 'sequence',
264 'stride',
265 'swap',
266 'swift_unboxFromSwiftValueWithType',
267 'transcode',
268 'type',
269 'unsafeBitCast',
270 'unsafeDowncast',
271 'withExtendedLifetime',
272 'withUnsafeMutablePointer',
273 'withUnsafePointer',
274 'withVaList',
275 'withoutActuallyEscaping',
276 'zip'
277 ];
278
279 // Valid first characters for operators.
280 const operatorHead = either(
281 /[/=\-+!*%<>&|^~?]/,
282 /[\u00A1-\u00A7]/,
283 /[\u00A9\u00AB]/,
284 /[\u00AC\u00AE]/,
285 /[\u00B0\u00B1]/,
286 /[\u00B6\u00BB\u00BF\u00D7\u00F7]/,
287 /[\u2016-\u2017]/,
288 /[\u2020-\u2027]/,
289 /[\u2030-\u203E]/,
290 /[\u2041-\u2053]/,
291 /[\u2055-\u205E]/,
292 /[\u2190-\u23FF]/,
293 /[\u2500-\u2775]/,
294 /[\u2794-\u2BFF]/,
295 /[\u2E00-\u2E7F]/,
296 /[\u3001-\u3003]/,
297 /[\u3008-\u3020]/,
298 /[\u3030]/
299 );
300
301 // Valid characters for operators.
302 const operatorCharacter = either(
303 operatorHead,
304 /[\u0300-\u036F]/,
305 /[\u1DC0-\u1DFF]/,
306 /[\u20D0-\u20FF]/,
307 /[\uFE00-\uFE0F]/,
308 /[\uFE20-\uFE2F]/
309 // TODO: The following characters are also allowed, but the regex isn't supported yet.
310 // /[\u{E0100}-\u{E01EF}]/u
311 );
312
313 // Valid operator.
314 const operator = concat(operatorHead, operatorCharacter, '*');
315
316 // Valid first characters for identifiers.
317 const identifierHead = either(
318 /[a-zA-Z_]/,
319 /[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,
320 /[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,
321 /[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,
322 /[\u1E00-\u1FFF]/,
323 /[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,
324 /[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,
325 /[\u2C00-\u2DFF\u2E80-\u2FFF]/,
326 /[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,
327 /[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,
328 /[\uFE47-\uFEFE\uFF00-\uFFFD]/ // Should be /[\uFE47-\uFFFD]/, but we have to exclude FEFF.
329 // The following characters are also allowed, but the regexes aren't supported yet.
330 // /[\u{10000}-\u{1FFFD}\u{20000-\u{2FFFD}\u{30000}-\u{3FFFD}\u{40000}-\u{4FFFD}]/u,
331 // /[\u{50000}-\u{5FFFD}\u{60000-\u{6FFFD}\u{70000}-\u{7FFFD}\u{80000}-\u{8FFFD}]/u,
332 // /[\u{90000}-\u{9FFFD}\u{A0000-\u{AFFFD}\u{B0000}-\u{BFFFD}\u{C0000}-\u{CFFFD}]/u,
333 // /[\u{D0000}-\u{DFFFD}\u{E0000-\u{EFFFD}]/u
334 );
335
336 // Valid characters for identifiers.
337 const identifierCharacter = either(
338 identifierHead,
339 /\d/,
340 /[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/
341 );
342
343 // Valid identifier.
344 const identifier = concat(identifierHead, identifierCharacter, '*');
345
346 // Valid type identifier.
347 const typeIdentifier = concat(/[A-Z]/, identifierCharacter, '*');
348
349 // Built-in attributes, which are highlighted as keywords.
350 // @available is handled separately.
351 // https://docs.swift.org/swift-book/documentation/the-swift-programming-language/attributes
352 const keywordAttributes = [
353 'attached',
354 'autoclosure',
355 concat(/convention\(/, either('swift', 'block', 'c'), /\)/),
356 'discardableResult',
357 'dynamicCallable',
358 'dynamicMemberLookup',
359 'escaping',
360 'freestanding',
361 'frozen',
362 'GKInspectable',
363 'IBAction',
364 'IBDesignable',
365 'IBInspectable',
366 'IBOutlet',
367 'IBSegueAction',
368 'inlinable',
369 'main',
370 'nonobjc',
371 'NSApplicationMain',
372 'NSCopying',
373 'NSManaged',
374 concat(/objc\(/, identifier, /\)/),
375 'objc',
376 'objcMembers',
377 'propertyWrapper',
378 'requires_stored_property_inits',
379 'resultBuilder',
380 'Sendable',
381 'testable',
382 'UIApplicationMain',
383 'unchecked',
384 'unknown',
385 'usableFromInline',
386 'warn_unqualified_access'
387 ];
388
389 // Contextual keywords used in @available and #(un)available.
390 const availabilityKeywords = [
391 'iOS',
392 'iOSApplicationExtension',
393 'macOS',
394 'macOSApplicationExtension',
395 'macCatalyst',
396 'macCatalystApplicationExtension',
397 'watchOS',
398 'watchOSApplicationExtension',
399 'tvOS',
400 'tvOSApplicationExtension',
401 'swift'
402 ];
403
404 /*
405 Language: Swift
406 Description: Swift is a general-purpose programming language built using a modern approach to safety, performance, and software design patterns.
407 Author: Steven Van Impe <steven.vanimpe@icloud.com>
408 Contributors: Chris Eidhof <chris@eidhof.nl>, Nate Cook <natecook@gmail.com>, Alexander Lichter <manniL@gmx.net>, Richard Gibson <gibson042@github>
409 Website: https://swift.org
410 Category: common, system
411 */
412
413
414 /** @type LanguageFn */
415 function swift(hljs) {
416 const WHITESPACE = {
417 match: /\s+/,
418 relevance: 0
419 };
420 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID411
421 const BLOCK_COMMENT = hljs.COMMENT(
422 '/\\*',
423 '\\*/',
424 { contains: [ 'self' ] }
425 );
426 const COMMENTS = [
427 hljs.C_LINE_COMMENT_MODE,
428 BLOCK_COMMENT
429 ];
430
431 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID413
432 // https://docs.swift.org/swift-book/ReferenceManual/zzSummaryOfTheGrammar.html
433 const DOT_KEYWORD = {
434 match: [
435 /\./,
436 either(...dotKeywords, ...optionalDotKeywords)
437 ],
438 className: { 2: "keyword" }
439 };
440 const KEYWORD_GUARD = {
441 // Consume .keyword to prevent highlighting properties and methods as keywords.
442 match: concat(/\./, either(...keywords)),
443 relevance: 0
444 };
445 const PLAIN_KEYWORDS = keywords
446 .filter(kw => typeof kw === 'string')
447 .concat([ "_|0" ]); // seems common, so 0 relevance
448 const REGEX_KEYWORDS = keywords
449 .filter(kw => typeof kw !== 'string') // find regex
450 .concat(keywordTypes)
451 .map(keywordWrapper);
452 const KEYWORD = { variants: [
453 {
454 className: 'keyword',
455 match: either(...REGEX_KEYWORDS, ...optionalDotKeywords)
456 }
457 ] };
458 // find all the regular keywords
459 const KEYWORDS = {
460 $pattern: either(
461 /\b\w+/, // regular keywords
462 /#\w+/ // number keywords
463 ),
464 keyword: PLAIN_KEYWORDS
465 .concat(numberSignKeywords),
466 literal: literals
467 };
468 const KEYWORD_MODES = [
469 DOT_KEYWORD,
470 KEYWORD_GUARD,
471 KEYWORD
472 ];
473
474 // https://github.com/apple/swift/tree/main/stdlib/public/core
475 const BUILT_IN_GUARD = {
476 // Consume .built_in to prevent highlighting properties and methods.
477 match: concat(/\./, either(...builtIns)),
478 relevance: 0
479 };
480 const BUILT_IN = {
481 className: 'built_in',
482 match: concat(/\b/, either(...builtIns), /(?=\()/)
483 };
484 const BUILT_INS = [
485 BUILT_IN_GUARD,
486 BUILT_IN
487 ];
488
489 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418
490 const OPERATOR_GUARD = {
491 // Prevent -> from being highlighting as an operator.
492 match: /->/,
493 relevance: 0
494 };
495 const OPERATOR = {
496 className: 'operator',
497 relevance: 0,
498 variants: [
499 { match: operator },
500 {
501 // dot-operator: only operators that start with a dot are allowed to use dots as
502 // characters (..., ...<, .*, etc). So there rule here is: a dot followed by one or more
503 // characters that may also include dots.
504 match: `\\.(\\.|${operatorCharacter})+` }
505 ]
506 };
507 const OPERATORS = [
508 OPERATOR_GUARD,
509 OPERATOR
510 ];
511
512 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_numeric-literal
513 // TODO: Update for leading `-` after lookbehind is supported everywhere
514 const decimalDigits = '([0-9]_*)+';
515 const hexDigits = '([0-9a-fA-F]_*)+';
516 const NUMBER = {
517 className: 'number',
518 relevance: 0,
519 variants: [
520 // decimal floating-point-literal (subsumes decimal-literal)
521 { match: `\\b(${decimalDigits})(\\.(${decimalDigits}))?` + `([eE][+-]?(${decimalDigits}))?\\b` },
522 // hexadecimal floating-point-literal (subsumes hexadecimal-literal)
523 { match: `\\b0x(${hexDigits})(\\.(${hexDigits}))?` + `([pP][+-]?(${decimalDigits}))?\\b` },
524 // octal-literal
525 { match: /\b0o([0-7]_*)+\b/ },
526 // binary-literal
527 { match: /\b0b([01]_*)+\b/ }
528 ]
529 };
530
531 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_string-literal
532 const ESCAPED_CHARACTER = (rawDelimiter = "") => ({
533 className: 'subst',
534 variants: [
535 { match: concat(/\\/, rawDelimiter, /[0\\tnr"']/) },
536 { match: concat(/\\/, rawDelimiter, /u\{[0-9a-fA-F]{1,8}\}/) }
537 ]
538 });
539 const ESCAPED_NEWLINE = (rawDelimiter = "") => ({
540 className: 'subst',
541 match: concat(/\\/, rawDelimiter, /[\t ]*(?:[\r\n]|\r\n)/)
542 });
543 const INTERPOLATION = (rawDelimiter = "") => ({
544 className: 'subst',
545 label: "interpol",
546 begin: concat(/\\/, rawDelimiter, /\(/),
547 end: /\)/
548 });
549 const MULTILINE_STRING = (rawDelimiter = "") => ({
550 begin: concat(rawDelimiter, /"""/),
551 end: concat(/"""/, rawDelimiter),
552 contains: [
553 ESCAPED_CHARACTER(rawDelimiter),
554 ESCAPED_NEWLINE(rawDelimiter),
555 INTERPOLATION(rawDelimiter)
556 ]
557 });
558 const SINGLE_LINE_STRING = (rawDelimiter = "") => ({
559 begin: concat(rawDelimiter, /"/),
560 end: concat(/"/, rawDelimiter),
561 contains: [
562 ESCAPED_CHARACTER(rawDelimiter),
563 INTERPOLATION(rawDelimiter)
564 ]
565 });
566 const STRING = {
567 className: 'string',
568 variants: [
569 MULTILINE_STRING(),
570 MULTILINE_STRING("#"),
571 MULTILINE_STRING("##"),
572 MULTILINE_STRING("###"),
573 SINGLE_LINE_STRING(),
574 SINGLE_LINE_STRING("#"),
575 SINGLE_LINE_STRING("##"),
576 SINGLE_LINE_STRING("###")
577 ]
578 };
579
580 const REGEXP_CONTENTS = [
581 hljs.BACKSLASH_ESCAPE,
582 {
583 begin: /\[/,
584 end: /\]/,
585 relevance: 0,
586 contains: [ hljs.BACKSLASH_ESCAPE ]
587 }
588 ];
589
590 const BARE_REGEXP_LITERAL = {
591 begin: /\/[^\s](?=[^/\n]*\/)/,
592 end: /\//,
593 contains: REGEXP_CONTENTS
594 };
595
596 const EXTENDED_REGEXP_LITERAL = (rawDelimiter) => {
597 const begin = concat(rawDelimiter, /\//);
598 const end = concat(/\//, rawDelimiter);
599 return {
600 begin,
601 end,
602 contains: [
603 ...REGEXP_CONTENTS,
604 {
605 scope: "comment",
606 begin: `#(?!.*${end})`,
607 end: /$/,
608 },
609 ],
610 };
611 };
612
613 // https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure/#Regular-Expression-Literals
614 const REGEXP = {
615 scope: "regexp",
616 variants: [
617 EXTENDED_REGEXP_LITERAL('###'),
618 EXTENDED_REGEXP_LITERAL('##'),
619 EXTENDED_REGEXP_LITERAL('#'),
620 BARE_REGEXP_LITERAL
621 ]
622 };
623
624 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID412
625 const QUOTED_IDENTIFIER = { match: concat(/`/, identifier, /`/) };
626 const IMPLICIT_PARAMETER = {
627 className: 'variable',
628 match: /\$\d+/
629 };
630 const PROPERTY_WRAPPER_PROJECTION = {
631 className: 'variable',
632 match: `\\$${identifierCharacter}+`
633 };
634 const IDENTIFIERS = [
635 QUOTED_IDENTIFIER,
636 IMPLICIT_PARAMETER,
637 PROPERTY_WRAPPER_PROJECTION
638 ];
639
640 // https://docs.swift.org/swift-book/ReferenceManual/Attributes.html
641 const AVAILABLE_ATTRIBUTE = {
642 match: /(@|#(un)?)available/,
643 scope: 'keyword',
644 starts: { contains: [
645 {
646 begin: /\(/,
647 end: /\)/,
648 keywords: availabilityKeywords,
649 contains: [
650 ...OPERATORS,
651 NUMBER,
652 STRING
653 ]
654 }
655 ] }
656 };
657
658 const KEYWORD_ATTRIBUTE = {
659 scope: 'keyword',
660 match: concat(/@/, either(...keywordAttributes), lookahead(either(/\(/, /\s+/))),
661 };
662
663 const USER_DEFINED_ATTRIBUTE = {
664 scope: 'meta',
665 match: concat(/@/, identifier)
666 };
667
668 const ATTRIBUTES = [
669 AVAILABLE_ATTRIBUTE,
670 KEYWORD_ATTRIBUTE,
671 USER_DEFINED_ATTRIBUTE
672 ];
673
674 // https://docs.swift.org/swift-book/ReferenceManual/Types.html
675 const TYPE = {
676 match: lookahead(/\b[A-Z]/),
677 relevance: 0,
678 contains: [
679 { // Common Apple frameworks, for relevance boost
680 className: 'type',
681 match: concat(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/, identifierCharacter, '+')
682 },
683 { // Type identifier
684 className: 'type',
685 match: typeIdentifier,
686 relevance: 0
687 },
688 { // Optional type
689 match: /[?!]+/,
690 relevance: 0
691 },
692 { // Variadic parameter
693 match: /\.\.\./,
694 relevance: 0
695 },
696 { // Protocol composition
697 match: concat(/\s+&\s+/, lookahead(typeIdentifier)),
698 relevance: 0
699 }
700 ]
701 };
702 const GENERIC_ARGUMENTS = {
703 begin: /</,
704 end: />/,
705 keywords: KEYWORDS,
706 contains: [
707 ...COMMENTS,
708 ...KEYWORD_MODES,
709 ...ATTRIBUTES,
710 OPERATOR_GUARD,
711 TYPE
712 ]
713 };
714 TYPE.contains.push(GENERIC_ARGUMENTS);
715
716 // https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#ID552
717 // Prevents element names from being highlighted as keywords.
718 const TUPLE_ELEMENT_NAME = {
719 match: concat(identifier, /\s*:/),
720 keywords: "_|0",
721 relevance: 0
722 };
723 // Matches tuples as well as the parameter list of a function type.
724 const TUPLE = {
725 begin: /\(/,
726 end: /\)/,
727 relevance: 0,
728 keywords: KEYWORDS,
729 contains: [
730 'self',
731 TUPLE_ELEMENT_NAME,
732 ...COMMENTS,
733 REGEXP,
734 ...KEYWORD_MODES,
735 ...BUILT_INS,
736 ...OPERATORS,
737 NUMBER,
738 STRING,
739 ...IDENTIFIERS,
740 ...ATTRIBUTES,
741 TYPE
742 ]
743 };
744
745 const GENERIC_PARAMETERS = {
746 begin: /</,
747 end: />/,
748 keywords: 'repeat each',
749 contains: [
750 ...COMMENTS,
751 TYPE
752 ]
753 };
754 const FUNCTION_PARAMETER_NAME = {
755 begin: either(
756 lookahead(concat(identifier, /\s*:/)),
757 lookahead(concat(identifier, /\s+/, identifier, /\s*:/))
758 ),
759 end: /:/,
760 relevance: 0,
761 contains: [
762 {
763 className: 'keyword',
764 match: /\b_\b/
765 },
766 {
767 className: 'params',
768 match: identifier
769 }
770 ]
771 };
772 const FUNCTION_PARAMETERS = {
773 begin: /\(/,
774 end: /\)/,
775 keywords: KEYWORDS,
776 contains: [
777 FUNCTION_PARAMETER_NAME,
778 ...COMMENTS,
779 ...KEYWORD_MODES,
780 ...OPERATORS,
781 NUMBER,
782 STRING,
783 ...ATTRIBUTES,
784 TYPE,
785 TUPLE
786 ],
787 endsParent: true,
788 illegal: /["']/
789 };
790 // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID362
791 // https://docs.swift.org/swift-book/documentation/the-swift-programming-language/declarations/#Macro-Declaration
792 const FUNCTION_OR_MACRO = {
793 match: [
794 /(func|macro)/,
795 /\s+/,
796 either(QUOTED_IDENTIFIER.match, identifier, operator)
797 ],
798 className: {
799 1: "keyword",
800 3: "title.function"
801 },
802 contains: [
803 GENERIC_PARAMETERS,
804 FUNCTION_PARAMETERS,
805 WHITESPACE
806 ],
807 illegal: [
808 /\[/,
809 /%/
810 ]
811 };
812
813 // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID375
814 // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID379
815 const INIT_SUBSCRIPT = {
816 match: [
817 /\b(?:subscript|init[?!]?)/,
818 /\s*(?=[<(])/,
819 ],
820 className: { 1: "keyword" },
821 contains: [
822 GENERIC_PARAMETERS,
823 FUNCTION_PARAMETERS,
824 WHITESPACE
825 ],
826 illegal: /\[|%/
827 };
828 // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID380
829 const OPERATOR_DECLARATION = {
830 match: [
831 /operator/,
832 /\s+/,
833 operator
834 ],
835 className: {
836 1: "keyword",
837 3: "title"
838 }
839 };
840
841 // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID550
842 const PRECEDENCEGROUP = {
843 begin: [
844 /precedencegroup/,
845 /\s+/,
846 typeIdentifier
847 ],
848 className: {
849 1: "keyword",
850 3: "title"
851 },
852 contains: [ TYPE ],
853 keywords: [
854 ...precedencegroupKeywords,
855 ...literals
856 ],
857 end: /}/
858 };
859
860 const CLASS_FUNC_DECLARATION = {
861 match: [
862 /class\b/,
863 /\s+/,
864 /func\b/,
865 /\s+/,
866 /\b[A-Za-z_][A-Za-z0-9_]*\b/
867 ],
868 scope: {
869 1: "keyword",
870 3: "keyword",
871 5: "title.function"
872 }
873 };
874
875 const CLASS_VAR_DECLARATION = {
876 match: [
877 /class\b/,
878 /\s+/,
879 /var\b/,
880 ],
881 scope: {
882 1: "keyword",
883 3: "keyword"
884 }
885 };
886
887 const TYPE_DECLARATION = {
888 begin: [
889 /(struct|protocol|class|extension|enum|actor)/,
890 /\s+/,
891 identifier,
892 /\s*/,
893 ],
894 beginScope: {
895 1: "keyword",
896 3: "title.class"
897 },
898 keywords: KEYWORDS,
899 contains: [
900 GENERIC_PARAMETERS,
901 ...KEYWORD_MODES,
902 {
903 begin: /:/,
904 end: /\{/,
905 keywords: KEYWORDS,
906 contains: [
907 {
908 scope: "title.class.inherited",
909 match: typeIdentifier,
910 },
911 ...KEYWORD_MODES,
912 ],
913 relevance: 0,
914 },
915 ]
916 };
917
918 // Add supported submodes to string interpolation.
919 for (const variant of STRING.variants) {
920 const interpolation = variant.contains.find(mode => mode.label === "interpol");
921 // TODO: Interpolation can contain any expression, so there's room for improvement here.
922 interpolation.keywords = KEYWORDS;
923 const submodes = [
924 ...KEYWORD_MODES,
925 ...BUILT_INS,
926 ...OPERATORS,
927 NUMBER,
928 STRING,
929 ...IDENTIFIERS
930 ];
931 interpolation.contains = [
932 ...submodes,
933 {
934 begin: /\(/,
935 end: /\)/,
936 contains: [
937 'self',
938 ...submodes
939 ]
940 }
941 ];
942 }
943
944 return {
945 name: 'Swift',
946 keywords: KEYWORDS,
947 contains: [
948 ...COMMENTS,
949 FUNCTION_OR_MACRO,
950 INIT_SUBSCRIPT,
951 CLASS_FUNC_DECLARATION,
952 CLASS_VAR_DECLARATION,
953 TYPE_DECLARATION,
954 OPERATOR_DECLARATION,
955 PRECEDENCEGROUP,
956 {
957 beginKeywords: 'import',
958 end: /$/,
959 contains: [ ...COMMENTS ],
960 relevance: 0
961 },
962 REGEXP,
963 ...KEYWORD_MODES,
964 ...BUILT_INS,
965 ...OPERATORS,
966 NUMBER,
967 STRING,
968 ...IDENTIFIERS,
969 ...ATTRIBUTES,
970 TYPE,
971 TUPLE
972 ]
973 };
974 }
975
976 return swift;
977
978 })();
979 ;
980 export default hljsGrammar;