@wooorm/starry-night
Version:
Syntax highlighting, like GitHub
999 lines (998 loc) • 59.5 kB
JavaScript
// This is a TextMate grammar distributed by `starry-night`.
// This grammar is developed at
// <https://github.com/B-Lang-org/language-bh>
// and licensed `bsd-3-clause`.
// See <https://github.com/wooorm/starry-night> for more info.
/**
* @import {Grammar} from '@wooorm/starry-night'
*/
/** @type {Grammar} */
const grammar = {
extensions: [],
names: ['bluespec-bh', 'bh', 'bluespec-classic'],
patterns: [
{include: '#comment_like'},
{include: '#numeric_literals'},
{include: '#string_literal'},
{include: '#char_literal'},
{match: '(?<!@|#)-\\}', name: 'invalid'},
{
captures: {
1: {name: 'punctuation.paren.bh'},
2: {name: 'punctuation.paren.bh'}
},
match: '(\\()\\s*(\\))',
name: 'constant.language.unit.bh'
},
{
captures: {
1: {name: 'punctuation.paren.bh'},
2: {name: 'keyword.operator.hash.bh'},
3: {name: 'keyword.operator.hash.bh'},
4: {name: 'punctuation.paren.bh'}
},
match: '(\\()(#)\\s*(#)(\\))',
name: 'constant.language.unit.unboxed.bh'
},
{
captures: {
1: {name: 'punctuation.paren.bh'},
2: {name: 'punctuation.paren.bh'}
},
match: '(\\()\\s*,[\\s,]*(\\))',
name: 'support.constant.tuple.bh'
},
{
captures: {
1: {name: 'punctuation.paren.bh'},
2: {name: 'keyword.operator.hash.bh'},
3: {name: 'keyword.operator.hash.bh'},
4: {name: 'punctuation.paren.bh'}
},
match: '(\\()(#)\\s*,[\\s,]*(#)(\\))',
name: 'support.constant.tuple.unboxed.bh'
},
{
captures: {
1: {name: 'punctuation.bracket.bh'},
2: {name: 'punctuation.bracket.bh'}
},
match: '(\\[)\\s*(\\])',
name: 'constant.language.empty-list.bh'
},
{
begin: "(\\b(?<!')(package)|^(signature))(\\b(?!'))",
beginCaptures: {
2: {name: 'keyword.other.package.bh'},
3: {name: 'keyword.other.signature.bh'}
},
end: "(?=\\b(?<!')where\\b(?!'))",
name: 'meta.declaration.package.bh',
patterns: [
{include: '#comment_like'},
{include: '#package_name'},
{include: '#package_exports'},
{match: '[a-z]+', name: 'invalid'}
]
},
{include: '#ffi'},
{
begin: "^(\\s*)(class)(\\s+(:?in?)coherent)?(\\b(?!'))",
beginCaptures: {
2: {name: 'keyword.other.class.bh'},
3: {name: 'keyword.other.coherent.bh'}
},
end: "(?x) # Detect end of class declaration:\n # 'where' keyword\n (?=(?<!')\\bwhere\\b(?!')) \n # Decreasing indentation\n |(?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_\"']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )",
name: 'meta.declaration.class.bh',
patterns: [
{include: '#comment_like'},
{include: '#where'},
{include: '#type_signature'}
]
},
{include: '#role_annotation'},
{
begin:
'^(\\s*)(pattern)\\s+(.*?)\\s+(::|∷)(?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])',
beginCaptures: {
2: {name: 'keyword.other.pattern.bh'},
3: {patterns: [{include: '#comma'}, {include: '#data_constructor'}]},
4: {name: 'keyword.operator.double-colon.bh'}
},
end: '(?x) # Detect end of pattern type definition by decreasing indentation:\n (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n',
name: 'meta.declaration.pattern.type.bh',
patterns: [{include: '#type_signature'}]
},
{
begin: "^\\s*(pattern)\\b(?!')",
captures: {1: {name: 'keyword.other.pattern.bh'}},
end: '(?x) # Detect end of pattern type definition by decreasing indentation:\n (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n',
name: 'meta.declaration.pattern.bh',
patterns: [{include: '$self'}]
},
{
begin:
'(?x)\n # Data declaration\n ^(\\s*)(data|newtype|interface|struct)\\s+\n # Keep consuming characters until:\n (((?!\n # the equals symbol or the start of a single-line comment, or\n (?: \n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]) # non-symbol\n (?:=|--+)\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]) # non-symbol\n )\n # the "where" or "deriving" keywords, or\n | (?:\\b(?<!\')(?:where|deriving)\\b(?!\'))\n # the start of a block comment.\n | {-\n #\n ).)*)',
beginCaptures: {
2: {name: 'keyword.other.$2.bh'},
3: {name: 'keyword.other.$3.bh'},
4: {patterns: [{include: '#type_signature'}]}
},
end: '(?x) # Detect end of data declaration: \n # Decreasing indentation\n (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )',
name: 'meta.declaration.$2.algebraic.bh',
patterns: [
{include: '#comment_like'},
{include: '#deriving'},
{include: '#forall'},
{include: '#adt_constructor'},
{include: '#data_context'},
{include: '#record_decl'},
{include: '#type_signature'}
]
},
{
begin:
'(?x)\n # Type declaration\n ^(\\s*)(type)(?:\\s+(instance))?\\s+\n # Keep consuming characters until:\n (((?!\n # the equals symbol, the start of a single-line comment, or a type signature\n (?: \n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]) # non-symbol\n (?:=|--+|::|∷)\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]) # non-symbol\n )\n # the start of a block comment.\n | {-\n #\n ).)*)',
beginCaptures: {
2: {name: 'keyword.other.type.bh'},
3: {name: 'keyword.other.instance.bh'},
4: {patterns: [{include: '#type_signature'}]}
},
end: '(?x) # Detect end of type definition by decreasing indentation:\n (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n',
name: 'meta.declaration.type.bh',
patterns: [{include: '#type_signature'}]
},
{
begin: "^(\\s*)(instance)(\\b(?!'))",
beginCaptures: {2: {name: 'keyword.other.instance.bh'}},
end: "(?x) # Detect end of instance declaration:\n # 'where' keyword\n (?=\\b(?<!')(where)\\b(?!'))\n # Decreasing indentation\n |(?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_\"']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n",
name: 'meta.declaration.instance.bh',
patterns: [
{include: '#comment_like'},
{include: '#where'},
{include: '#type_signature'}
]
},
{
begin: "^(\\s*)(import)(\\b(?!'))",
beginCaptures: {2: {name: 'keyword.other.import.bh'}},
end: "(?x) # Detect end of import\n # 'where' keyword\n (?=\\b(?<!')(where)\\b(?!'))\n # Decreasing indentation\n |(?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_\"']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n",
name: 'meta.import.bh',
patterns: [
{include: '#comment_like'},
{include: '#where'},
{
captures: {1: {name: 'keyword.other.$1.bh'}},
match: '(qualified|as|hiding)'
},
{include: '#package_name'},
{include: '#package_exports'}
]
},
{include: '#deriving'},
{include: '#layout_herald'},
{include: '#keyword'},
{
captures: {
1: {name: 'keyword.other.fixity.$1.bh'},
2: {
patterns: [
{include: '#comment_like'},
{include: '#integer_literals'},
{
match: ':[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]*',
name: 'constant.other.operator.infix.bh'
},
{include: '#infix_op'}
]
}
},
match: '^\\s*(infix[lr]?)\\s+(.*)',
name: 'meta.fixity-declaration.bh'
},
{include: '#start_type_signature'},
{include: '#overloaded_label'},
{include: '#type_application'},
{include: '#reserved_symbol'},
{include: '#fun_decl'},
{include: '#qualifier'},
{
match: ':[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]*',
name: 'constant.other.operator.infix.bh'
},
{include: '#data_constructor'},
{include: '#prefix_op'},
{include: '#infix_op'},
{
begin: '(\\()(#)\\s',
beginCaptures: {
1: {name: 'punctuation.paren.bh'},
2: {name: 'keyword.operator.hash.bh'}
},
end: '(#)(\\))',
endCaptures: {
1: {name: 'keyword.operator.hash.bh'},
2: {name: 'punctuation.paren.bh'}
},
patterns: [{include: '#comma'}, {include: '$self'}]
},
{
begin: '(\\()',
beginCaptures: {1: {name: 'punctuation.paren.bh'}},
end: '(\\))',
endCaptures: {1: {name: 'punctuation.paren.bh'}},
patterns: [{include: '#comma'}, {include: '$self'}]
},
{include: '#quasi_quote'},
{
begin: '(\\[)',
beginCaptures: {1: {name: 'punctuation.bracket.bh'}},
end: '(\\])',
endCaptures: {1: {name: 'punctuation.bracket.bh'}},
patterns: [{include: '#comma'}, {include: '$self'}]
},
{include: '#record'}
],
repository: {
adt_constructor: {
patterns: [
{include: '#comment_like'},
{
begin:
'(?x)\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]) # non-symbol\n (?:(=)|(\\|))\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]) # non-symbol',
beginCaptures: {
1: {name: 'keyword.operator.eq.bh'},
2: {name: 'keyword.operator.pipe.bh'}
},
end: "(?x)\n (?: # Infix data constructor\n # First argument\n (?:\n # Simple type\n (?<!')\\b((?:[\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}'\\.])+)\n # Type inside balanced parentheses\n | ('? # Optional promotion tick\n (?<paren>\n \\( # Opening parenthesis\n (?:\n [^\\(\\)]* # Match non-parentheses\n | \\g<paren> # or recurse into further depth\n )*\n \\) # Closing parenthesis\n )\n )\n # Type inside balanced brackets\n | ('? # Optional promotion tick\n (?<brac>\n \\[ # Opening bracket\n (?:\n [^\\[\\]]* # Match non-brackets\n | \\g<brac> # or recurse into further depth\n )*\n \\] # Closing bracket\n )\n )\n )\n # Then either\n \\s*\n # - a symbolic infix constructor, or\n (?:(?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']])(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]*)\n # - an alphabetic infix constructor\n | (`)([\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)(`)\n )\n ) # Otherwise, prefix data constructor, either:\n | # - an alphabetic data constructor e.g. \"Cons_123\"\n (?:(?<!')\\b([\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*))\n | # - a symbolic (prefix) data constructor\n (\\()\\s*(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]*)\\s*(\\))\n | # Otherwise, try to fail early to avoid excessive backtracking (https://github.com/JustusAdam/language-bh/issues/161)\n # Fail when detecting a lowercase identifier and then something not starting with a tick or colon\n (?=\\b(?<!')(?!(?:forall|deriving)\\s)[\\p{Ll}_]\\S+\\s+[^`:])\n # Fail when seeing another equal signs or pipe symbol\n |(?=\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]) # non-symbol\n (?:=|\\|)\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]) # non-symbol\n )",
endCaptures: {
1: {patterns: [{include: '#type_signature'}]},
10: {name: 'constant.other.bh'},
11: {name: 'punctuation.paren.bh'},
12: {name: 'constant.other.operator.prefix.bh'},
13: {name: 'punctuation.paren.bh'},
2: {patterns: [{include: '#type_signature'}]},
4: {patterns: [{include: '#type_signature'}]},
6: {name: 'constant.other.operator.infix.bh'},
7: {name: 'punctuation.backtick.bh'},
8: {name: 'constant.other.infix.bh'},
9: {name: 'punctuation.backtick.bh'}
},
patterns: [
{include: '#comment_like'},
{include: '#deriving'},
{include: '#record_decl'},
{include: '#forall'},
{include: '#data_context'},
{include: '#type_signature'}
]
}
]
},
block_comment: {
applyEndPatternLast: true,
begin: '\\{-',
captures: {0: {name: 'punctuation.definition.comment.bh'}},
end: '-\\}',
name: 'comment.block.bh',
patterns: [{include: '#block_comment'}]
},
char_literal: {
captures: {
1: {name: 'punctuation.definition.string.begin.bh'},
2: {name: 'constant.character.escape.bh'},
3: {name: 'constant.character.escape.octal.bh'},
4: {name: 'constant.character.escape.hexadecimal.bh'},
5: {name: 'constant.character.escape.control.bh'},
6: {name: 'punctuation.definition.string.end.bh'}
},
match:
"(?x)\n (?<![\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}'])\n (')\n (?:\n [\\ -\\[\\]-~] # Basic Char\n | (\\\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE\n |DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS\n |US|SP|DEL|[abfnrtv\\\\\\\"'\\\\&])) # Escapes\n | (\\\\o[0-7]+) # Octal Escapes\n | (\\\\x[0-9A-Fa-f]+) # Hexadecimal Escapes\n | (\\\\\\^[A-Z@\\[\\]\\\\\\^_]) # Control Chars\n )\n (')\n",
name: 'string.quoted.single.bh'
},
comma: {match: ',', name: 'punctuation.separator.comma.bh'},
comment_like: {
patterns: [
{include: '#cpp'},
{include: '#pragma'},
{include: '#comments'}
]
},
comments: {
patterns: [
{
begin: '^(\\s*)(--\\s[\\|\\$])',
beginCaptures: {
2: {name: 'punctuation.whitespace.comment.leading.bh'}
},
end: '(?=^(?!\\1--+(?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])))',
name: 'comment.block.documentation.bh'
},
{
begin: '(^[ \\t]+)?(--(@)\\s)',
beginCaptures: {
1: {name: 'punctuation.whitespace.comment.leading.bh'}
},
end: '\\n',
name: 'comment.line.documentation.bh'
},
{
applyEndPatternLast: true,
begin: '\\{-\\s?[\\|\\$\\*\\^]',
captures: {0: {name: 'punctuation.definition.comment.bh'}},
end: '-\\}',
name: 'comment.block.documentation.bh',
patterns: [{include: '#block_comment'}]
},
{
begin: '(^[ \\t]+)?(?=--+(?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]))',
beginCaptures: {
1: {name: 'punctuation.whitespace.comment.leading.bh'}
},
end: '(?!\\G)',
patterns: [
{
begin: '--',
beginCaptures: {0: {name: 'punctuation.definition.comment.bh'}},
end: '\\n',
name: 'comment.line.double-dash.bh'
}
]
},
{include: '#block_comment'}
]
},
cpp: {
captures: {1: {name: 'punctuation.definition.preprocessor.c'}},
match: '^(#).*$',
name: 'meta.preprocessor.c'
},
data_constructor: {
patterns: [
{
match:
"\\b(?<!')[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*(?![\\.'\\w])",
name: 'constant.other.bh'
},
{
match: '(\\()\\s*(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]*)\\s*(\\))',
name: 'constant.other.operator.bh'
}
]
},
data_context: {
captures: {
1: {
patterns: [
{include: '#comment_like'},
{include: '#forall'},
{
begin: "(?='?\\()",
end: '(?=\\))',
patterns: [{include: '#type_signature'}]
},
{
begin: "(?='?\\[)",
end: '(?=\\])',
patterns: [{include: '#type_signature'}]
},
{
captures: {
1: {
patterns: [
{include: '#comment_like'},
{include: '#forall'},
{include: '#record_decl_field'}
]
},
2: {patterns: [{include: '#reserved_symbol'}]},
3: {patterns: [{include: '#type_signature'}]}
},
match:
'(?x)\n (\\S*)\\s*\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])\n (::|∷|=)\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])'
},
{include: '#type_signature'}
]
},
2: {name: 'keyword.operator.big-arrow.bh'}
},
match:
'(?x)\n (.*)\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])\n (=>|⇒)\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])\n'
},
deriving: {
patterns: [
{
begin: '^(\\s*)(deriving)\\s+(?:(via|stock|newtype|anyclass)\\s+)?',
beginCaptures: {
2: {name: 'keyword.other.deriving.bh'},
3: {name: 'keyword.other.deriving.strategy.$3.bh'}
},
end: '(?x) # Detect end of deriving statement\n # Decreasing indentation\n (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )',
name: 'meta.deriving.bh',
patterns: [
{include: '#comment_like'},
{
match: "(?<!')\\b(instance)\\b(?!')",
name: 'keyword.other.instance.bh'
},
{
captures: {1: {name: 'keyword.other.deriving.strategy.$1.bh'}},
match: "(?<!')\\b(via|stock|newtype|anyclass)\\b(?!')"
},
{include: '#type_signature'}
]
},
{
begin: '(deriving)(?:\\s+(stock|newtype|anyclass))?\\s*(\\()',
beginCaptures: {
1: {name: 'keyword.other.deriving.bh'},
2: {name: 'keyword.other.deriving.strategy.$2.bh'},
3: {name: 'punctuation.paren.bh'}
},
end: '(\\))',
endCaptures: {1: {name: 'punctuation.paren.bh'}},
name: 'meta.deriving.bh',
patterns: [{include: '#type_signature'}]
},
{
captures: {
1: {name: 'keyword.other.deriving.bh'},
2: {name: 'keyword.other.deriving.strategy.$2.bh'},
3: {patterns: [{include: '#type_signature'}]},
5: {name: 'keyword.other.deriving.strategy.via.bh'},
6: {patterns: [{include: '#type_signature'}]}
},
match:
"(?x)\n (deriving)(?:\\s+(stock|newtype|anyclass))?\\s+\n ([\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)\n (\\s+(via)\\s+(.*)$)?\n",
name: 'meta.deriving.bh'
},
{
match: "(?<!')\\b(via)\\b(?!')",
name: 'keyword.other.deriving.strategy.via.bh'
}
]
},
double_colon: {
captures: {1: {name: 'keyword.operator.double-colon.bh'}},
match: '\\s*(::|∷)(?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])\\s*'
},
export_constructs: {
patterns: [
{include: '#comment_like'},
{
begin: "\\b(?<!')(pattern)\\b(?!')",
beginCaptures: {1: {name: 'keyword.other.pattern.bh'}},
end: "(?x)\n # Data constructor\n ([\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)\n # Prefix form of symbolic constructor\n | (\\()\\s*(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]+)\\s*(\\))",
endCaptures: {
1: {name: 'constant.other.bh'},
2: {name: 'punctuation.paren.bh'},
3: {name: 'constant.other.operator.prefix.bh'},
4: {name: 'punctuation.paren.bh'}
},
patterns: [{include: '#comment_like'}]
},
{
begin: "\\b(?<!')(type)\\b(?!')",
beginCaptures: {1: {name: 'keyword.other.type.bh'}},
end: '(?=,|\\))',
patterns: [
{include: '#comment_like'},
{include: '#reserved_symbol'},
{include: '#type_constructor'},
{include: '#type_operator'}
]
},
{include: '#record_wildcard'},
{include: '#reserved_symbol'},
{
match: '(\\()\\s*(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]*)\\s*(\\))',
name: 'storage.type.operator.bh'
},
{
match: "(?<!')\\b[\\p{Ll}_][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*",
name: 'entity.name.function.bh'
},
{
match: "(?<!')\\b[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*",
name: 'storage.type.bh'
},
{include: '#prefix_op'}
]
},
ffi: {
begin: '^(\\s*)(foreign)\\s+(import|export)\\s+',
beginCaptures: {
2: {name: 'keyword.other.foreign.bh'},
3: {name: 'keyword.other.$3.bh'}
},
end: '(?x) # Detect end of FFI block by decreasing indentation:\n (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n',
name: 'meta.$3.foreign.bh',
patterns: [
{include: '#comment_like'},
{
captures: {1: {name: 'keyword.other.calling-convention.$1.bh'}},
match: "\\b(?<!')(ccall|cplusplus|dotnet|jvm|stdcall|prim|capi)\\s+"
},
{
begin:
"(?=\")|(?=\\b(?<!')([\\p{Ll}_][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)\\b(?!'))",
end: '(?=(::|∷)(?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]))',
patterns: [
{include: '#comment_like'},
{
captures: {
1: {name: 'keyword.other.safety.$1.bh'},
2: {
name: 'entity.name.foreign.bh',
patterns: [{include: '#string_literal'}]
},
3: {name: 'entity.name.function.bh'},
4: {name: 'entity.name.function.infix.bh'}
},
match:
"(?x)\n \\b(?<!')(safe|unsafe|interruptible)\\b(?!')\n \\s*\n (\"(?:\\\\\"|[^\"])*\")?\n \\s*\n (?:\n (?:\\b(?<!'')([\\p{Ll}_][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)\\b(?!'))\n |(?:\\(\\s*(?!--+\\))([\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]+)\\s*\\))\n )\n"
},
{
captures: {
1: {name: 'keyword.other.safety.$1.bh'},
2: {
name: 'entity.name.foreign.bh',
patterns: [{include: '#string_literal'}]
}
},
match:
'(?x)\n \\b(?<!\')(safe|unsafe|interruptible)\\b(?!\')\n \\s*\n ("(?:\\\\"|[^"])*")?\n \\s*$\n'
},
{
captures: {
0: {
name: 'entity.name.foreign.bh',
patterns: [{include: '#string_literal'}]
}
},
match: '(?x)\n "(?:\\\\"|[^"])*"'
},
{
captures: {
1: {name: 'entity.name.function.bh'},
2: {name: 'punctuation.paren.bh'},
3: {name: 'entity.name.function.infix.bh'},
4: {name: 'punctuation.paren.bh'}
},
match:
"(?x)\n (?:\\b(?<!'')([\\p{Ll}_][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)\\b(?!'))\n |(?:(\\()\\s*(?!--+\\))([\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]+)\\s*(\\)))\n"
}
]
},
{include: '#double_colon'},
{include: '#type_signature'}
]
},
float_literals: {
captures: {
1: {name: 'constant.numeric.floating.decimal.bh'},
2: {name: 'constant.numeric.floating.hexadecimal.bh'}
},
match:
"(?x)\n \\b(?<!')\n (?: # Decimal\n ([0-9][_0-9]*\\.[0-9][_0-9]*(?:[eE][-+]?[0-9][_0-9]*)?\n |[0-9][_0-9]*[eE][-+]?[0-9][_0-9]*\n )\n | # Hexadecimal\n (0[xX]_*[0-9a-fA-F][_0-9a-fA-F]*\\.[0-9a-fA-F][_0-9a-fA-F]*(?:[pP][-+]?[0-9][_0-9]*)?\n |0[xX]_*[0-9a-fA-F][_0-9a-fA-F]*[pP][-+]?[0-9][_0-9]*\n )\n )\\b(?!')"
},
forall: {
begin:
"(?x)\n # Alphabetic forall\n (?:\n \\b(?<!')\n (forall)\n \\b(?!')\n )\n |\n # Symbolic forall\n (?:\n # Not preceded by a symbol except reserved symbols\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"'']])\n (∀)\n # Not followed by a symbol except reserved symbols\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"'']])\n )",
beginCaptures: {
1: {name: 'keyword.other.forall.bh'},
2: {name: 'keyword.other.forall.bh'}
},
end: '(\\.)|(->|→)',
endCaptures: {
1: {name: 'keyword.operator.period.bh'},
2: {name: 'keyword.operator.arrow.bh'}
},
patterns: [
{include: '#comment_like'},
{include: '#type_variable'},
{include: '#type_signature'}
]
},
fun_decl: {
begin:
"(?x)^(\\s*)\n (primitive\\s+)?\n (type\\s+)?\n (?<fn>\n (?:\n [\\p{Ll}_\\p{Lu}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*\\#*\n | \\(\\s*\n (?!--+\\))\n [\\p{S}\\p{P}&&[^(),:;\\[\\]`{}_\"']]\n [\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]*\n \\s*\\)\n )\n (?:\\s*,\\s*\\g<fn>)?\n )\n \\s*(?<![\\p{S}\\p{P}&&[^\\),;\\]`}_\"']])(::|∷)(?![\\p{S}\\p{P}&&[^\\(,;\\[`{_\"']])\n",
beginCaptures: {
2: {name: 'keyword.other.primitive.bh'},
3: {name: 'keyword.other.type.bh'},
4: {
name: 'entity.name.function.bh',
patterns: [{include: '#reserved_symbol'}, {include: '#prefix_op'}]
},
5: {name: 'keyword.operator.double-colon.bh'}
},
end: '(?x)\n # End of type annotation:\n # To the left of a reserved symbolic keyword such as = or <-\n (?= \n # non-symbolic character\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])\n # symbolic keyword except (->)\n ((<-|←)|(=)|(-<|↢)|(-<<|⤛))\n # non-symbolic character\n ([(),;\\[\\]`{}_"\']|[^\\p{S}\\p{P}])\n )\n # Decreasing indentation:\n |(?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n',
name: 'meta.function.type-declaration.bh',
patterns: [{include: '#type_signature'}]
},
gadt_constructor: {
patterns: [
{
begin:
"(?x)\n ^(\\s*)\n (?:\n (\\b(?<!')[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)\n |(\\()\\s*(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]*)\\s*(\\))\n )",
beginCaptures: {
2: {name: 'constant.other.bh'},
3: {name: 'punctuation.paren.bh'},
4: {name: 'constant.other.operator.prefix.bh'},
5: {name: 'punctuation.paren.bh'}
},
end: "(?x)\n # GADT constructor ends\n (?=\\b(?<!'')deriving\\b(?!')) \n # Decreasing indentation\n |(?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_\"']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n",
patterns: [
{include: '#comment_like'},
{include: '#deriving'},
{include: '#double_colon'},
{include: '#record_decl'},
{include: '#type_signature'}
]
},
{
begin:
"(?x)\n (\\b(?<!')[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}]*) # named constructor\n |(\\()\\s*(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]*)\\s*(\\)) # prefix operator",
beginCaptures: {
1: {name: 'constant.other.bh'},
2: {name: 'punctuation.paren.bh'},
3: {name: 'constant.other.operator.prefix.bh'},
4: {name: 'punctuation.paren.bh'}
},
end: '(?=;|\\}|$)',
patterns: [
{include: '#comment_like'},
{include: '#deriving'},
{include: '#double_colon'},
{include: '#record_decl'},
{include: '#type_signature'}
]
}
]
},
infix_op: {
patterns: [
{
captures: {
1: {name: 'keyword.operator.promotion.bh'},
2: {name: 'entity.name.namespace.bh'},
3: {name: 'keyword.operator.infix.bh'}
},
match:
"(?x)\n ((?:(?<!'')('')?[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}'']*\\.)*)\n (\\#+|[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]+(?<!\\#))"
},
{
captures: {
1: {name: 'punctuation.backtick.bh'},
2: {name: 'entity.name.namespace.bh'},
3: {patterns: [{include: '#data_constructor'}]},
4: {name: 'punctuation.backtick.bh'}
},
match:
"(`)((?:[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}'']*\\.)*)([\\p{Ll}\\p{Lu}_][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}'']*)(`)",
name: 'keyword.operator.function.infix.bh'
}
]
},
inline_phase: {
begin: '\\[',
beginCaptures: {0: {name: 'punctuation.bracket.bh'}},
end: '\\]',
endCaptures: {0: {name: 'punctuation.bracket.bh'}},
name: 'meta.inlining-phase.bh',
patterns: [
{match: '~', name: 'punctuation.tilde.bh'},
{include: '#integer_literals'},
{match: '\\w*', name: 'invalid'}
]
},
integer_literals: {
captures: {
1: {name: 'constant.numeric.integral.decimal.bh'},
2: {name: 'constant.numeric.integral.hexadecimal.bh'},
3: {name: 'constant.numeric.integral.octal.bh'},
4: {name: 'constant.numeric.integral.binary.bh'}
},
match:
"(?x)\n \\b(?<!')\n (?:\n ([0-9][_0-9]*) # Decimal integer\n | (0[xX]_*[0-9a-fA-F][_0-9a-fA-F]*) # Hexadecimal integer\n | (0[oO]_*[0-7][_0-7]*) # Octal integer\n | (0[bB]_*[01][_01]*) # Binary integer\n )\n \\b(?!')"
},
keyword: {
captures: {
1: {name: 'keyword.other.$1.bh'},
2: {name: 'keyword.control.$2.bh'}
},
match:
"\\b(?<!')(?:(where|when|let|letseq|in)|(do|module|rules|action|if|then|else|case(?:s)?|of|verilog|synthesize))\\b(?!')"
},
layout_herald: {
begin:
"(?x)\n (?:(?<!')\\b(?:(where|let|letseq|do|module|rules|action)|(of))|(\\\\\\s*case(?:s)?))\n \\s*(\\{)(?!-)",
beginCaptures: {
1: {name: 'keyword.other.$1.bh'},
2: {name: 'keyword.control.of.bh'},
3: {name: 'keyword.control.lambda-case.bh'},
4: {name: 'punctuation.brace.bh'}
},
end: '(\\})',
endCaptures: {1: {name: 'punctuation.brace.bh'}},
patterns: [
{include: '$self'},
{match: ';', name: 'punctuation.semicolon.bh'}
]
},
numeric_literals: {
patterns: [{include: '#float_literals'}, {include: '#integer_literals'}]
},
overloaded_label: {
patterns: [
{
captures: {
1: {name: 'keyword.operator.prefix.hash.bh'},
2: {patterns: [{include: '#string_literal'}]}
},
match:
'(?x) \n (?<![\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}\\p{S}\\p{P}&&[^(,;\\[`{]]) # Disallow closing characters\n (\\#)\n (?:\n # String\n ("(?:\\\\"|[^"])*")\n # Sequence of allowed label identifiers\n |[\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}\'\\.]+\n )',
name: 'entity.name.label.bh'
}
]
},
package_exports: {
applyEndPatternLast: true,
begin: '\\(',
beginCaptures: {0: {name: 'punctuation.paren.bh'}},
end: '\\)',
endCaptures: {0: {name: 'punctuation.paren.bh'}},
name: 'meta.declaration.exports.bh',
patterns: [
{include: '#comment_like'},
{
captures: {1: {name: 'keyword.other.package.bh'}},
match: "\\b(?<!')(package)\\b(?!')"
},
{include: '#comma'},
{include: '#export_constructs'},
{
begin: '\\(',
beginCaptures: {0: {name: 'punctuation.paren.bh'}},
end: '\\)',
endCaptures: {0: {name: 'punctuation.paren.bh'}},
patterns: [
{include: '#comment_like'},
{include: '#record_wildcard'},
{
match:
'(\\()\\s*(:[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]*)\\s*(\\))',
name: 'constant.other.operator.prefix.bh'
},
{include: '#export_constructs'},
{include: '#comma'}
]
}
]
},
package_name: {
match:
"(?<conid>[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*(\\.\\g<conid>)?)",
name: 'entity.name.namespace.bh'
},
pragma: {
begin: '\\{-#',
end: '#-\\}',
name: 'meta.preprocessor.bh',
patterns: [
{include: '#comments'},
{
match:
"(?xi) \\b(?<!')\n (synthesize|verilog|noReady|alwaysEnabled|parameter|no_default_clock|no_default_reset|gate_input_clocks|clock_family|clock_prefix|gate_prefix|reset_prefix|alwaysReady|noReady|alwaysEnabled|scanInsert|bitBlast|CLK|RSTN|options|deprecate|properties)\\b(?!')",
name: 'keyword.other.preprocessor.pragma.bh'
},
{
match:
"(?xi) \\b(?<!')\n (prefixs?|arg_names|ready|enable|result|always_ready|always_enabled)\\b(?!')",
name: 'keyword.other.preprocessor.pragma.bh'
}
]
},
prefix_op: {
patterns: [
{
captures: {
1: {name: 'punctuation.paren.bh'},
2: {name: 'entity.name.function.infix.bh'},
3: {name: 'punctuation.paren.bh'}
},
match:
'(?x)\n (\\()\\s*(?!(?:--+|\\.\\.)\\))(\\#+|[\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']]+(?<!\\#))\\s*(\\))'
}
]
},
qualifier: {
match: "\\b(?<!')[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*\\.",
name: 'entity.name.namespace.bh'
},
quasi_quote: {
patterns: [
{
begin: '(?x)\n (\\[)\n (e|d|p)?\n (\\|(?:\\|(?!\\]))?)',
beginCaptures: {
1: {name: 'keyword.operator.quasi-quotation.begin.bh'},
2: {name: 'entity.name.quasi-quoter.bh'},
3: {name: 'keyword.operator.quasi-quotation.begin.bh'}
},
end: '\\3\\]',
endCaptures: {0: {name: 'keyword.operator.quasi-quotation.end.bh'}},
name: 'meta.quasi-quotation.bh',
patterns: [{include: '$self'}]
},
{
begin: '(?x)\n (\\[)\n (t)\n (\\|(?:\\|(?!\\]))?)',
beginCaptures: {
1: {name: 'keyword.operator.quasi-quotation.begin.bh'},
2: {name: 'entity.name.quasi-quoter.bh'},
3: {name: 'keyword.operator.quasi-quotation.begin.bh'}
},
end: '\\3\\]',
endCaptures: {0: {name: 'keyword.operator.quasi-quotation.end.bh'}},
name: 'meta.quasi-quotation.bh',
patterns: [{include: '#type_signature'}]
},
{
begin:
"(?x)\n (\\[)\n (?:(\\$\\$)|(\\$))?\n (?!'\\|') # Don't parse ['|'...] as a quasi quotation\n ((?:[\\p{Lu}\\p{Lt}][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*\\.)*) # Optional qualifier\n ((?:[^\\s\\p{S}\\p{P}]|['_])*) # Quasi-quoter\n (\\|)",
beginCaptures: {
1: {name: 'keyword.operator.quasi-quotation.begin.bh'},
2: {name: 'keyword.operator.prefix.double-dollar.bh'},
3: {name: 'keyword.operator.prefix.dollar.bh'},
4: {name: 'entity.name.namespace.bh'},
5: {name: 'entity.name.quasi-quoter.bh'},
6: {name: 'keyword.operator.quasi-quotation.begin.bh'}
},
end: '\\|\\]',
endCaptures: {0: {name: 'keyword.operator.quasi-quotation.end.bh'}},
name: 'meta.quasi-quotation.bh meta.embedded.block.$5'
}
]
},
record: {
begin: '({)(?!-)',
beginCaptures: {1: {name: 'punctuation.brace.bh'}},
end: '(?<!-)(})',
endCaptures: {1: {name: 'punctuation.brace.bh'}},
name: 'meta.record.bh',
patterns: [{include: '#comment_like'}, {include: '#record_field'}]
},
record_decl: {
begin: '({)(?!-)',
beginCaptures: {1: {name: 'punctuation.brace.bh'}},
end: '(?<!-)(})',
endCaptures: {1: {name: 'punctuation.brace.bh'}},
name: 'meta.record.definition.bh',
patterns: [{include: '#comment_like'}, {include: '#record_decl_field'}]
},
record_decl_field: {
begin:
"(?x)\n (?:([\\p{Ll}_][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}']*)\n |(\\()\\s*([\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]+)\\s*(\\))\n )\n",
beginCaptures: {
1: {name: 'variable.other.member.definition.bh'},
2: {name: 'punctuation.paren.bh'},
3: {name: 'variable.other.member.definition.bh'},
4: {name: 'punctuation.paren.bh'}
},
end: '(,)|(?=})',
endCaptures: {1: {name: 'punctuation.comma.bh'}},
patterns: [
{include: '#comment_like'},
{include: '#comma'},
{include: '#double_colon'},
{include: '#type_signature'},
{include: '#record_decl_field'}
]
},
record_field: {
patterns: [
{
begin:
"(?x)\n (?:([\\p{Ll}\\p{Lu}_][\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}\\.']*)\n |(\\()\\s*([\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']]+)\\s*(\\))\n )\n",
beginCaptures: {
1: {
name: 'variable.other.member.bh',
patterns: [{include: '#qualifier'}]
},
2: {name: 'punctuation.paren.bh'},
3: {name: 'variable.other.member.bh'},
4: {name: 'punctuation.paren.bh'}
},
end: '(,)|(?=})',
endCaptures: {1: {name: 'punctuation.comma.bh'}},
patterns: [
{include: '#comment_like'},
{include: '#comma'},
{include: '$self'}
]
},
{include: '#record_wildcard'}
]
},
record_wildcard: {
captures: {1: {name: 'variable.other.member.wildcard.bh'}},
match:
'(?x)\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])\n (\\.\\.)\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_"\']])'
},
reserved_symbol: {
patterns: [
{
captures: {
1: {name: 'keyword.operator.double-dot.bh'},
10: {name: 'keyword.operator.arrow.tail.bh'},
11: {name: 'keyword.operator.arrow.tail.double.bh'},
2: {name: 'keyword.operator.colon.bh'},
3: {name: 'keyword.operator.eq.bh'},
4: {name: 'keyword.operator.lambda.bh'},
5: {name: 'keyword.operator.pipe.bh'},
6: {name: 'keyword.operator.arrow.left.bh'},
7: {name: 'keyword.operator.arrow.bh'},
8: {name: 'keyword.operator.arrow.left.tail.bh'},
9: {name: 'keyword.operator.arrow.left.tail.double.bh'}
},
match:
"(?x)\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"'']])\n (?:\n (\\.\\.)\n |(:)\n |(=)\n |(\\\\) # λ not reserved as it is a letter\n |(\\|)\n |(<-|←)\n |(->|→)\n |(-<|↢)\n |(-<<|⤛)\n |(>-|⤚)\n |(>>-|⤜)\n )\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"'']])"
},
{
captures: {1: {name: 'keyword.operator.postfix.hash.bh'}},
match:
'(?x)\n (?<=[\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}\\p{S}\\p{P}&&[^\\#,;\\[`{]]) # Require closing characters\n (\\#+)\n (?![\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}\\p{S}\\p{P}&&[^),;\\]`}]]) # Disallow opening character'
},
{
captures: {1: {name: 'keyword.operator.infix.tight.at.bh'}},
match:
"(?x)\n (?<=[\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}'\\)\\}\\]]) # Require closing characters\n (@)\n (?=[\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}'\\(\\[\\{]) # Require opening character"
},
{
captures: {
1: {name: 'keyword.operator.prefix.tilde.bh'},
2: {name: 'keyword.operator.prefix.bang.bh'},
3: {name: 'keyword.operator.prefix.minus.bh'},
4: {name: 'keyword.operator.prefix.double-dollar.bh'},
5: {name: 'keyword.operator.prefix.dollar.bh'},
6: {name: 'keyword.operator.prefix.modifier.bh'}
},
match:
"(?x)\n (?<![\\p{Ll}_\\p{Lu}\\p{Lt}\\p{Nd}\\p{S}\\p{P}&&[^(,;\\[`{]]) # Disallow closing characters\n (?:(~)|(!)|(-)|(\\$\\$)|(\\$)|(%))\n (?=[\\p{Ll}_'\\p{Lu}\\p{Lt}\\p{Nd}\\(\\{\\[]) # Require opening character (non operator symbol)"
}
]
},
role_annotation: {
patterns: [
{
begin: "^(\\s*)(type)\\s+(role)\\b(?!')",
beginCaptures: {
2: {name: 'keyword.other.type.bh'},
3: {name: 'keyword.other.role.bh'}
},
end: '(?x) # Detect end of block by decreasing indentation:\n (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s+\\S # - more indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_"\']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )',
name: 'meta.role-annotation.bh',
patterns: [
{include: '#comment_like'},
{include: '#type_constructor'},
{
captures: {1: {name: 'keyword.other.role.$1.bh'}},
match: "\\b(?<!')(nominal|representational|phantom)\\b(?!')"
}
]
}
]
},
start_type_signature: {
patterns: [
{
begin: '^(\\s*)(::|∷)(?![\\p{S}\\p{P}&&[^\\(,;\\[`{_"\']])\\s*',
beginCaptures: {2: {name: 'keyword.operator.double-colon.bh'}},
end: "(?x)\n # End type annotation when seeing one of:\n (?=\n \\#?\\) # closing parenthesis\n |\\] # closing bracket\n |, # comma\n |(?<!')\\b(in|then|else|of)\\b(?!') # keyword\n | # symbolic keyword except (->)\n (?<![\\p{S}\\p{P}&&[^(),;\\[\\]`{}_\"']])\n (?:\n (\\\\|λ)\n |(<-|←)\n |(=)\n |(-<|↢)\n |(-<<|⤛)\n )\n ([(),;\\[\\]`{}_\"']|[^\\p{S}\\p{P}])\n |(\\#|@)-\\} # End of annotation block (pragma)\n # Decreasing indentation:\n | (?=\\}|;) # Explicit indentation\n |^(?! # Implicit indentation: end match on newline *unless* the new line is either:\n \\1\\s*\\S # - equally indented, or\n | \\s* # - starts with whitespace, followed by:\n (?: $ # - the end of the line (i.e. empty line), or\n |\\{-[^@] # - the start of a block comment, or\n |--+ # - the start of a single-line comment.\n (?![\\p{S}\\p{P}&&[^(),;\\[\\]{}`_\"']]).*$) # non-symbol\n # The double dash may not be followed by other operator characters\n # (then it would be an operator, not a comment)\n )\n )",
name: 'meta.type-declaration.bh',
patterns: [{include: '#type_signature'}]
},
{
begin:
'(?<![\\p{S}\\p{P}&&[^\\(,;\\[`{_"\']])(::|∷)(?![\\p{S}\\p{P}&&[^\\(,;\\[`{_"\']])',
beginCaptures: {1: {name: 'keyword.operator.double-colon.bh'}},
end: "(?x)\n # End type annotation when seeing one of:\n (?=\n \\#?\\)