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

« back to all changes in this revision

Viewing changes to mode/rust/rust.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("rust", function() {
 
2
  var indentUnit = 4, altIndentUnit = 2;
 
3
  var valKeywords = {
 
4
    "if": "if-style", "while": "if-style", "else": "else-style",
 
5
    "do": "else-style", "ret": "else-style", "fail": "else-style",
 
6
    "break": "atom", "cont": "atom", "const": "let", "resource": "fn",
 
7
    "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface",
 
8
    "impl": "impl", "type": "type", "enum": "enum", "mod": "mod",
 
9
    "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op",
 
10
    "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style",
 
11
    "export": "else-style", "copy": "op", "log": "op", "log_err": "op",
 
12
    "use": "op", "bind": "op", "self": "atom"
 
13
  };
 
14
  var typeKeywords = function() {
 
15
    var keywords = {"fn": "fn", "block": "fn", "obj": "obj"};
 
16
    var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" ");
 
17
    for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom";
 
18
    return keywords;
 
19
  }();
 
20
  var operatorChar = /[+\-*&%=<>!?|\.@]/;
 
21
 
 
22
  // Tokenizer
 
23
 
 
24
  // Used as scratch variable to communicate multiple values without
 
25
  // consing up tons of objects.
 
26
  var tcat, content;
 
27
  function r(tc, style) {
 
28
    tcat = tc;
 
29
    return style;
 
30
  }
 
31
 
 
32
  function tokenBase(stream, state) {
 
33
    var ch = stream.next();
 
34
    if (ch == '"') {
 
35
      state.tokenize = tokenString;
 
36
      return state.tokenize(stream, state);
 
37
    }
 
38
    if (ch == "'") {
 
39
      tcat = "atom";
 
40
      if (stream.eat("\\")) {
 
41
        if (stream.skipTo("'")) { stream.next(); return "string"; }
 
42
        else { return "error"; }
 
43
      } else {
 
44
        stream.next();
 
45
        return stream.eat("'") ? "string" : "error";
 
46
      }
 
47
    }
 
48
    if (ch == "/") {
 
49
      if (stream.eat("/")) { stream.skipToEnd(); return "comment"; }
 
50
      if (stream.eat("*")) {
 
51
        state.tokenize = tokenComment(1);
 
52
        return state.tokenize(stream, state);
 
53
      }
 
54
    }
 
55
    if (ch == "#") {
 
56
      if (stream.eat("[")) { tcat = "open-attr"; return null; }
 
57
      stream.eatWhile(/\w/);
 
58
      return r("macro", "meta");
 
59
    }
 
60
    if (ch == ":" && stream.match(":<")) {
 
61
      return r("op", null);
 
62
    }
 
63
    if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) {
 
64
      var flp = false;
 
65
      if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) {
 
66
        stream.eatWhile(/\d/);
 
67
        if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); }
 
68
        if (stream.match(/^e[+\-]?\d+/i)) { flp = true; }
 
69
      }
 
70
      if (flp) stream.match(/^f(?:32|64)/);
 
71
      else stream.match(/^[ui](?:8|16|32|64)/);
 
72
      return r("atom", "number");
 
73
    }
 
74
    if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null);
 
75
    if (ch == "-" && stream.eat(">")) return r("->", null);
 
76
    if (ch.match(operatorChar)) {
 
77
      stream.eatWhile(operatorChar);
 
78
      return r("op", null);
 
79
    }
 
80
    stream.eatWhile(/\w/);
 
81
    content = stream.current();
 
82
    if (stream.match(/^::\w/)) {
 
83
      stream.backUp(1);
 
84
      return r("prefix", "variable-2");
 
85
    }
 
86
    if (state.keywords.propertyIsEnumerable(content))
 
87
      return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword");
 
88
    return r("name", "variable");
 
89
  }
 
90
 
 
91
  function tokenString(stream, state) {
 
92
    var ch, escaped = false;
 
93
    while (ch = stream.next()) {
 
94
      if (ch == '"' && !escaped) {
 
95
        state.tokenize = tokenBase;
 
96
        return r("atom", "string");
 
97
      }
 
98
      escaped = !escaped && ch == "\\";
 
99
    }
 
100
    // Hack to not confuse the parser when a string is split in
 
101
    // pieces.
 
102
    return r("op", "string");
 
103
  }
 
