1
CodeMirror.defineMode("haskell", function(cmCfg, modeCfg) {
3
function switchState(source, setState, f) {
5
return f(source, setState);
8
// These should all be Unicode extended, as per the Haskell 2010 report
9
var smallRE = /[a-z_]/;
10
var largeRE = /[A-Z]/;
11
var digitRE = /[0-9]/;
12
var hexitRE = /[0-9A-Fa-f]/;
13
var octitRE = /[0-7]/;
14
var idRE = /[a-z_A-Z0-9']/;
15
var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
16
var specialRE = /[(),;[\]`{}]/;
17
var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
19
function normal(source, setState) {
20
if (source.eatWhile(whiteCharRE)) {
24
var ch = source.next();
25
if (specialRE.test(ch)) {
26
if (ch == '{' && source.eat('-')) {
28
if (source.eat('#')) {
31
return switchState(source, setState, ncomment(t, 1));
37
if (source.eat('\\')) {
38
source.next(); // should handle other escapes here
43
if (source.eat('\'')) {
50
return switchState(source, setState, stringLiteral);
53
if (largeRE.test(ch)) {
54
source.eatWhile(idRE);
55
if (source.eat('.')) {
61
if (smallRE.test(ch)) {
62
source.eatWhile(idRE);
66
if (digitRE.test(ch)) {
68
if (source.eat(/[xX]/)) {
69
source.eatWhile(hexitRE); // should require at least 1
72
if (source.eat(/[oO]/)) {
73
source.eatWhile(octitRE); // should require at least 1
77
source.eatWhile(digitRE);
79
if (source.eat('.')) {
81
source.eatWhile(digitRE); // should require at least 1
83
if (source.eat(/[eE]/)) {
86
source.eatWhile(digitRE); // should require at least 1
91
if (symbolRE.test(ch)) {
92
if (ch == '-' && source.eat(/-/)) {
94
if (!source.eat(symbolRE)) {
103
source.eatWhile(symbolRE);
110
function ncomment(type, nest) {
114
return function(source, setState) {
116
while (!source.eol()) {
117
var ch = source.next();
118
if (ch == '{' && source.eat('-')) {
121
else if (ch == '-' && source.eat('}')) {
129
setState(ncomment(type, currNest));
134
function stringLiteral(source, setState) {
135
while (!source.eol()) {
136
var ch = source.next();
142
if (source.eol() || source.eat(whiteCharRE)) {
146
if (source.eat('&')) {
149
source.next(); // should handle other escapes here
157
function stringGap(source, setState) {
158
if (source.eat('\\')) {
159
return switchState(source, setState, stringLiteral);
167
var wellKnownWords = (function() {
169
function setType(t) {
171
for (var i = 0; i < arguments.length; i++)
172
wkw[arguments[i]] = t;
177
"case", "class", "data", "default", "deriving", "do", "else", "foreign",
178
"if", "import", "in", "infix", "infixl", "infixr", "instance", "let",
179
"module", "newtype", "of", "then", "type", "where", "_");
182
"\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>");
185
"!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
186
"==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");
189
"Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
190
"False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
191
"IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
192
"Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
193
"ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
197
"abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
198
"asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
199
"compare", "concat", "concatMap", "const", "cos", "cosh", "curry",
200
"cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either",
201
"elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
202
"enumFromTo", "error", "even", "exp", "exponent", "fail", "filter",
203
"flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap",
204
"foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger",
205
"fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents",
206
"getLine", "head", "id", "init", "interact", "ioError", "isDenormalized",
207
"isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last",
208
"lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
209
"mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
210
"minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
211
"otherwise", "pi", "pred", "print", "product", "properFraction",
212
"putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
213
"readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
214
"realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",
215
"round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq",
216
"sequence", "sequence_", "show", "showChar", "showList", "showParen",
217
"showString", "shows", "showsPrec", "significand", "signum", "sin",
218
"sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum",
219
"tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger",
220
"toRational", "truncate", "uncurry", "undefined", "unlines", "until",
221
"unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
222
"zip3", "zipWith", "zipWith3");
230
startState: function () { return { f: normal }; },
231
copyState: function (s) { return { f: s.f }; },
233
token: function(stream, state) {
234
var t = state.f(stream, function(s) { state.f = s; });
235
var w = stream.current();
236
return (w in wellKnownWords) ? wellKnownWords[w] : t;
242
CodeMirror.defineMIME("text/x-haskell", "haskell");