1 /*! `fsharp` grammar compiled for Highlight.js 11.11.1 */
2 var hljsGrammar
= (function () {
6 * @param {string} value
9 function escape(value
) {
10 return new RegExp(value
.replace(/[-/\\^$*+?.()|[\]{}]/g
, '\\$&'), 'm');
14 * @param {RegExp | string } re
19 if (typeof re
=== "string") return re
;
25 * @param {RegExp | string } re
28 function lookahead(re
) {
29 return concat('(?=', re
, ')');
33 * @param {...(RegExp | string) } args
36 function concat(...args
) {
37 const joined
= args
.map((x
) => source(x
)).join("");
42 * @param { Array<string | RegExp | Object> } args
45 function stripOptionsFromArgs(args
) {
46 const opts
= args
[args
.length
- 1];
48 if (typeof opts
=== 'object' && opts
.constructor === Object
) {
49 args
.splice(args
.length
- 1, 1);
56 /** @typedef { {capture?: boolean} } RegexEitherOptions */
59 * Any of the passed expresssions may match
61 * Creates a huge this | this | that | that match
62 * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args
65 function either(...args
) {
66 /** @type { object & {capture?: boolean} } */
67 const opts
= stripOptionsFromArgs(args
);
69 + (opts
.capture
? "" : "?:")
70 + args
.map((x
) => source(x
)).join("|") + ")";
76 Author: Jonas Follesø <jonas@follesoe.no>
77 Contributors: Troy Kershaw <hello@troykershaw.com>, Henrik Feldt <henrik@haf.se>, Melvyn Laïly <melvyn.laily@gmail.com>
78 Website: https://docs.microsoft.com/en-us/dotnet/fsharp/
83 /** @type LanguageFn */
84 function fsharp(hljs
) {
104 // "false", // literal
125 // "not", // built_in
126 // "null", // literal
139 // "true", // literal
152 const BANG_KEYWORD_MODE
= {
153 // monad builder keywords (matches before non-bang keywords)
155 match: /\b(yield|return|let|do|match|use)!/
158 const PREPROCESSOR_KEYWORDS
= [
188 const SPECIAL_IDENTIFIERS
= [
190 "__SOURCE_DIRECTORY__",
194 // Since it's possible to re-bind/shadow names (e.g. let char = 'c'),
195 // these builtin types should only be matched when a type name is expected.
196 const KNOWN_TYPES
= [
222 // other native types or lowercase aliases
235 // other important FSharp types
240 // Somewhat arbitrary list of builtin functions and values.
241 // Most of them are declared in Microsoft.FSharp.Core
242 // I tried to stay relevant by adding only the most idiomatic
243 // and most used symbols that are not already declared as types.
280 const ALL_KEYWORDS
= {
284 'variable.constant': SPECIAL_IDENTIFIERS
287 // (* potentially multi-line Meta Language style comment *)
289 hljs
.COMMENT(/\(\*(?!\))/, /\*\)/, {
292 // Either a multi-line (* Meta Language style comment *) or a single line // C style comment.
296 hljs
.C_LINE_COMMENT_MODE
,
300 // Most identifiers can contain apostrophes
301 const IDENTIFIER_RE
= /[a-zA-Z_](\w|')*/;
303 const QUOTED_IDENTIFIER
= {
309 // 'a or ^a where a can be a ``quoted identifier``
310 const BEGIN_GENERIC_TYPE_SYMBOL_RE
= /\B('|\^)/;
311 const GENERIC_TYPE_SYMBOL
= {
314 // the type name is a quoted identifier:
315 { match: concat(BEGIN_GENERIC_TYPE_SYMBOL_RE
, /``.*?``/) },
316 // the type name is a normal identifier (we don't use IDENTIFIER_RE because there cannot be another apostrophe here):
317 { match: concat(BEGIN_GENERIC_TYPE_SYMBOL_RE
, hljs
.UNDERSCORE_IDENT_RE
) }
322 const makeOperatorMode = function({ includeEqual
}) {
323 // List or symbolic operator characters from the FSharp Spec 4.1, minus the dot, and with `?` added, used for nullable operators.
324 let allOperatorChars
;
326 allOperatorChars
= "!%&*+-/<=>@^|~?";
328 allOperatorChars
= "!%&*+-/<>@^|~?";
329 const OPERATOR_CHARS
= Array
.from(allOperatorChars
);
330 const OPERATOR_CHAR_RE
= concat('[', ...OPERATOR_CHARS
.map(escape
), ']');
331 // The lone dot operator is special. It cannot be redefined, and we don't want to highlight it. It can be used as part of a multi-chars operator though.
332 const OPERATOR_CHAR_OR_DOT_RE
= either(OPERATOR_CHAR_RE
, /\./);
333 // When a dot is present, it must be followed by another operator char:
334 const OPERATOR_FIRST_CHAR_OF_MULTIPLE_RE
= concat(OPERATOR_CHAR_OR_DOT_RE
, lookahead(OPERATOR_CHAR_OR_DOT_RE
));
335 const SYMBOLIC_OPERATOR_RE
= either(
336 concat(OPERATOR_FIRST_CHAR_OF_MULTIPLE_RE
, OPERATOR_CHAR_OR_DOT_RE
, '*'), // Matches at least 2 chars operators
337 concat(OPERATOR_CHAR_RE
, '+'), // Matches at least one char operators
342 // symbolic operators:
343 SYMBOLIC_OPERATOR_RE
,
344 // other symbolic keywords:
345 // Type casting and conversion operators:
349 /:=/, // Reference cell assignment
351 /\$/), // A single $ can be used as an operator
356 const OPERATOR
= makeOperatorMode({ includeEqual: true });
357 // This variant is used when matching '=' should end a parent mode:
358 const OPERATOR_WITHOUT_EQUAL
= makeOperatorMode({ includeEqual: false });
360 const makeTypeAnnotationMode = function(prefix
, prefixScope
) {
362 begin: concat( // a type annotation is a
363 prefix
, // should be a colon or the 'of' keyword
364 lookahead( // that has to be followed by
366 /\s*/, // optional space
367 either( // then either of:
369 /'/, // generic type name
370 /\^/, // generic type name
371 /#/, // flexible type name
372 /``/, // quoted type name
373 /\(/, // parens type expression
374 /{\|/, // anonymous type annotation
376 beginScope: prefixScope,
377 // BUG: because ending with \n is necessary for some cases, multi-line type annotations are not properly supported.
378 // Examples where \n is required at the end:
379 // - abstract member definitions in classes: abstract Property : int * string
380 // - return type annotations: let f f' = f
' () : returnTypeAnnotation
381 // - record fields definitions: { A : int \n B : string }
387 // we need the known types, and we need the type constraint keywords and literals. e.g.: when 'a : null
388 keywords: hljs
.inherit(ALL_KEYWORDS
, { type: KNOWN_TYPES
}),
392 hljs
.inherit(QUOTED_IDENTIFIER
, { scope: null }), // match to avoid strange patterns inside that may break the parsing
393 OPERATOR_WITHOUT_EQUAL
398 const TYPE_ANNOTATION
= makeTypeAnnotationMode(/:/, 'operator');
399 const DISCRIMINATED_UNION_TYPE_ANNOTATION
= makeTypeAnnotationMode(/\bof\b/, 'keyword');
401 // type MyType<'a> = ...
402 const TYPE_DECLARATION
= {
404 /(^|\s+)/, // prevents matching the following: `match s.stype with`
413 end: lookahead(/\(|=|$/),
414 keywords: ALL_KEYWORDS
, // match keywords in type constraints. e.g.: when 'a : null
417 hljs
.inherit(QUOTED_IDENTIFIER
, { scope: null }), // match to avoid strange patterns inside that may break the parsing
420 // For visual consistency, highlight type brackets as operators.
424 TYPE_ANNOTATION
// generic types can have constraints, which are type annotations. e.g. type MyType<'T when 'T : delegate<obj * string>> =
428 const COMPUTATION_EXPRESSION
= {
429 // computation expressions:
430 scope: 'computation-expression',
431 // BUG: might conflict with record deconstruction. e.g. let f { Name = name } = name // will highlight f
432 match: /\b[_a-z]\w*(?=\s*\{)/
435 const PREPROCESSOR
= {
436 // preprocessor directives and fsi commands:
439 concat(/#/, either(...PREPROCESSOR_KEYWORDS
)),
442 beginScope: { 2: 'meta' },
443 end: lookahead(/\s|$/)
446 // TODO: this definition is missing support for type suffixes and octal notation.
447 // BUG: range operator without any space is wrongly interpreted as a single number (e.g. 1..10 )
450 hljs
.BINARY_NUMBER_MODE
,
455 // All the following string definitions are potentially multi-line.
456 // BUG: these definitions are missing support for byte strings (suffixed with B)
459 const QUOTED_STRING
= {
464 hljs
.BACKSLASH_ESCAPE
468 const VERBATIM_STRING
= {
474 match: /""/ // escaped "
476 hljs
.BACKSLASH_ESCAPE
480 const TRIPLE_QUOTED_STRING
= {
490 keywords: ALL_KEYWORDS
493 const INTERPOLATED_STRING
= {
499 match: /\{\{/ // escaped {
502 match: /\}\}/ // escaped }
504 hljs.BACKSLASH_ESCAPE,
509 const INTERPOLATED_VERBATIM_STRING = {
515 match: /\{\{/ // escaped {
518 match: /\}\}/ // escaped }
523 hljs.BACKSLASH_ESCAPE,
527 // $"""...{1+1}..."""
528 const INTERPOLATED_TRIPLE_QUOTED_STRING = {
534 match: /\{\{/ // escaped {
537 match: /\}\}/ // escaped }
544 const CHAR_LITERAL
= {
549 /[^\\']/, // either a single non escaped char...
550 /\\(?:.|\d{3}|x[a-fA-F\d]{2}|u[a-fA-F\d]{4}|U[a-fA-F\d]{8})/ // ...or an escape sequence
555 // F# allows a lot of things inside string placeholders.
556 // Things that don't currently seem allowed by the
compiler: types definition
, attributes usage
.
557 // (Strictly speaking, some of the followings are only allowed inside triple quoted interpolated strings...)
559 INTERPOLATED_VERBATIM_STRING
,
568 COMPUTATION_EXPRESSION
,
576 INTERPOLATED_TRIPLE_QUOTED_STRING
,
577 INTERPOLATED_VERBATIM_STRING
,
579 TRIPLE_QUOTED_STRING
,
592 keywords: ALL_KEYWORDS
,
595 'computation-expression': 'keyword'
604 // e.g. [<Attributes("")>] or [<``module``: MyCustomAttributeThatWorksOnModules>]
605 // or [<Sealed; NoEquality; NoComparison; CompiledName("FSharpAsync`1")>]
612 // can contain any constant value
613 TRIPLE_QUOTED_STRING
,
620 DISCRIMINATED_UNION_TYPE_ANNOTATION
,
622 COMPUTATION_EXPRESSION
,
635 export default hljsGrammar
;