104
 
 
105
  function tokenComment(depth) {
 
106
    return function(stream, state) {
 
107
      var lastCh = null, ch;
 
108
      while (ch = stream.next()) {
 
109
        if (ch == "/" && lastCh == "*") {
 
110
          if (depth == 1) {
 
111
            state.tokenize = tokenBase;
 
112
            break;
 
113
          } else {
 
114
            state.tokenize = tokenComment(depth - 1);
 
115
            return state.tokenize(stream, state);
 
116
          }
 
117
        }
 
118
        if (ch == "*" && lastCh == "/") {
 
119
          state.tokenize = tokenComment(depth + 1);
 
120
          return state.tokenize(stream, state);
 
121
        }
 
122
        lastCh = ch;
 
123
      }
 
124
      return "comment";
 
125
    };
 
126
  }
 
127
 
 
128
  // Parser
 
129
 
 
130
  var cx = {state: null, stream: null, marked: null, cc: null};
 
131
  function pass() {
 
132
    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
 
133
  }
 
134
  function cont() {
 
135
    pass.apply(null, arguments);
 
136
    return true;
 
137
  }
 
138
 
 
139
  function pushlex(type, info) {
 
140
    var result = function() {
 
141
      var state = cx.state;
 
142
      state.lexical = {indented: state.indented, column: cx.stream.column(),
 
143
                       type: type, prev: state.lexical, info: info};
 
144
    };
 
145
    result.lex = true;
 
146
    return result;
 
147
  }
 
148
  function poplex() {
 
149
    var state = cx.state;
 
150
    if (state.lexical.prev) {
 
151
      if (state.lexical.type == ")")
 
152
        state.indented = state.lexical.indented;
 
153
      state.lexical = state.lexical.prev;
 
154
    }
 
155
  }
 
156
  function typecx() { cx.state.keywords = typeKeywords; }
 
157
  function valcx() { cx.state.keywords = valKeywords; }
 
158
  poplex.lex = typecx.lex = valcx.lex = true;
 
159
 
 
160
  function commasep(comb, end) {
 
161
    function more(type) {
 
162
      if (type == ",") return cont(comb, more);
 
163
      if (type == end) return cont();
 
164
      return cont(more);
 
165
    }
 
166
    return function(type) {
 
167
      if (type == end) return cont();
 
168
      return pass(comb, more);
 
169
    };
 
170
  }
 
171
 
 
172
  function stat_of(comb, tag) {
 
173
    return cont(pushlex("stat", tag), comb, poplex, block);
 
174
  }
 
175
  function block(type) {
 
176
    if (type == "}") return cont();
 
177
    if (type == "let") return stat_of(letdef1, "let");
 
178
    if (type == "fn") return stat_of(fndef);
 
179
    if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block);
 
180
    if (type == "enum") return stat_of(enumdef);
 
181
    if (type == "mod") return stat_of(mod);
 
182
    if (type == "iface") return stat_of(iface);
 
183
    if (type == "impl") return stat_of(impl);
 
184
    if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex);
 
185
    if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block);
 
186
    return pass(pushlex("stat"), expression, poplex, endstatement, block);
 
187
  }
 
188
  function endstatement(type) {
 
189
    if (type == ";") return cont();
 
190
    return pass();
 
191
  }
 
192
  function expression(type) {
 
193
    if (type == "atom" || type == "name") return cont(maybeop);
 
194
    if (type == "{") return cont(pushlex("}"), exprbrace, poplex);
 
195
    if (type.match(/[\[\(]/)) return matchBrackets(type, expression);
 
196
    if (type.match(/[\]\)\};,]/)) return pass();
 
197
    if (type == "if-style") return cont(expression, expression);
 
198
    if (type == "else-style" || type == "op") return cont(expression);
 
199
    if (type == "for") return cont(pattern, maybetype, inop, expression, expression);
 
200
    if (type == "alt") return cont(expression, altbody);
 
201
    if (type == "fn") return cont(fndef);
 
202
    if (type == "macro") return cont(macro);
 
203
    return cont();
 
204
  }
 
205
  function maybeop(type) {
 
206
    if (content == ".") return cont(maybeprop);
 
207
    if (content == "::<"){return cont(typarams, maybeop);}
 
208
    if (type == "op" || content == ":") return cont(expression);
 
209
    if (type == "(" || type == "[") return matchBrackets(type, expression);
 
210
    return pass();
 
211
  }
 
212
  function maybeprop(type) {
 
213
    if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}
 
214
    return pass(expression);
 
215
  }
 
