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("haxe", function(config, parserConfig) {
15
  var indentUnit = config.indentUnit;
16
 
17
  // Tokenizer
18
 
19
  var keywords = function(){
20
    function kw(type) {return {type: type, style: "keyword"};}
21
    var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
22
    var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"};
23
  var type = kw("typedef");
24
    return {
25
      "if": A, "while": A, "else": B, "do": B, "try": B,
26
      "return": C, "break": C, "continue": C, "new": C, "throw": C,
27
      "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"),
28
    "public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"),
29
      "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),
30
      "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
31
      "in": operator, "never": kw("property_access"), "trace":kw("trace"),
32
    "class": type, "abstract":type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,
33
      "true": atom, "false": atom, "null": atom
34
    };
35
  }();
36
 
37
  var isOperatorChar = /[+\-*&%=<>!?|]/;
38
 
39
  function chain(stream, state, f) {
40
    state.tokenize = f;
41
    return f(stream, state);
42
  }
43
 
44
  function nextUntilUnescaped(stream, end) {
45
    var escaped = false, next;
46
    while ((next = stream.next()) != null) {
47
      if (next == end && !escaped)
48
        return false;
49
      escaped = !escaped && next == "\\";
50
    }
51
    return escaped;
52
  }
53
 
54
  // Used as scratch variables to communicate multiple values without
55
  // consing up tons of objects.
56
  var type, content;
57
  function ret(tp, style, cont) {
58
    type = tp; content = cont;
59
    return style;
60
  }
61
 
62
  function haxeTokenBase(stream, state) {
63
    var ch = stream.next();
64
    if (ch == '"' || ch == "'")
65
      return chain(stream, state, haxeTokenString(ch));
66
    else if (/[\[\]{}\(\),;\:\.]/.test(ch))
67
      return ret(ch);
68
    else if (ch == "0" && stream.eat(/x/i)) {
69
      stream.eatWhile(/[\da-f]/i);
70
      return ret("number", "number");
71
    }
72
    else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
73
      stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
74
      return ret("number", "number");
75
    }
76
    else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) {
77
      nextUntilUnescaped(stream, "/");
78
      stream.eatWhile(/[gimsu]/);
79
      return ret("regexp", "string-2");
80
    }
81
    else if (ch == "/") {
82
      if (stream.eat("*")) {
83
        return chain(stream, state, haxeTokenComment);
84
      }
85
      else if (stream.eat("/")) {
86
        stream.skipToEnd();
87
        return ret("comment", "comment");
88
      }
89
      else {
90
        stream.eatWhile(isOperatorChar);
91
        return ret("operator", null, stream.current());
92
      }
93
    }
94
    else if (ch == "#") {
95
        stream.skipToEnd();
96
        return ret("conditional", "meta");
97
    }
98
    else if (ch == "@") {
99
      stream.eat(/:/);
100
      stream.eatWhile(/[\w_]/);
101
      return ret ("metadata", "meta");
102
    }
103
    else if (isOperatorChar.test(ch)) {
104
      stream.eatWhile(isOperatorChar);
105
      return ret("operator", null, stream.current());
106
    }
107
    else {
108
    var word;
109
    if(/[A-Z]/.test(ch))
110
    {
111
      stream.eatWhile(/[\w_<>]/);
112
      word = stream.current();
113
      return ret("type", "variable-3", word);
114
    }
115
    else
116
    {
117
        stream.eatWhile(/[\w_]/);
118
        var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
119
        return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
120
                       ret("variable", "variable", word);
121
    }
122
    }
123
  }
124
 
125
  function haxeTokenString(quote) {
126
    return function(stream, state) {
127
      if (!nextUntilUnescaped(stream, quote))
128
        state.tokenize = haxeTokenBase;
129
      return ret("string", "string");
130
    };
131
  }
132
 
