github.com/jancarloviray/community@v0.41.1-0.20170124221257-33a66c87cf2f/app/public/codemirror/mode/mathematica/mathematica.js (about)

     1  // CodeMirror, copyright (c) by Marijn Haverbeke and others
     2  // Distributed under an MIT license: http://codemirror.net/LICENSE
     3  
     4  // Mathematica mode copyright (c) 2015 by Calin Barbat
     5  // Based on code by Patrick Scheibe (halirutan)
     6  // See: https://github.com/halirutan/Mathematica-Source-Highlighting/tree/master/src/lang-mma.js
     7  
     8  (function(mod) {
     9    if (typeof exports == "object" && typeof module == "object") // CommonJS
    10      mod(require("../../lib/codemirror"));
    11    else if (typeof define == "function" && define.amd) // AMD
    12      define(["../../lib/codemirror"], mod);
    13    else // Plain browser env
    14      mod(CodeMirror);
    15  })(function(CodeMirror) {
    16  "use strict";
    17  
    18  CodeMirror.defineMode('mathematica', function(_config, _parserConfig) {
    19  
    20    // used pattern building blocks
    21    var Identifier = '[a-zA-Z\\$][a-zA-Z0-9\\$]*';
    22    var pBase      = "(?:\\d+)";
    23    var pFloat     = "(?:\\.\\d+|\\d+\\.\\d*|\\d+)";
    24    var pFloatBase = "(?:\\.\\w+|\\w+\\.\\w*|\\w+)";
    25    var pPrecision = "(?:`(?:`?"+pFloat+")?)";
    26  
    27    // regular expressions
    28    var reBaseForm        = new RegExp('(?:'+pBase+'(?:\\^\\^'+pFloatBase+pPrecision+'?(?:\\*\\^[+-]?\\d+)?))');
    29    var reFloatForm       = new RegExp('(?:' + pFloat + pPrecision + '?(?:\\*\\^[+-]?\\d+)?)');
    30    var reIdInContext     = new RegExp('(?:`?)(?:' + Identifier + ')(?:`(?:' + Identifier + '))*(?:`?)');
    31  
    32    function tokenBase(stream, state) {
    33      var ch;
    34  
    35      // get next character
    36      ch = stream.next();
    37  
    38      // string
    39      if (ch === '"') {
    40        state.tokenize = tokenString;
    41        return state.tokenize(stream, state);
    42      }
    43  
    44      // comment
    45      if (ch === '(') {
    46        if (stream.eat('*')) {
    47          state.commentLevel++;
    48          state.tokenize = tokenComment;
    49          return state.tokenize(stream, state);
    50        }
    51      }
    52  
    53      // go back one character
    54      stream.backUp(1);
    55  
    56      // look for numbers
    57      // Numbers in a baseform
    58      if (stream.match(reBaseForm, true, false)) {
    59        return 'number';
    60      }
    61  
    62      // Mathematica numbers. Floats (1.2, .2, 1.) can have optionally a precision (`float) or an accuracy definition
    63      // (``float). Note: while 1.2` is possible 1.2`` is not. At the end an exponent (float*^+12) can follow.
    64      if (stream.match(reFloatForm, true, false)) {
    65        return 'number';
    66      }
    67  
    68      /* In[23] and Out[34] */
    69      if (stream.match(/(?:In|Out)\[[0-9]*\]/, true, false)) {
    70        return 'atom';
    71      }
    72  
    73      // usage
    74      if (stream.match(/([a-zA-Z\$]+(?:`?[a-zA-Z0-9\$])*::usage)/, true, false)) {
    75        return 'meta';
    76      }
    77  
    78      // message
    79      if (stream.match(/([a-zA-Z\$]+(?:`?[a-zA-Z0-9\$])*::[a-zA-Z\$][a-zA-Z0-9\$]*):?/, true, false)) {
    80        return 'string-2';
    81      }
    82  
    83      // this makes a look-ahead match for something like variable:{_Integer}
    84      // the match is then forwarded to the mma-patterns tokenizer.
    85      if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*\s*:)(?:(?:[a-zA-Z\$][a-zA-Z0-9\$]*)|(?:[^:=>~@\^\&\*\)\[\]'\?,\|])).*/, true, false)) {
    86        return 'variable-2';
    87      }
    88  
    89      // catch variables which are used together with Blank (_), BlankSequence (__) or BlankNullSequence (___)
    90      // Cannot start with a number, but can have numbers at any other position. Examples
    91      // blub__Integer, a1_, b34_Integer32
    92      if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {
    93        return 'variable-2';
    94      }
    95      if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+/, true, false)) {
    96        return 'variable-2';
    97      }
    98      if (stream.match(/_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) {
    99        return 'variable-2';
   100      }
   101  
   102      // Named characters in Mathematica, like \[Gamma].
   103      if (stream.match(/\\\[[a-zA-Z\$][a-zA-Z0-9\$]*\]/, true, false)) {
   104        return 'variable-3';
   105      }
   106  
   107      // Match all braces separately
   108      if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) {
   109        return 'bracket';
   110      }
   111  
   112      // Catch Slots (#, ##, #3, ##9 and the V10 named slots #name). I have never seen someone using more than one digit after #, so we match
   113      // only one.
   114      if (stream.match(/(?:#[a-zA-Z\$][a-zA-Z0-9\$]*|#+[0-9]?)/, true, false)) {
   115        return 'variable-2';
   116      }
   117  
   118      // Literals like variables, keywords, functions
   119      if (stream.match(reIdInContext, true, false)) {
   120        return 'keyword';
   121      }
   122  
   123      // operators. Note that operators like @@ or /; are matched separately for each symbol.
   124      if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%)/, true, false)) {
   125        return 'operator';
   126      }
   127  
   128      // everything else is an error
   129      return 'error';
   130    }
   131  
   132    function tokenString(stream, state) {
   133      var next, end = false, escaped = false;
   134      while ((next = stream.next()) != null) {
   135        if (next === '"' && !escaped) {
   136          end = true;
   137          break;
   138        }
   139        escaped = !escaped && next === '\\';
   140      }
   141      if (end && !escaped) {
   142        state.tokenize = tokenBase;
   143      }
   144      return 'string';
   145    };
   146  
   147    function tokenComment(stream, state) {
   148      var prev, next;
   149      while(state.commentLevel > 0 && (next = stream.next()) != null) {
   150        if (prev === '(' && next === '*') state.commentLevel++;
   151        if (prev === '*' && next === ')') state.commentLevel--;
   152        prev = next;
   153      }
   154      if (state.commentLevel <= 0) {
   155        state.tokenize = tokenBase;
   156      }
   157      return 'comment';
   158    }
   159  
   160    return {
   161      startState: function() {return {tokenize: tokenBase, commentLevel: 0};},
   162      token: function(stream, state) {
   163        if (stream.eatSpace()) return null;
   164        return state.tokenize(stream, state);
   165      },
   166      blockCommentStart: "(*",
   167      blockCommentEnd: "*)"
   168    };
   169  });
   170  
   171  CodeMirror.defineMIME('text/x-mathematica', {
   172    name: 'mathematica'
   173  });
   174  
   175  });