File modules/editor/codemirror/mode/mathematica/mathematica.js

Last commit: Sun Dec 17 01:14:09 2017 +0100	Jan Dankert	Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.
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 stream.next(); // advance the stream. 130 return 'error'; 131 } 132 133 function tokenString(stream, state) { 134 var next, end = false, escaped = false; 135 while ((next = stream.next()) != null) { 136 if (next === '"' && !escaped) { 137 end = true; 138 break; 139 } 140 escaped = !escaped && next === '\\'; 141 } 142 if (end && !escaped) { 143 state.tokenize = tokenBase; 144 } 145 return 'string'; 146 }; 147 148 function tokenComment(stream, state) { 149 var prev, next; 150 while(state.commentLevel > 0 && (next = stream.next()) != null) { 151 if (prev === '(' && next === '*') state.commentLevel++; 152 if (prev === '*' && next === ')') state.commentLevel--; 153 prev = next; 154 } 155 if (state.commentLevel <= 0) { 156 state.tokenize = tokenBase; 157 } 158 return 'comment'; 159 } 160 161 return { 162 startState: function() {return {tokenize: tokenBase, commentLevel: 0};}, 163 token: function(stream, state) { 164 if (stream.eatSpace()) return null; 165 return state.tokenize(stream, state); 166 }, 167 blockCommentStart: "(*", 168 blockCommentEnd: "*)" 169 }; 170 }); 171 172 CodeMirror.defineMIME('text/x-mathematica', { 173 name: 'mathematica' 174 }); 175 176 });
Download modules/editor/codemirror/mode/mathematica/mathematica.js
History Sun, 17 Dec 2017 01:14:09 +0100 Jan Dankert Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.