133
  function haxeTokenComment(stream, state) {
134
    var maybeEnd = false, ch;
135
    while (ch = stream.next()) {
136
      if (ch == "/" && maybeEnd) {
137
        state.tokenize = haxeTokenBase;
138
        break;
139
      }
140
      maybeEnd = (ch == "*");
141
    }
142
    return ret("comment", "comment");
143
  }
144
 
145
  // Parser
146
 
147
  var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};
148
 
149
  function HaxeLexical(indented, column, type, align, prev, info) {
150
    this.indented = indented;
151
    this.column = column;
152
    this.type = type;
153
    this.prev = prev;
154
    this.info = info;
155
    if (align != null) this.align = align;
156
  }
157
 
158
  function inScope(state, varname) {
159
    for (var v = state.localVars; v; v = v.next)
160
      if (v.name == varname) return true;
161
  }
162
 
163
  function parseHaxe(state, style, type, content, stream) {
164
    var cc = state.cc;
165
    // Communicate our context to the combinators.
166
    // (Less wasteful than consing up a hundred closures on every call.)
167
    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
168
 
169
    if (!state.lexical.hasOwnProperty("align"))
170
      state.lexical.align = true;
171
 
172
    while(true) {
173
      var combinator = cc.length ? cc.pop() : statement;
174
      if (combinator(type, content)) {
175
        while(cc.length && cc[cc.length - 1].lex)
176
          cc.pop()();
177
        if (cx.marked) return cx.marked;
178
        if (type == "variable" && inScope(state, content)) return "variable-2";
179
    if (type == "variable" && imported(state, content)) return "variable-3";
180
        return style;
181
      }
182
    }
183
  }
184
 
185
  function imported(state, typename)
186
  {
187
  if (/[a-z]/.test(typename.charAt(0)))
188
    return false;
189
  var len = state.importedtypes.length;
190
  for (var i = 0; i<len; i++)
191
    if(state.importedtypes[i]==typename) return true;
192
  }
193
 
194
 
195
  function registerimport(importname) {
196
  var state = cx.state;
197
  for (var t = state.importedtypes; t; t = t.next)
198
    if(t.name == importname) return;
199
  state.importedtypes = { name: importname, next: state.importedtypes };
200
  }
201
  // Combinator utils
202
 
203
  var cx = {state: null, column: null, marked: null, cc: null};
204
  function pass() {
205
    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
206
  }
207
  function cont() {
208
    pass.apply(null, arguments);
209
    return true;
210
  }
211
  function register(varname) {
212
    var state = cx.state;
213
    if (state.context) {
214
      cx.marked = "def";
215
      for (var v = state.localVars; v; v = v.next)
216
        if (v.name == varname) return;
217
      state.localVars = {name: varname, next: state.localVars};
218
    }
219
  }
220
 
221
  // Combinators
222
 
223
  var defaultVars = {name: "this", next: null};
224
  function pushcontext() {
225
    if (!cx.state.context) cx.state.localVars = defaultVars;
226
    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
227
  }
228
  function popcontext() {
229
    cx.state.localVars = cx.state.context.vars;
230
    cx.state.context = cx.state.context.prev;
231
  }
232
  function pushlex(type, info) {
233
    var result = function() {
234
      var state = cx.state;
235
      state.lexical = new HaxeLexical(state.indented, cx.stream.column(), type, null, state.lexical, info);
236
    };
237
    result.lex = true;
238
    return result;
239
  }
240
  function poplex() {
241
    var state = cx.state;
242
    if (state.lexical.prev) {
243
      if (state.lexical.type == ")")
244
        state.indented = state.lexical.indented;
245
      state.lexical = state.lexical.prev;
246
    }
247
  }
248
  poplex.lex = true;
249
 
250
  function expect(wanted) {
251
    function f(type) {
252
      if (type == wanted) return cont();
253
      else if (wanted == ";") return pass();
254
      else return cont(f);
255
    };
256
    return f;
257
  }
258
 
