Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
776 lars 1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: http://codemirror.net/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 "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 "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
    setType("builtin")(
204
      "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
205
      "False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
206
      "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
207
      "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
208
      "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
209
      "String", "True");
210
 
211
    setType("builtin")(
212
      "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
213
      "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
214
      "compare", "concat", "concatMap", "const", "cos", "cosh", "curry",
215
      "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either",
216
      "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
217
      "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter",
218
      "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap",
219
      "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger",
220
      "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents",
221
      "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized",
222
      "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last",
223
      "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
224
      "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
225
      "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
226
      "otherwise", "pi", "pred", "print", "product", "properFraction",
227
      "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
228
      "readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
229
      "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",
230
      "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq",
231
      "sequence", "sequence_", "show", "showChar", "showList", "showParen",
232
      "showString", "shows", "showsPrec", "significand", "signum", "sin",
233
      "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum",
234
      "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger",
235
      "toRational", "truncate", "uncurry", "undefined", "unlines", "until",
236
      "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
237
      "zip3", "zipWith", "zipWith3");
238
 
239
    var override = modeConfig.overrideKeywords;
240
    if (override) for (var word in override) if (override.hasOwnProperty(word))
241
      wkw[word] = override[word];
242
 
243
    return wkw;
244
  })();
245
 
246
 
247
 
248
  return {
249
    startState: function ()  { return { f: normal }; },
250
    copyState:  function (s) { return { f: s.f }; },
251
 
252
    token: function(stream, state) {
253
      var t = state.f(stream, function(s) { state.f = s; });
254
      var w = stream.current();
255
      return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t;
256
    },
257
 
258
    blockCommentStart: "{-",
259
    blockCommentEnd: "-}",
260
    lineComment: "--"
261
  };
262
 
263
});
264
 
265
CodeMirror.defineMIME("text/x-haskell", "haskell");
266
 
267
});