Mercurial
comparison .cms/lib/codemirror/mode/haskell/haskell.js @ 0:78edf6b517a0 draft
24.10
author | Coffee CMS <info@coffee-cms.ru> |
---|---|
date | Fri, 11 Oct 2024 22:40:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:78edf6b517a0 |
---|---|
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others | |
2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE | |
3 | |
4 (function(mod) { | |
5 if (typeof exports == "object" && typeof module == "object") // CommonJS | |
6 mod(require("../../lib/codemirror")); | |
7 else if (typeof define == "function" && define.amd) // AMD | |
8 define(["../../lib/codemirror"], mod); | |
9 else // Plain browser env | |
10 mod(CodeMirror); | |
11 })(function(CodeMirror) { | |
12 "use strict"; | |
13 | |
14 CodeMirror.defineMode("haskell", function(_config, modeConfig) { | |
15 | |
16 function switchState(source, setState, f) { | |
17 setState(f); | |
18 return f(source, setState); | |
19 } | |
20 | |
21 // These should all be Unicode extended, as per the Haskell 2010 report | |
22 var smallRE = /[a-z_]/; | |
23 var largeRE = /[A-Z]/; | |
24 var digitRE = /\d/; | |
25 var hexitRE = /[0-9A-Fa-f]/; | |
26 var octitRE = /[0-7]/; | |
27 var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/; | |
28 var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/; | |
29 var specialRE = /[(),;[\]`{}]/; | |
30 var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer | |
31 | |
32 function normal(source, setState) { | |
33 if (source.eatWhile(whiteCharRE)) { | |
34 return null; | |
35 } | |
36 | |
37 var ch = source.next(); | |
38 if (specialRE.test(ch)) { | |
39 if (ch == '{' && source.eat('-')) { | |
40 var t = "comment"; | |
41 if (source.eat('#')) { | |
42 t = "meta"; | |
43 } | |
44 return switchState(source, setState, ncomment(t, 1)); | |
45 } | |
46 return null; | |
47 } | |
48 | |
49 if (ch == '\'') { | |
50 if (source.eat('\\')) { | |
51 source.next(); // should handle other escapes here | |
52 } | |
53 else { | |
54 source.next(); | |
55 } | |
56 if (source.eat('\'')) { | |
57 return "string"; | |
58 } | |
59 return "string error"; | |
60 } | |
61 | |
62 if (ch == '"') { | |
63 return switchState(source, setState, stringLiteral); | |
64 } | |
65 | |
66 if (largeRE.test(ch)) { | |
67 source.eatWhile(idRE); | |
68 if (source.eat('.')) { | |
69 return "qualifier"; | |
70 } | |
71 return "variable-2"; | |
72 } | |
73 | |
74 if (smallRE.test(ch)) { | |
75 source.eatWhile(idRE); | |
76 return "variable"; | |
77 } | |
78 | |
79 if (digitRE.test(ch)) { | |
80 if (ch == '0') { | |
81 if (source.eat(/[xX]/)) { | |
82 source.eatWhile(hexitRE); // should require at least 1 | |
83 return "integer"; | |
84 } | |
85 if (source.eat(/[oO]/)) { | |
86 source.eatWhile(octitRE); // should require at least 1 | |
87 return "number"; | |
88 } | |
89 } | |
90 source.eatWhile(digitRE); | |
91 var t = "number"; | |
92 if (source.match(/^\.\d+/)) { | |
93 t = "number"; | |
94 } | |
95 if (source.eat(/[eE]/)) { | |
96 t = "number"; | |
97 source.eat(/[-+]/); | |
98 source.eatWhile(digitRE); // should require at least 1 | |
99 } | |
100 return t; | |
101 } | |
102 | |
103 if (ch == "." && source.eat(".")) | |
104 return "keyword"; | |
105 | |
106 if (symbolRE.test(ch)) { | |
107 if (ch == '-' && source.eat(/-/)) { | |
108 source.eatWhile(/-/); | |
109 if (!source.eat(symbolRE)) { | |
110 source.skipToEnd(); | |
111 return "comment"; | |
112 } | |
113 } | |
114 var t = "variable"; | |
115 if (ch == ':') { | |
116 t = "variable-2"; | |
117 } | |
118 source.eatWhile(symbolRE); | |
119 return t; | |
120 } | |
121 | |
122 return "error"; | |
123 } | |
124 | |
125 function ncomment(type, nest) { | |
126 if (nest == 0) { | |
127 return normal; | |
128 } | |
129 return function(source, setState) { | |
130 var currNest = nest; | |
131 while (!source.eol()) { | |
132 var ch = source.next(); | |
133 if (ch == '{' && source.eat('-')) { | |
134 ++currNest; | |
135 } | |
136 else if (ch == '-' && source.eat('}')) { | |
137 --currNest; | |
138 if (currNest == 0) { | |
139 setState(normal); | |
140 return type; | |
141 } | |
142 } | |
143 } | |
144 setState(ncomment(type, currNest)); | |
145 return type; | |
146 }; | |
147 } | |
148 | |
149 function stringLiteral(source, setState) { | |
150 while (!source.eol()) { | |
151 var ch = source.next(); | |
152 if (ch == '"') { | |
153 setState(normal); | |
154 return "string"; | |
155 } | |
156 if (ch == '\\') { | |
157 if (source.eol() || source.eat(whiteCharRE)) { | |
158 setState(stringGap); | |
159 return "string"; | |
160 } | |
161 if (source.eat('&')) { | |
162 } | |
163 else { | |
164 source.next(); // should handle other escapes here | |
165 } | |
166 } | |
167 } | |
168 setState(normal); | |
169 return "string error"; | |
170 } | |
171 | |
172 function stringGap(source, setState) { | |
173 if (source.eat('\\')) { | |
174 return switchState(source, setState, stringLiteral); | |
175 } | |
176 source.next(); | |
177 setState(normal); | |
178 return "error"; | |
179 } | |
180 | |
181 | |
182 var wellKnownWords = (function() { | |
183 var wkw = {}; | |
184 function setType(t) { | |
185 return function () { | |
186 for (var i = 0; i < arguments.length; i++) | |
187 wkw[arguments[i]] = t; | |
188 }; | |
189 } | |
190 | |
191 setType("keyword")( | |
192 "case", "class", "data", "default", "deriving", "do", "else", "foreign", | |
193 "if", "import", "in", "infix", "infixl", "infixr", "instance", "let", | |
194 "module", "newtype", "of", "then", "type", "where", "_"); | |
195 | |
196 setType("keyword")( | |
197 "\.\.", ":", "::", "=", "\\", "<-", "->", "@", "~", "=>"); | |
198 | |
199 setType("builtin")( | |
200 "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<*", "<=", | |
201 "<$>", "<*>", "=<<", "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", | |
202 "*>", "**"); | |
203 | |
204 setType("builtin")( | |
205 "Applicative", "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", | |
206 "Eq", "False", "FilePath", "Float", "Floating", "Fractional", "Functor", | |
207 "GT", "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left", | |
208 "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read", | |
209 "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS", | |
210 "String", "True"); | |
211 | |
212 setType("builtin")( | |
213 "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf", | |
214 "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling", | |
215 "compare", "concat", "concatMap", "const", "cos", "cosh", "curry", | |
216 "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either", | |
217 "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo", | |
218 "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", | |
219 "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap", | |
220 "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger", | |
221 "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents", | |
222 "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized", | |
223 "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last", | |
224 "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map", | |
225 "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound", | |
226 "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or", | |
227 "otherwise", "pi", "pred", "print", "product", "properFraction", "pure", | |
228 "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile", | |
229 "readIO", "readList", "readLn", "readParen", "reads", "readsPrec", | |
230 "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse", | |
231 "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", | |
232 "sequence", "sequence_", "show", "showChar", "showList", "showParen", | |
233 "showString", "shows", "showsPrec", "significand", "signum", "sin", | |
234 "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum", | |
235 "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger", | |
236 "toRational", "truncate", "uncurry", "undefined", "unlines", "until", | |
237 "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip", | |
238 "zip3", "zipWith", "zipWith3"); | |
239 | |
240 var override = modeConfig.overrideKeywords; | |
241 if (override) for (var word in override) if (override.hasOwnProperty(word)) | |
242 wkw[word] = override[word]; | |
243 | |
244 return wkw; | |
245 })(); | |
246 | |
247 | |
248 | |
249 return { | |
250 startState: function () { return { f: normal }; }, | |
251 copyState: function (s) { return { f: s.f }; }, | |
252 | |
253 token: function(stream, state) { | |
254 var t = state.f(stream, function(s) { state.f = s; }); | |
255 var w = stream.current(); | |
256 return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t; | |
257 }, | |
258 | |
259 blockCommentStart: "{-", | |
260 blockCommentEnd: "-}", | |
261 lineComment: "--" | |
262 }; | |
263 | |
264 }); | |
265 | |
266 CodeMirror.defineMIME("text/x-haskell", "haskell"); | |
267 | |
268 }); |