259
  function statement(type) {
260
    if (type == "@") return cont(metadef);
261
    if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
262
    if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
263
    if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
264
    if (type == "{") return cont(pushlex("}"), pushcontext, block, poplex, popcontext);
265
    if (type == ";") return cont();
266
    if (type == "attribute") return cont(maybeattribute);
267
    if (type == "function") return cont(functiondef);
268
    if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
269
                                      poplex, statement, poplex);
270
    if (type == "variable") return cont(pushlex("stat"), maybelabel);
271
    if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
272
                                         block, poplex, poplex);
273
    if (type == "case") return cont(expression, expect(":"));
274
    if (type == "default") return cont(expect(":"));
275
    if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
276
                                        statement, poplex, popcontext);
277
    if (type == "import") return cont(importdef, expect(";"));
278
    if (type == "typedef") return cont(typedef);
279
    return pass(pushlex("stat"), expression, expect(";"), poplex);
280
  }
281
  function expression(type) {
282
    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
283
    if (type == "function") return cont(functiondef);
284
    if (type == "keyword c") return cont(maybeexpression);
285
    if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
286
    if (type == "operator") return cont(expression);
287
    if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
288
    if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
289
    return cont();
290
  }
291
  function maybeexpression(type) {
292
    if (type.match(/[;\}\)\],]/)) return pass();
293
    return pass(expression);
294
  }
295
 
296
  function maybeoperator(type, value) {
297
    if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
298
    if (type == "operator" || type == ":") return cont(expression);
299
    if (type == ";") return;
300
    if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
301
    if (type == ".") return cont(property, maybeoperator);
302
    if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
303
  }
304
 
305
  function maybeattribute(type) {
306
    if (type == "attribute") return cont(maybeattribute);
307
    if (type == "function") return cont(functiondef);
308
    if (type == "var") return cont(vardef1);
309
  }
310
 
311
  function metadef(type) {
312
    if(type == ":") return cont(metadef);
313
    if(type == "variable") return cont(metadef);
314
    if(type == "(") return cont(pushlex(")"), commasep(metaargs, ")"), poplex, statement);
315
  }
316
  function metaargs(type) {
317
    if(type == "variable") return cont();
318
  }
319
 
320
  function importdef (type, value) {
321
  if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
322
  else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef);
323
  }
324
 
325
  function typedef (type, value)
326
  {
327
  if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
328
  else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); }
329
  }
330
 
331
  function maybelabel(type) {
332
    if (type == ":") return cont(poplex, statement);
333
    return pass(maybeoperator, expect(";"), poplex);
334
  }
335
  function property(type) {
336
    if (type == "variable") {cx.marked = "property"; return cont();}
337
  }
338
  function objprop(type) {
339
    if (type == "variable") cx.marked = "property";
340
    if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
341
  }
342
  function commasep(what, end) {
343
    function proceed(type) {
344
      if (type == ",") return cont(what, proceed);
345
      if (type == end) return cont();
346
      return cont(expect(end));
347
    }
348
    return function(type) {
349
      if (type == end) return cont();
350
      else return pass(what, proceed);
351
    };
352
  }
353
  function block(type) {
354
    if (type == "}") return cont();
355
    return pass(statement, block);
356
  }
357
  function vardef1(type, value) {
358
    if (type == "variable"){register(value); return cont(typeuse, vardef2);}
359
    return cont();
360
  }
361
  function vardef2(type, value) {
362
    if (value == "=") return cont(expression, vardef2);
363
    if (type == ",") return cont(vardef1);
364
  }
365
  function forspec1(type, value) {
366
  if (type == "variable") {
367
    register(value);
368
  }
369
  return cont(pushlex(")"), pushcontext, forin, expression, poplex, statement, popcontext);
370
  }
371
  function forin(_type, value) {
372
    if (value == "in") return cont();
373
  }
374
  function functiondef(type, value) {
375
    if (type == "variable") {register(value); return cont(functiondef);}
376
    if (value == "new") return cont(functiondef);
377
    if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext);
378
  }
379
  function typeuse(type) {
380
    if(type == ":") return cont(typestring);
381
  }