216
  function exprbrace(type) {
 
217
    if (type == "op") {
 
218
      if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block);
 
219
      if (content == "||") return cont(poplex, pushlex("}", "block"), block);
 
220
    }
 
221
    if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":"
 
222
                                 && !cx.stream.match("::", false)))
 
223
      return pass(record_of(expression));
 
224
    return pass(block);
 
225
  }
 
226
  function record_of(comb) {
 
227
    function ro(type) {
 
228
      if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);}
 
229
      if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);}
 
230
      if (type == ":") return cont(comb, ro);
 
231
      if (type == "}") return cont();
 
232
      return cont(ro);
 
233
    }
 
234
    return ro;
 
235
  }
 
236
  function blockvars(type) {
 
237
    if (type == "name") {cx.marked = "def"; return cont(blockvars);}
 
238
    if (type == "op" && content == "|") return cont();
 
239
    return cont(blockvars);
 
240
  }
 
241
 
 
242
  function letdef1(type) {
 
243
    if (type.match(/[\]\)\};]/)) return cont();
 
244
    if (content == "=") return cont(expression, letdef2);
 
245
    if (type == ",") return cont(letdef1);
 
246
    return pass(pattern, maybetype, letdef1);
 
247
  }
 
248
  function letdef2(type) {
 
249
    if (type.match(/[\]\)\};,]/)) return pass(letdef1);
 
250
    else return pass(expression, letdef2);
 
251
  }
 
252
  function maybetype(type) {
 
253
    if (type == ":") return cont(typecx, rtype, valcx);
 
254
    return pass();
 
255
  }
 
256
  function inop(type) {
 
257
    if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();}
 
258
    return pass();
 
259
  }
 
260
  function fndef(type) {
 
261
    if (content == "@" || content == "~") {cx.marked = "keyword"; return cont(fndef);}
 
262
    if (type == "name") {cx.marked = "def"; return cont(fndef);}
 
263
    if (content == "<") return cont(typarams, fndef);
 
264
    if (type == "{") return pass(expression);
 
265
    if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef);
 
266
    if (type == "->") return cont(typecx, rtype, valcx, fndef);
 
267
    if (type == ";") return cont();
 
268
    return cont(fndef);
 
269
  }
 
270
  function tydef(type) {
 
271
    if (type == "name") {cx.marked = "def"; return cont(tydef);}
 
272
    if (content == "<") return cont(typarams, tydef);
 
273
    if (content == "=") return cont(typecx, rtype, valcx);
 
274
    return cont(tydef);
 
275
  }
 
276
  function enumdef(type) {
 
277
    if (type == "name") {cx.marked = "def"; return cont(enumdef);}
 
278
    if (content == "<") return cont(typarams, enumdef);
 
279
    if (content == "=") return cont(typecx, rtype, valcx, endstatement);
 
280
    if (type == "{") return cont(pushlex("}"), typecx, enumblock, valcx, poplex);
 
281
    return cont(enumdef);
 
282
  }
 
283
  function enumblock(type) {
 
284
    if (type == "}") return cont();
 
285
    if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, enumblock);
 
286
    if (content.match(/^\w+$/)) cx.marked = "def";
 
287
    return cont(enumblock);
 
288
  }
 
289
  function mod(type) {
 
290
    if (type == "name") {cx.marked = "def"; return cont(mod);}
 
291
    if (type == "{") return cont(pushlex("}"), block, poplex);
 
292
    return pass();
 
293
  }
 
294
  function iface(type) {
 
295
    if (type == "name") {cx.marked = "def"; return cont(iface);}
 
296
    if (content == "<") return cont(typarams, iface);
 
297
    if (type == "{") return cont(pushlex("}"), block, poplex);
 
298
    return pass();
 
299
  }
 
300
  function impl(type) {
 
301
    if (content == "<") return cont(typarams, impl);
 
302
    if (content == "of" || content == "for") {cx.marked = "keyword"; return cont(rtype, impl);}
 
303
    if (type == "name") {cx.marked = "def"; return cont(impl);}
 
304
    if (type == "{") return cont(pushlex("}"), block, poplex);
 
305
    return pass();
 
306
  }
 
307
  function typarams(type) {
 
308
    if (content == ">") return cont();
 
309
    if (content == ",") return cont(typarams);
 
310
    if (content == ":") return cont(rtype, typarams);
 
311
    return pass(rtype, typarams);
 
312
  }
 
313
  function argdef(type) {
 
314
    if (type == "name") {cx.marked = "def"; return cont(argdef);}
 
315
    if (type == ":") return cont(typecx, rtype, valcx);
 
316
    return pass();
 
317
  }
 
