~ubuntu-branches/ubuntu/utopic/codemirror-js/utopic

« back to all changes in this revision

Viewing changes to mode/haskell/haskell.js

  • Committer: Package Import Robot
  • Author(s): David Paleino
  • Date: 2012-04-12 12:25:28 UTC
  • Revision ID: package-import@ubuntu.com-20120412122528-8xp5a8frj4h1d3ee
Tags: upstream-2.23
ImportĀ upstreamĀ versionĀ 2.23

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
CodeMirror.defineMode("haskell", function(cmCfg, modeCfg) {
 
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
 
 
240
});
 
241
 
 
242
CodeMirror.defineMIME("text/x-haskell", "haskell");