]> luflow.net public git repositories - flow-web.git/blob - static/highlight/languages/haskell.js
Initial commit.
[flow-web.git] / static / highlight / languages / haskell.js
1 /*! `haskell` grammar compiled for Highlight.js 11.11.1 */
2 (function(){
3 var hljsGrammar = (function () {
4 'use strict';
5
6 /*
7 Language: Haskell
8 Author: Jeremy Hull <sourdrums@gmail.com>
9 Contributors: Zena Treep <zena.treep@gmail.com>
10 Website: https://www.haskell.org
11 Category: functional
12 */
13
14 function haskell(hljs) {
15
16 /* See:
17 - https://www.haskell.org/onlinereport/lexemes.html
18 - https://downloads.haskell.org/ghc/9.0.1/docs/html/users_guide/exts/binary_literals.html
19 - https://downloads.haskell.org/ghc/9.0.1/docs/html/users_guide/exts/numeric_underscores.html
20 - https://downloads.haskell.org/ghc/9.0.1/docs/html/users_guide/exts/hex_float_literals.html
21 */
22 const decimalDigits = '([0-9]_*)+';
23 const hexDigits = '([0-9a-fA-F]_*)+';
24 const binaryDigits = '([01]_*)+';
25 const octalDigits = '([0-7]_*)+';
26 const ascSymbol = '[!#$%&*+.\\/<=>?@\\\\^~-]';
27 const uniSymbol = '(\\p{S}|\\p{P})'; // Symbol or Punctuation
28 const special = '[(),;\\[\\]`|{}]';
29 const symbol = `(${ascSymbol}|(?!(${special}|[_:"']))${uniSymbol})`;
30
31 const COMMENT = { variants: [
32 // Double dash forms a valid comment only if it's not part of legal lexeme.
33 // See: Haskell 98 report: https://www.haskell.org/onlinereport/lexemes.html
34 //
35 // The commented code does the job, but we can't use negative lookbehind,
36 // due to poor support by Safari browser.
37 // > hljs.COMMENT(`(?<!${symbol})--+(?!${symbol})`, '$'),
38 // So instead, we'll add a no-markup rule before the COMMENT rule in the rules list
39 // to match the problematic infix operators that contain double dash.
40 hljs.COMMENT('--+', '$'),
41 hljs.COMMENT(
42 /\{-/,
43 /-\}/,
44 { contains: [ 'self' ] }
45 )
46 ] };
47
48 const PRAGMA = {
49 className: 'meta',
50 begin: /\{-#/,
51 end: /#-\}/
52 };
53
54 const PREPROCESSOR = {
55 className: 'meta',
56 begin: '^#',
57 end: '$'
58 };
59
60 const CONSTRUCTOR = {
61 className: 'type',
62 begin: '\\b[A-Z][\\w\']*', // TODO: other constructors (build-in, infix).
63 relevance: 0
64 };
65
66 const LIST = {
67 begin: '\\(',
68 end: '\\)',
69 illegal: '"',
70 contains: [
71 PRAGMA,
72 PREPROCESSOR,
73 {
74 className: 'type',
75 begin: '\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?'
76 },
77 hljs.inherit(hljs.TITLE_MODE, { begin: '[_a-z][\\w\']*' }),
78 COMMENT
79 ]
80 };
81
82 const RECORD = {
83 begin: /\{/,
84 end: /\}/,
85 contains: LIST.contains
86 };
87
88 const NUMBER = {
89 className: 'number',
90 relevance: 0,
91 variants: [
92 // decimal floating-point-literal (subsumes decimal-literal)
93 { match: `\\b(${decimalDigits})(\\.(${decimalDigits}))?` + `([eE][+-]?(${decimalDigits}))?\\b` },
94 // hexadecimal floating-point-literal (subsumes hexadecimal-literal)
95 { match: `\\b0[xX]_*(${hexDigits})(\\.(${hexDigits}))?` + `([pP][+-]?(${decimalDigits}))?\\b` },
96 // octal-literal
97 { match: `\\b0[oO](${octalDigits})\\b` },
98 // binary-literal
99 { match: `\\b0[bB](${binaryDigits})\\b` }
100 ]
101 };
102
103 return {
104 name: 'Haskell',
105 aliases: [ 'hs' ],
106 keywords:
107 'let in if then else case of where do module import hiding '
108 + 'qualified type data newtype deriving class instance as default '
109 + 'infix infixl infixr foreign export ccall stdcall cplusplus '
110 + 'jvm dotnet safe unsafe family forall mdo proc rec',
111 unicodeRegex: true,
112 contains: [
113 // Top-level constructions.
114 {
115 beginKeywords: 'module',
116 end: 'where',
117 keywords: 'module where',
118 contains: [
119 LIST,
120 COMMENT
121 ],
122 illegal: '\\W\\.|;'
123 },
124 {
125 begin: '\\bimport\\b',
126 end: '$',
127 keywords: 'import qualified as hiding',
128 contains: [
129 LIST,
130 COMMENT
131 ],
132 illegal: '\\W\\.|;'
133 },
134 {
135 className: 'class',
136 begin: '^(\\s*)?(class|instance)\\b',
137 end: 'where',
138 keywords: 'class family instance where',
139 contains: [
140 CONSTRUCTOR,
141 LIST,
142 COMMENT
143 ]
144 },
145 {
146 className: 'class',
147 begin: '\\b(data|(new)?type)\\b',
148 end: '$',
149 keywords: 'data family type newtype deriving',
150 contains: [
151 PRAGMA,
152 CONSTRUCTOR,
153 LIST,
154 RECORD,
155 COMMENT
156 ]
157 },
158 {
159 beginKeywords: 'default',
160 end: '$',
161 contains: [
162 CONSTRUCTOR,
163 LIST,
164 COMMENT
165 ]
166 },
167 {
168 beginKeywords: 'infix infixl infixr',
169 end: '$',
170 contains: [
171 hljs.C_NUMBER_MODE,
172 COMMENT
173 ]
174 },
175 {
176 begin: '\\bforeign\\b',
177 end: '$',
178 keywords: 'foreign import export ccall stdcall cplusplus jvm '
179 + 'dotnet safe unsafe',
180 contains: [
181 CONSTRUCTOR,
182 hljs.QUOTE_STRING_MODE,
183 COMMENT
184 ]
185 },
186 {
187 className: 'meta',
188 begin: '#!\\/usr\\/bin\\/env\ runhaskell',
189 end: '$'
190 },
191 // "Whitespaces".
192 PRAGMA,
193 PREPROCESSOR,
194
195 // Literals and names.
196
197 // Single characters.
198 {
199 scope: 'string',
200 begin: /'(?=\\?.')/,
201 end: /'/,
202 contains: [
203 {
204 scope: 'char.escape',
205 match: /\\./,
206 },
207 ]
208 },
209 hljs.QUOTE_STRING_MODE,
210 NUMBER,
211 CONSTRUCTOR,
212 hljs.inherit(hljs.TITLE_MODE, { begin: '^[_a-z][\\w\']*' }),
213 // No markup, prevents infix operators from being recognized as comments.
214 { begin: `(?!-)${symbol}--+|--+(?!-)${symbol}`},
215 COMMENT,
216 { // No markup, relevance booster
217 begin: '->|<-' }
218 ]
219 };
220 }
221
222 return haskell;
223
224 })();
225
226 hljs.registerLanguage('haskell', hljsGrammar);
227 })();