318
  function rtype(type) {
 
319
    if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); }
 
320
    if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);}
 
321
    if (type == "atom") return cont(rtypemaybeparam);
 
322
    if (type == "op" || type == "obj") return cont(rtype);
 
323
    if (type == "fn") return cont(fntype);
 
324
    if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex);
 
325
    return matchBrackets(type, rtype);
 
326
  }
 
327
  function rtypemaybeparam(type) {
 
328
    if (content == "<") return cont(typarams);
 
329
    return pass();
 
330
  }
 
331
  function fntype(type) {
 
332
    if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype);
 
333
    if (type == "->") return cont(rtype);
 
334
    return pass();
 
335
  }
 
336
  function pattern(type) {
 
337
    if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);}
 
338
    if (type == "atom") return cont(patternmaybeop);
 
339
    if (type == "op") return cont(pattern);
 
340
    if (type.match(/[\]\)\};,]/)) return pass();
 
341
    return matchBrackets(type, pattern);
 
342
  }
 
343
  function patternmaybeop(type) {
 
344
    if (type == "op" && content == ".") return cont();
 
345
    if (content == "to") {cx.marked = "keyword"; return cont(pattern);}
 
346
    else return pass();
 
347
  }
 
348
  function altbody(type) {
 
349
    if (type == "{") return cont(pushlex("}", "alt"), altblock1, poplex);
 
350
    return pass();
 
351
  }
 
352
  function altblock1(type) {
 
353
    if (type == "}") return cont();
 
354
    if (type == "|") return cont(altblock1);
 
355
    if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock2);}
 
356
    if (type.match(/[\]\);,]/)) return cont(altblock1);
 
357
    return pass(pattern, altblock2);
 
358
  }
 
359
  function altblock2(type) {
 
360
    if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock1);
 
361
    else return pass(altblock1);
 
362
  }
 
363
 
 
364
  function macro(type) {
 
365
    if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression);
 
366
    return pass();
 
367
  }
 
368
  function matchBrackets(type, comb) {
 
369
    if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex);
 
370
    if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex);
 
371
    if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex);
 
372
    return cont();
 
373
  }
 
374
 
 
375
  function parse(state, stream, style) {
 
376
    var cc = state.cc;
 
377
    // Communicate our context to the combinators.
 
378
    // (Less wasteful than consing up a hundred closures on every call.)
 
379
    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
 
380
 
 
381
    while (true) {
 
382
      var combinator = cc.length ? cc.pop() : block;
 
383
      if (combinator(tcat)) {
 
384
        while(cc.length && cc[cc.length - 1].lex)
 
385
          cc.pop()();
 
386
        return cx.marked || style;
 
387
      }
 
388
    }
 
389
  }
 
390
 
 
391
  return {
 
392
    startState: function() {
 
393
      return {
 
394
        tokenize: tokenBase,
 
395
        cc: [],
 
396
        lexical: {indented: -indentUnit, column: 0, type: "top", align: false},
 
397
        keywords: valKeywords,
 
398
        indented: 0
 
399
      };
 
400
    },
 
401
 
 
402
    token: function(stream, state) {
 
403
      if (stream.sol()) {
 
404
        if (!state.lexical.hasOwnProperty("align"))
 
405
          state.lexical.align = false;
 
406
        state.indented = stream.indentation();
 
407
      }
 
408
      if (stream.eatSpace()) return null;
 
409
      tcat = content = null;
 
410
      var style = state.tokenize(stream, state);
 
411
      if (style == "comment") return style;
 
412
      if (!state.lexical.hasOwnProperty("align"))
 
413
        state.lexical.align = true;
 
414
      if (tcat == "prefix") return style;
 
415
      if (!content) content = stream.current();
 
416
      return parse(state, stream, style);
 
417
    },
 
418
 
 
419
    indent: function(state, textAfter) {
 
420
      if (state.tokenize != tokenBase) return 0;
 
421
      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
 
422
          type = lexical.type, closing = firstChar == type;
 
423
      if (type == "stat") return lexical.indented + indentUnit;
 
424
      if (lexical.align) return lexical.column + (closing ? 0 : 1);
 
425
      return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit));
 
426
    },
 
427
 
 
428
    electricChars: "{}"
 
429
  };
 
430
});
 
431
 
 
432
CodeMirror.defineMIME("text/x-rustsrc", "rust");