scripts/CodeMirror/mode/dylan/dylan.js (view raw)
1// CodeMirror, copyright (c) by Marijn Haverbeke and others
2// Distributed under an MIT license: https://codemirror.net/LICENSE
3
4(function(mod) {
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
9 else // Plain browser env
10 mod(CodeMirror);
11})(function(CodeMirror) {
12"use strict";
13
14function forEach(arr, f) {
15 for (var i = 0; i < arr.length; i++) f(arr[i], i)
16}
17function some(arr, f) {
18 for (var i = 0; i < arr.length; i++) if (f(arr[i], i)) return true
19 return false
20}
21
22CodeMirror.defineMode("dylan", function(_config) {
23 // Words
24 var words = {
25 // Words that introduce unnamed definitions like "define interface"
26 unnamedDefinition: ["interface"],
27
28 // Words that introduce simple named definitions like "define library"
29 namedDefinition: ["module", "library", "macro",
30 "C-struct", "C-union",
31 "C-function", "C-callable-wrapper"
32 ],
33
34 // Words that introduce type definitions like "define class".
35 // These are also parameterized like "define method" and are
36 // appended to otherParameterizedDefinitionWords
37 typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"],
38
39 // Words that introduce trickier definitions like "define method".
40 // These require special definitions to be added to startExpressions
41 otherParameterizedDefinition: ["method", "function",
42 "C-variable", "C-address"
43 ],
44
45 // Words that introduce module constant definitions.
46 // These must also be simple definitions and are
47 // appended to otherSimpleDefinitionWords
48 constantSimpleDefinition: ["constant"],
49
50 // Words that introduce module variable definitions.
51 // These must also be simple definitions and are
52 // appended to otherSimpleDefinitionWords
53 variableSimpleDefinition: ["variable"],
54
55 // Other words that introduce simple definitions
56 // (without implicit bodies).
57 otherSimpleDefinition: ["generic", "domain",
58 "C-pointer-type",
59 "table"
60 ],
61
62 // Words that begin statements with implicit bodies.
63 statement: ["if", "block", "begin", "method", "case",
64 "for", "select", "when", "unless", "until",
65 "while", "iterate", "profiling", "dynamic-bind"
66 ],
67
68 // Patterns that act as separators in compound statements.
69 // This may include any general pattern that must be indented
70 // specially.
71 separator: ["finally", "exception", "cleanup", "else",
72 "elseif", "afterwards"
73 ],
74
75 // Keywords that do not require special indentation handling,
76 // but which should be highlighted
77 other: ["above", "below", "by", "from", "handler", "in",
78 "instance", "let", "local", "otherwise", "slot",
79 "subclass", "then", "to", "keyed-by", "virtual"
80 ],
81
82 // Condition signaling function calls
83 signalingCalls: ["signal", "error", "cerror",
84 "break", "check-type", "abort"
85 ]
86 };
87
88 words["otherDefinition"] =
89 words["unnamedDefinition"]
90 .concat(words["namedDefinition"])
91 .concat(words["otherParameterizedDefinition"]);
92
93 words["definition"] =
94 words["typeParameterizedDefinition"]
95 .concat(words["otherDefinition"]);
96
97 words["parameterizedDefinition"] =
98 words["typeParameterizedDefinition"]
99 .concat(words["otherParameterizedDefinition"]);
100
101 words["simpleDefinition"] =
102 words["constantSimpleDefinition"]
103 .concat(words["variableSimpleDefinition"])
104 .concat(words["otherSimpleDefinition"]);
105
106 words["keyword"] =
107 words["statement"]
108 .concat(words["separator"])
109 .concat(words["other"]);
110
111 // Patterns
112 var symbolPattern = "[-_a-zA-Z?!*@<>$%]+";
113 var symbol = new RegExp("^" + symbolPattern);
114 var patterns = {
115 // Symbols with special syntax
116 symbolKeyword: symbolPattern + ":",
117 symbolClass: "<" + symbolPattern + ">",
118 symbolGlobal: "\\*" + symbolPattern + "\\*",
119 symbolConstant: "\\$" + symbolPattern
120 };
121 var patternStyles = {
122 symbolKeyword: "atom",
123 symbolClass: "tag",
124 symbolGlobal: "variable-2",
125 symbolConstant: "variable-3"
126 };
127
128 // Compile all patterns to regular expressions
129 for (var patternName in patterns)
130 if (patterns.hasOwnProperty(patternName))
131 patterns[patternName] = new RegExp("^" + patterns[patternName]);
132
133 // Names beginning "with-" and "without-" are commonly
134 // used as statement macro
135 patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/];
136
137 var styles = {};
138 styles["keyword"] = "keyword";
139 styles["definition"] = "def";
140 styles["simpleDefinition"] = "def";
141 styles["signalingCalls"] = "builtin";
142
143 // protected words lookup table
144 var wordLookup = {};
145 var styleLookup = {};
146
147 forEach([
148 "keyword",
149 "definition",
150 "simpleDefinition",
151 "signalingCalls"
152 ], function(type) {
153 forEach(words[type], function(word) {
154 wordLookup[word] = type;
155 styleLookup[word] = styles[type];
156 });
157 });
158
159
160 function chain(stream, state, f) {
161 state.tokenize = f;
162 return f(stream, state);
163 }
164
165 function tokenBase(stream, state) {
166 // String
167 var ch = stream.peek();
168 if (ch == "'" || ch == '"') {
169 stream.next();
170 return chain(stream, state, tokenString(ch, "string"));
171 }
172 // Comment
173 else if (ch == "/") {
174 stream.next();
175 if (stream.eat("*")) {
176 return chain(stream, state, tokenComment);
177 } else if (stream.eat("/")) {
178 stream.skipToEnd();
179 return "comment";
180 }
181 stream.backUp(1);
182 }
183 // Decimal
184 else if (/[+\-\d\.]/.test(ch)) {
185 if (stream.match(/^[+-]?[0-9]*\.[0-9]*([esdx][+-]?[0-9]+)?/i) ||
186 stream.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i) ||
187 stream.match(/^[+-]?\d+/)) {
188 return "number";
189 }
190 }
191 // Hash
192 else if (ch == "#") {
193 stream.next();
194 // Symbol with string syntax
195 ch = stream.peek();
196 if (ch == '"') {
197 stream.next();
198 return chain(stream, state, tokenString('"', "string"));
199 }
200 // Binary number
201 else if (ch == "b") {
202 stream.next();
203 stream.eatWhile(/[01]/);
204 return "number";
205 }
206 // Hex number
207 else if (ch == "x") {
208 stream.next();
209 stream.eatWhile(/[\da-f]/i);
210 return "number";
211 }
212 // Octal number
213 else if (ch == "o") {
214 stream.next();
215 stream.eatWhile(/[0-7]/);
216 return "number";
217 }
218 // Token concatenation in macros
219 else if (ch == '#') {
220 stream.next();
221 return "punctuation";
222 }
223 // Sequence literals
224 else if ((ch == '[') || (ch == '(')) {
225 stream.next();
226 return "bracket";
227 // Hash symbol
228 } else if (stream.match(/f|t|all-keys|include|key|next|rest/i)) {
229 return "atom";
230 } else {
231 stream.eatWhile(/[-a-zA-Z]/);
232 return "error";
233 }
234 } else if (ch == "~") {
235 stream.next();
236 ch = stream.peek();
237 if (ch == "=") {
238 stream.next();
239 ch = stream.peek();
240 if (ch == "=") {
241 stream.next();
242 return "operator";
243 }
244 return "operator";
245 }
246 return "operator";
247 } else if (ch == ":") {
248 stream.next();
249 ch = stream.peek();
250 if (ch == "=") {
251 stream.next();
252 return "operator";
253 } else if (ch == ":") {
254 stream.next();
255 return "punctuation";
256 }
257 } else if ("[](){}".indexOf(ch) != -1) {
258 stream.next();
259 return "bracket";
260 } else if (".,".indexOf(ch) != -1) {
261 stream.next();
262 return "punctuation";
263 } else if (stream.match("end")) {
264 return "keyword";
265 }
266 for (var name in patterns) {
267 if (patterns.hasOwnProperty(name)) {
268 var pattern = patterns[name];
269 if ((pattern instanceof Array && some(pattern, function(p) {
270 return stream.match(p);
271 })) || stream.match(pattern))
272 return patternStyles[name];
273 }
274 }
275 if (/[+\-*\/^=<>&|]/.test(ch)) {
276 stream.next();
277 return "operator";
278 }
279 if (stream.match("define")) {
280 return "def";
281 } else {
282 stream.eatWhile(/[\w\-]/);
283 // Keyword
284 if (wordLookup.hasOwnProperty(stream.current())) {
285 return styleLookup[stream.current()];
286 } else if (stream.current().match(symbol)) {
287 return "variable";
288 } else {
289 stream.next();
290 return "variable-2";
291 }
292 }
293 }
294
295 function tokenComment(stream, state) {
296 var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;
297 while ((ch = stream.next())) {
298 if (ch == "/" && maybeEnd) {
299 if (nestedCount > 0) {
300 nestedCount--;
301 } else {
302 state.tokenize = tokenBase;
303 break;
304 }
305 } else if (ch == "*" && maybeNested) {
306 nestedCount++;
307 }
308 maybeEnd = (ch == "*");
309 maybeNested = (ch == "/");
310 }
311 return "comment";
312 }
313
314 function tokenString(quote, style) {
315 return function(stream, state) {
316 var escaped = false, next, end = false;
317 while ((next = stream.next()) != null) {
318 if (next == quote && !escaped) {
319 end = true;
320 break;
321 }
322 escaped = !escaped && next == "\\";
323 }
324 if (end || !escaped) {
325 state.tokenize = tokenBase;
326 }
327 return style;
328 };
329 }
330
331 // Interface
332 return {
333 startState: function() {
334 return {
335 tokenize: tokenBase,
336 currentIndent: 0
337 };
338 },
339 token: function(stream, state) {
340 if (stream.eatSpace())
341 return null;
342 var style = state.tokenize(stream, state);
343 return style;
344 },
345 blockCommentStart: "/*",
346 blockCommentEnd: "*/"
347 };
348});
349
350CodeMirror.defineMIME("text/x-dylan", "dylan");
351
352});