Mercurial
comparison .cms/lib/codemirror/mode/mathematica/mathematica.js @ 0:78edf6b517a0 draft
24.10
author | Coffee CMS <info@coffee-cms.ru> |
---|---|
date | Fri, 11 Oct 2024 22:40:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:78edf6b517a0 |
---|---|
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others | |
2 // Distributed under an MIT license: https://codemirror.net/5/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\$]*(?:`[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-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 }); |