text: // 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('mllike', function (_config, parserConfig) {
          var words = {
              'let': 'keyword',
              'rec': 'keyword',
              'in': 'keyword',
              'of': 'keyword',
              'and': 'keyword',
              'if': 'keyword',
              'then': 'keyword',
              'else': 'keyword',
              'for': 'keyword',
              'to': 'keyword',
              'while': 'keyword',
              'do': 'keyword',
              'done': 'keyword',
              'fun': 'keyword',
              'function': 'keyword',
              'val': 'keyword',
              'type': 'keyword',
              'mutable': 'keyword',
              'match': 'keyword',
              'with': 'keyword',
              'try': 'keyword',
              'open': 'builtin',
              'ignore': 'builtin',
              'begin': 'keyword',
              'end': 'keyword'
          };
  
          var extraWords = parserConfig.extraWords || {};
          for (var prop in extraWords) {
              if (extraWords.hasOwnProperty(prop)) {
                  words[prop] = parserConfig.extraWords[prop];
              }
          }
  
          function tokenBase(stream, state) {
              var ch = stream.next();
  
              if (ch === '"') {
                  state.tokenize = tokenString;
                  return state.tokenize(stream, state);
              }
              if (ch === '(') {
                  if (stream.eat('*')) {
                      state.commentLevel++;
                      state.tokenize = tokenComment;
                      return state.tokenize(stream, state);
                  }
              }
              if (ch === '~') {
                  stream.eatWhile(/\w/);
                  return 'variable-2';
              }
              if (ch === '`') {
                  stream.eatWhile(/\w/);
                  return 'quote';
              }
              if (ch === '/' && parserConfig.slashComments && stream.eat('/')) {
                  stream.skipToEnd();
                  return 'comment';
              }
              if (/\d/.test(ch)) {
                  stream.eatWhile(/[\d]/);
                  if (stream.eat('.')) {
                      stream.eatWhile(/[\d]/);
                  }
                  return 'number';
              }
              if (/[+\-*&%=<>!?|]/.test(ch)) {
                  return 'operator';
              }
              stream.eatWhile(/\w/);
              var cur = stream.current();
              return words.hasOwnProperty(cur) ? words[cur] : 'variable';
          }
  
          function tokenString(stream, state) {
              var next, end = false, escaped = false;
              while ((next = stream.next()) != null) {
                  if (next === '"' && !escaped) {
                      end = true;
                      break;
                  }
                  escaped = !escaped && next === '\\';
              }
              if (end && !escaped) {
                  state.tokenize = tokenBase;
              }
              return 'string';
          }
  
          function tokenComment(stream, state) {
              var prev, next;
              while (state.commentLevel > 0 && (next = stream.next()) != null) {
                  if (prev === '(' && next === '*') state.commentLevel++;
                  if (prev === '*' && next === ')') state.commentLevel--;
                  prev = next;
              }
              if (state.commentLevel <= 0) {
                  state.tokenize = tokenBase;
              }
              return 'comment';
          }
  
          return {
              startState: function () {
                  return {tokenize: tokenBase, commentLevel: 0};
              },
              token: function (stream, state) {
                  if (stream.eatSpace()) return null;
                  return state.tokenize(stream, state);
              },
  
              blockCommentStart: "(*",
              blockCommentEnd: "*)",
              lineComment: parserConfig.slashComments ? "//" : null
          };
      });
  
      CodeMirror.defineMIME('text/x-ocaml', {
          name: 'mllike',
          extraWords: {
              'succ': 'keyword',
              'trace': 'builtin',
              'exit': 'builtin',
              'print_string': 'builtin',
              'print_endline': 'builtin',
              'true': 'atom',
              'false': 'atom',
              'raise': 'keyword'
          }
      });
  
      CodeMirror.defineMIME('text/x-fsharp', {
          name: 'mllike',
          extraWords: {
              'abstract': 'keyword',
              'as': 'keyword',
              'assert': 'keyword',
              'base': 'keyword',
              'class': 'keyword',
              'default': 'keyword',
              'delegate': 'keyword',
              'downcast': 'keyword',
              'downto': 'keyword',
              'elif': 'keyword',
              'exception': 'keyword',
              'extern': 'keyword',
              'finally': 'keyword',
              'global': 'keyword',
              'inherit': 'keyword',
              'inline': 'keyword',
              'interface': 'keyword',
              'internal': 'keyword',
              'lazy': 'keyword',
              'let!': 'keyword',
              'member': 'keyword',
              'module': 'keyword',
              'namespace': 'keyword',
              'new': 'keyword',
              'null': 'keyword',
              'override': 'keyword',
              'private': 'keyword',
              'public': 'keyword',
              'return': 'keyword',
              'return!': 'keyword',
              'select': 'keyword',
              'static': 'keyword',
              'struct': 'keyword',
              'upcast': 'keyword',
              'use': 'keyword',
              'use!': 'keyword',
              'val': 'keyword',
              'when': 'keyword',
              'yield': 'keyword',
              'yield!': 'keyword',
  
              'List': 'builtin',
              'Seq': 'builtin',
              'Map': 'builtin',
              'Set': 'builtin',
              'int': 'builtin',
              'string': 'builtin',
              'raise': 'builtin',
              'failwith': 'builtin',
              'not': 'builtin',
              'true': 'builtin',
              'false': 'builtin'
          },
          slashComments: true
      });
  
  });
  