annotate .cms/lib/codemirror/mode/mathematica/mathematica.js @ 1:1d486627aa1e draft default tip

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