1 /*! `swift` grammar compiled for Highlight.js 11.11.1 */
2 var hljsGrammar
= (function () {
6 * @param {string} value
11 * @param {RegExp | string } re
16 if (typeof re
=== "string") return re
;
22 * @param {RegExp | string } re
25 function lookahead(re
) {
26 return concat('(?=', re
, ')');
30 * @param {...(RegExp | string) } args
33 function concat(...args
) {
34 const joined
= args
.map((x
) => source(x
)).join("");
39 * @param { Array<string | RegExp | Object> } args
42 function stripOptionsFromArgs(args
) {
43 const opts
= args
[args
.length
- 1];
45 if (typeof opts
=== 'object' && opts
.constructor === Object
) {
46 args
.splice(args
.length
- 1, 1);
53 /** @typedef { {capture?: boolean} } RegexEitherOptions */
56 * Any of the passed expresssions may match
58 * Creates a huge this | this | that | that match
59 * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args
62 function either(...args
) {
63 /** @type { object & {capture?: boolean} } */
64 const opts
= stripOptionsFromArgs(args
);
66 + (opts
.capture
? "" : "?:")
67 + args
.map((x
) => source(x
)).join("|") + ")";
71 const keywordWrapper
= keyword
=> concat(
74 /\w$/.test(keyword
) ? /\b/ : /\B/
77 // Keywords that require a leading dot.
79 'Protocol', // contextual
81 ].map(keywordWrapper
);
83 // Keywords that may have a leading dot.
84 const optionalDotKeywords
= [
87 ].map(keywordWrapper
);
89 // should register as keyword, not type
90 const keywordTypes
= [
95 // Regular keywords and literals.
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
108 'borrowing', // contextual
113 'consume', // contextual
114 'consuming', // contextual
116 'convenience', // contextual
117 'copy', // contextual
121 'didSet', // contextual
124 'dynamic', // contextual
130 /fileprivate\(set\)/,
132 'final', // contextual
139 'indirect', // contextual
140 'infix', // contextual
148 'isolated', // contextual
149 'nonisolated', // contextual
150 'lazy', // contextual
153 'mutating', // contextual
154 'nonmutating', // contextual
155 /open\(set\)/, // contextual
156 'open', // contextual
158 'optional', // contextual
159 'override', // contextual
161 'postfix', // contextual
163 'prefix', // contextual
170 'required', // contextual
174 'some', // contextual
186 /unowned\(safe\)/, // contextual
187 /unowned\(unsafe\)/, // contextual
188 'unowned', // contextual
190 'weak', // contextual
193 'willSet' // contextual
196 // NOTE: Contextual keywords are reserved only in specific contexts.
197 // Ideally, these should be matched using modes to avoid false positives.
206 // Keywords used in precedence groups.
207 const precedencegroupKeywords
= [
217 // Keywords that start with a number sign (#).
218 // #(un)available is handled separately.
219 const numberSignKeywords
= [
241 // Global functions in the Standard Library.
252 'isKnownUniquelyReferenced',
259 'preconditionFailure',
266 'swift_unboxFromSwiftValueWithType',
271 'withExtendedLifetime',
272 'withUnsafeMutablePointer',
275 'withoutActuallyEscaping',
279 // Valid first characters for operators.
280 const operatorHead
= either(
286 /[\u00B6\u00BB\u00BF\u00D7\u00F7]/,
301 // Valid characters for operators.
302 const operatorCharacter
= either(
309 // TODO: The following characters are also allowed, but the regex isn't supported yet.
310 // /[\u{E0100}-\u{E01EF}]/u
314 const operator
= concat(operatorHead
, operatorCharacter
, '*');
316 // Valid first characters for identifiers.
317 const identifierHead
= either(
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]/,
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
336 // Valid characters for identifiers.
337 const identifierCharacter
= either(
340 /[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/
344 const identifier
= concat(identifierHead
, identifierCharacter
, '*');
346 // Valid type identifier.
347 const typeIdentifier
= concat(/[A-Z]/, identifierCharacter
, '*');
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
= [
355 concat(/convention\(/, either('swift', 'block', 'c'), /\)/),
358 'dynamicMemberLookup',
374 concat(/objc\(/, identifier
, /\)/),
378 'requires_stored_property_inits',
386 'warn_unqualified_access'
389 // Contextual keywords used in @available and #(un)available.
390 const availabilityKeywords
= [
392 'iOSApplicationExtension',
394 'macOSApplicationExtension',
396 'macCatalystApplicationExtension',
398 'watchOSApplicationExtension',
400 'tvOSApplicationExtension',
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
414 /** @type LanguageFn */
415 function swift(hljs
) {
420 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID411
421 const BLOCK_COMMENT
= hljs
.COMMENT(
424 { contains: [ 'self' ] }
427 hljs
.C_LINE_COMMENT_MODE
,
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
= {
436 either(...dotKeywords
, ...optionalDotKeywords
)
438 className: { 2: "keyword" }
440 const KEYWORD_GUARD
= {
441 // Consume .keyword to prevent highlighting properties and methods as keywords.
442 match: concat(/\./, either(...keywords
)),
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: [
454 className: 'keyword',
455 match: either(...REGEX_KEYWORDS
, ...optionalDotKeywords
)
458 // find all the regular keywords
461 /\b\w+/, // regular keywords
462 /#\w+/ // number keywords
464 keyword: PLAIN_KEYWORDS
465 .concat(numberSignKeywords
),
468 const KEYWORD_MODES
= [
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
)),
481 className: 'built_in',
482 match: concat(/\b/, either(...builtIns
), /(?=\()/)
489 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418
490 const OPERATOR_GUARD
= {
491 // Prevent -> from being highlighting as an operator.
496 className: 'operator',
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})+` }
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]_*)+';
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` },
525 { match: /\b0o([0-7]_*)+\b/ },
527 { match: /\b0b([01]_*)+\b/ }
531 // https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#grammar_string-literal
532 const ESCAPED_CHARACTER
= (rawDelimiter
= "") => ({
535 { match: concat(/\\/, rawDelimiter
, /[0\\tnr"']/) },
536 { match: concat(/\\/, rawDelimiter
, /u\{[0-9a-fA-F]{1,8}\}/) }
539 const ESCAPED_NEWLINE
= (rawDelimiter
= "") => ({
541 match: concat(/\\/, rawDelimiter
, /[\t ]*(?:[\r\n]|\r\n)/)
543 const INTERPOLATION
= (rawDelimiter
= "") => ({
546 begin: concat(/\\/, rawDelimiter
, /\(/),
549 const MULTILINE_STRING
= (rawDelimiter
= "") => ({
550 begin: concat(rawDelimiter
, /"""/),
551 end: concat(/"""/, rawDelimiter
),
553 ESCAPED_CHARACTER(rawDelimiter
),
554 ESCAPED_NEWLINE(rawDelimiter
),
555 INTERPOLATION(rawDelimiter
)
558 const SINGLE_LINE_STRING
= (rawDelimiter
= "") => ({
559 begin: concat(rawDelimiter
, /"/),
560 end: concat(/"/, rawDelimiter
),
562 ESCAPED_CHARACTER(rawDelimiter
),
563 INTERPOLATION(rawDelimiter
)
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("###")
580 const REGEXP_CONTENTS
= [
581 hljs
.BACKSLASH_ESCAPE
,
586 contains: [ hljs
.BACKSLASH_ESCAPE
]
590 const BARE_REGEXP_LITERAL
= {
591 begin: /\/[^\s](?=[^/\n]*\/)/,
593 contains: REGEXP_CONTENTS
596 const EXTENDED_REGEXP_LITERAL
= (rawDelimiter
) => {
597 const begin
= concat(rawDelimiter
, /\//);
598 const end
= concat(/\//, rawDelimiter
);
606 begin: `#(?!.*${end})`,
613 // https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure/#Regular-Expression-Literals
617 EXTENDED_REGEXP_LITERAL('###'),
618 EXTENDED_REGEXP_LITERAL('##'),
619 EXTENDED_REGEXP_LITERAL('#'),
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',
630 const PROPERTY_WRAPPER_PROJECTION
= {
631 className: 'variable',
632 match: `\\$${identifierCharacter}+`
634 const IDENTIFIERS
= [
637 PROPERTY_WRAPPER_PROJECTION
640 // https://docs.swift.org/swift-book/ReferenceManual/Attributes.html
641 const AVAILABLE_ATTRIBUTE
= {
642 match: /(@|#(un)?)available/,
644 starts: { contains: [
648 keywords: availabilityKeywords
,
658 const KEYWORD_ATTRIBUTE
= {
660 match: concat(/@/, either(...keywordAttributes
), lookahead(either(/\(/, /\s+/))),
663 const USER_DEFINED_ATTRIBUTE
= {
665 match: concat(/@/, identifier
)
671 USER_DEFINED_ATTRIBUTE
674 // https://docs.swift.org/swift-book/ReferenceManual/Types.html
676 match: lookahead(/\b[A-Z]/),
679 { // Common Apple frameworks, for relevance boost
681 match: concat(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/, identifierCharacter
, '+')
685 match: typeIdentifier
,
692 { // Variadic parameter
696 { // Protocol composition
697 match: concat(/\s+&\s+/, lookahead(typeIdentifier
)),
702 const GENERIC_ARGUMENTS
= {
714 TYPE
.contains
.push(GENERIC_ARGUMENTS
);
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*:/),
723 // Matches tuples as well as the parameter list of a function type.
745 const GENERIC_PARAMETERS
= {
748 keywords: 'repeat each',
754 const FUNCTION_PARAMETER_NAME
= {
756 lookahead(concat(identifier
, /\s*:/)),
757 lookahead(concat(identifier
, /\s+/, identifier
, /\s*:/))
763 className: 'keyword',
772 const FUNCTION_PARAMETERS
= {
777 FUNCTION_PARAMETER_NAME
,
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
= {
796 either(QUOTED_IDENTIFIER
.match
, identifier
, operator
)
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
= {
817 /\b(?:subscript|init[?!]?)/,
820 className: { 1: "keyword" },
828 // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID380
829 const OPERATOR_DECLARATION
= {
841 // https://docs.swift.org/swift-book/ReferenceManual/Declarations.html#ID550
842 const PRECEDENCEGROUP
= {
854 ...precedencegroupKeywords
,
860 const CLASS_FUNC_DECLARATION
= {
866 /\b[A-Za-z_][A-Za-z0-9_]*\b/
875 const CLASS_VAR_DECLARATION
= {
887 const TYPE_DECLARATION
= {
889 /(struct|protocol|class|extension|enum|actor)/,
908 scope: "title.class.inherited",
909 match: typeIdentifier
,
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
;
931 interpolation
.contains
= [
951 CLASS_FUNC_DECLARATION
,
952 CLASS_VAR_DECLARATION
,
954 OPERATOR_DECLARATION
,
957 beginKeywords: 'import',
959 contains: [ ...COMMENTS
],
980 export default hljsGrammar
;