382
  function typestring(type) {
383
    if(type == "type") return cont();
384
    if(type == "variable") return cont();
385
    if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
386
  }
387
  function typeprop(type) {
388
    if(type == "variable") return cont(typeuse);
389
  }
390
  function funarg(type, value) {
391
    if (type == "variable") {register(value); return cont(typeuse);}
392
  }
393
 
394
  // Interface
395
 
396
  return {
397
    startState: function(basecolumn) {
398
    var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
399
      return {
400
        tokenize: haxeTokenBase,
401
        reAllowed: true,
402
        kwAllowed: true,
403
        cc: [],
404
        lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false),
405
        localVars: parserConfig.localVars,
406
    importedtypes: defaulttypes,
407
        context: parserConfig.localVars && {vars: parserConfig.localVars},
408
        indented: 0
409
      };
410
    },
411
 
412
    token: function(stream, state) {
413
      if (stream.sol()) {
414
        if (!state.lexical.hasOwnProperty("align"))
415
          state.lexical.align = false;
416
        state.indented = stream.indentation();
417
      }
418
      if (stream.eatSpace()) return null;
419
      var style = state.tokenize(stream, state);
420
      if (type == "comment") return style;
421
      state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/));
422
      state.kwAllowed = type != '.';
423
      return parseHaxe(state, style, type, content, stream);
424
    },
425
 
426
    indent: function(state, textAfter) {
427
      if (state.tokenize != haxeTokenBase) return 0;
428
      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
429
      if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
430
      var type = lexical.type, closing = firstChar == type;
431
      if (type == "vardef") return lexical.indented + 4;
432
      else if (type == "form" && firstChar == "{") return lexical.indented;
433
      else if (type == "stat" || type == "form") return lexical.indented + indentUnit;
434
      else if (lexical.info == "switch" && !closing)
435
        return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
436
      else if (lexical.align) return lexical.column + (closing ? 0 : 1);
437
      else return lexical.indented + (closing ? 0 : indentUnit);
438
    },
439
 
440
    electricChars: "{}",
441
    blockCommentStart: "/*",
442
    blockCommentEnd: "*/",
443
    lineComment: "//"
444
  };
445
});
446
 
447
CodeMirror.defineMIME("text/x-haxe", "haxe");
448
 
449
CodeMirror.defineMode("hxml", function () {
450
 
451
  return {
452
    startState: function () {
453
      return {
454
        define: false,
455
        inString: false
456
      };
457
    },
458
    token: function (stream, state) {
459
      var ch = stream.peek();
460
      var sol = stream.sol();
461
 
462
      ///* comments */
463
      if (ch == "#") {
464
        stream.skipToEnd();
465
        return "comment";
466
      }
467
      if (sol && ch == "-") {
468
        var style = "variable-2";
469
 
470
        stream.eat(/-/);
471
 
472
        if (stream.peek() == "-") {
473
          stream.eat(/-/);
474
          style = "keyword a";
475
        }
476
 
477
        if (stream.peek() == "D") {
478
          stream.eat(/[D]/);
479
          style = "keyword c";
480
          state.define = true;
481
        }
482
 
483
        stream.eatWhile(/[A-Z]/i);
484
        return style;
485
      }
486
 
487
      var ch = stream.peek();
488
 
489
      if (state.inString == false && ch == "'") {
490
        state.inString = true;
491
        ch = stream.next();
492
      }
493
 
494
      if (state.inString == true) {
495
        if (stream.skipTo("'")) {
496
 
497
        } else {
498
          stream.skipToEnd();
499
        }
500
 
501
        if (stream.peek() == "'") {
502
          stream.next();
503
          state.inString = false;
504
        }
505
 
506
        return "string";
507
      }
508
 
509
      stream.next();
510
      return null;
511
    },
512
    lineComment: "#"
513
  };
514
});
515
 
516
CodeMirror.defineMIME("text/x-hxml", "hxml");
517
 
518
});