Fix: merge conflict
[myslice.git] / to-be-integrated / third-party / codemirror-3.15 / mode / haskell / haskell.js
1 CodeMirror.defineMode("haskell", function() {
2
3   function switchState(source, setState, f) {
4     setState(f);
5     return f(source, setState);
6   }
7
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
18
19   function normal(source, setState) {
20     if (source.eatWhile(whiteCharRE)) {
21       return null;
22     }
23
24     var ch = source.next();
25     if (specialRE.test(ch)) {
26       if (ch == '{' && source.eat('-')) {
27         var t = "comment";
28         if (source.eat('#')) {
29           t = "meta";
30         }
31         return switchState(source, setState, ncomment(t, 1));
32       }
33       return null;
34     }
35
36     if (ch == '\'') {
37       if (source.eat('\\')) {
38         source.next();  // should handle other escapes here
39       }
40       else {
41         source.next();
42       }
43       if (source.eat('\'')) {
44         return "string";
45       }
46       return "error";
47     }
48
49     if (ch == '"') {
50       return switchState(source, setState, stringLiteral);
51     }
52
53     if (largeRE.test(ch)) {
54       source.eatWhile(idRE);
55       if (source.eat('.')) {
56         return "qualifier";
57       }
58       return "variable-2";
59     }
60
61     if (smallRE.test(ch)) {
62       source.eatWhile(idRE);
63       return "variable";
64     }
65
66     if (digitRE.test(ch)) {
67       if (ch == '0') {
68         if (source.eat(/[xX]/)) {
69           source.eatWhile(hexitRE); // should require at least 1
70           return "integer";
71         }
72         if (source.eat(/[oO]/)) {
73           source.eatWhile(octitRE); // should require at least 1
74           return "number";
75         }
76       }
77       source.eatWhile(digitRE);
78       var t = "number";
79       if (source.eat('.')) {
80         t = "number";
81         source.eatWhile(digitRE); // should require at least 1
82       }
83       if (source.eat(/[eE]/)) {
84         t = "number";
85         source.eat(/[-+]/);
86         source.eatWhile(digitRE); // should require at least 1
87       }
88       return t;
89     }
90
91     if (symbolRE.test(ch)) {
92       if (ch == '-' && source.eat(/-/)) {
93         source.eatWhile(/-/);
94         if (!source.eat(symbolRE)) {
95           source.skipToEnd();
96           return "comment";
97         }
98       }
99       var t = "variable";
100       if (ch == ':') {
101         t = "variable-2";
102       }
103       source.eatWhile(symbolRE);
104       return t;
105     }
106
107     return "error";
108   }
109
110   function ncomment(type, nest) {
111     if (nest == 0) {
112       return normal;
113     }
114     return function(source, setState) {
115       var currNest = nest;
116       while (!source.eol()) {
117         var ch = source.next();
118         if (ch == '{' && source.eat('-')) {
119           ++currNest;
120         }
121         else if (ch == '-' && source.eat('}')) {
122           --currNest;
123           if (currNest == 0) {
124             setState(normal);
125             return type;
126           }
127         }
128       }
129       setState(ncomment(type, currNest));
130       return type;
131     };
132   }
133
134   function stringLiteral(source, setState) {
135     while (!source.eol()) {
136       var ch = source.next();
137       if (ch == '"') {
138         setState(normal);
139         return "string";
140       }
141       if (ch == '\\') {
142         if (source.eol() || source.eat(whiteCharRE)) {
143           setState(stringGap);
144           return "string";
145         }
146         if (source.eat('&')) {
147         }
148         else {
149           source.next(); // should handle other escapes here
150         }
151       }
152     }
153     setState(normal);
154     return "error";
155   }
156
157   function stringGap(source, setState) {
158     if (source.eat('\\')) {
159       return switchState(source, setState, stringLiteral);
160     }
161     source.next();
162     setState(normal);
163     return "error";
164   }
165
166
167   var wellKnownWords = (function() {
168     var wkw = {};
169     function setType(t) {
170       return function () {
171         for (var i = 0; i < arguments.length; i++)
172           wkw[arguments[i]] = t;
173       };
174     }
175
176     setType("keyword")(
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", "_");
180
181     setType("keyword")(
182       "\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>");
183
184     setType("builtin")(
185       "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
186       "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");
187
188     setType("builtin")(
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",
194       "String", "True");
195
196     setType("builtin")(
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");
223
224     return wkw;
225   })();
226
227
228
229   return {
230     startState: function ()  { return { f: normal }; },
231     copyState:  function (s) { return { f: s.f }; },
232
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;
237     },
238
239     blockCommentStart: "{-",
240     blockCommentEnd: "-}",
241     lineComment: "--"
242   };
243
244 });
245
246 CodeMirror.defineMIME("text/x-haskell", "haskell");