// CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE (function(mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD define(["../../lib/codemirror"], mod); else // Plain browser env mod(CodeMirror); })(function(CodeMirror) { "use strict"; CodeMirror.defineMode("elm", function() { function switchState(source, setState, f) { setState(f); return f(source, setState); } // These should all be Unicode extended, as per the Haskell 2010 report var smallRE = /[a-z_]/; var largeRE = /[A-Z]/; var digitRE = /[0-9]/; var hexitRE = /[0-9A-Fa-f]/; var octitRE = /[0-7]/; var idRE = /[a-z_A-Z0-9\']/; var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:\u03BB\u2192]/; var specialRE = /[(),;[\]`{}]/; var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer function normal() { return function (source, setState) { if (source.eatWhile(whiteCharRE)) { return null; } var ch = source.next(); if (specialRE.test(ch)) { if (ch == '{' && source.eat('-')) { var t = "comment"; if (source.eat('#')) t = "meta"; return switchState(source, setState, ncomment(t, 1)); } return null; } if (ch == '\'') { if (source.eat('\\')) source.next(); // should handle other escapes here else source.next(); if (source.eat('\'')) return "string"; return "error"; } if (ch == '"') { return switchState(source, setState, stringLiteral); } if (largeRE.test(ch)) { source.eatWhile(idRE); if (source.eat('.')) return "qualifier"; return "variable-2"; } if (smallRE.test(ch)) { var isDef = source.pos === 1; source.eatWhile(idRE); return isDef ? "variable-3" : "variable"; } if (digitRE.test(ch)) { if (ch == '0') { if (source.eat(/[xX]/)) { source.eatWhile(hexitRE); // should require at least 1 return "integer"; } if (source.eat(/[oO]/)) { source.eatWhile(octitRE); // should require at least 1 return "number"; } } source.eatWhile(digitRE); var t = "number"; if (source.eat('.')) { t = "number"; source.eatWhile(digitRE); // should require at least 1 } if (source.eat(/[eE]/)) { t = "number"; source.eat(/[-+]/); source.eatWhile(digitRE); // should require at least 1 } return t; } if (symbolRE.test(ch)) { if (ch == '-' && source.eat(/-/)) { source.eatWhile(/-/); if (!source.eat(symbolRE)) { source.skipToEnd(); return "comment"; } } source.eatWhile(symbolRE); return "builtin"; } return "error"; } } function ncomment(type, nest) { if (nest == 0) { return normal(); } return function(source, setState) { var currNest = nest; while (!source.eol()) { var ch = source.next(); if (ch == '{' && source.eat('-')) { ++currNest; } else if (ch == '-' && source.eat('}')) { --currNest; if (currNest == 0) { setState(normal()); return type; } } } setState(ncomment(type, currNest)); return type; } } function stringLiteral(source, setState) { while (!source.eol()) { var ch = source.next(); if (ch == '"') { setState(normal()); return "string"; } if (ch == '\\') { if (source.eol() || source.eat(whiteCharRE)) { setState(stringGap); return "string"; } if (!source.eat('&')) source.next(); // should handle other escapes here } } setState(normal()); return "error"; } function stringGap(source, setState) { if (source.eat('\\')) { return switchState(source, setState, stringLiteral); } source.next(); setState(normal()); return "error"; } var wellKnownWords = (function() { var wkw = {}; var keywords = [ "case", "of", "as", "if", "then", "else", "let", "in", "infix", "infixl", "infixr", "type", "alias", "input", "output", "foreign", "loopback", "module", "where", "import", "exposing", "_", "..", "|", ":", "=", "\\", "\"", "->", "<-" ]; for (var i = keywords.length; i--;) wkw[keywords[i]] = "keyword"; return wkw; })(); return { startState: function () { return { f: normal() }; }, copyState: function (s) { return { f: s.f }; }, token: function(stream, state) { var t = state.f(stream, function(s) { state.f = s; }); var w = stream.current(); return (wellKnownWords.hasOwnProperty(w)) ? wellKnownWords[w] : t; } }; }); CodeMirror.defineMIME("text/x-elm", "elm"); });