1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
/*
This MUMPS Language script was constructed using vbscript.js as a template.
*/
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("mumps", function() {
function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
}
var singleOperators = new RegExp("^[\\+\\-\\*/&#!_?\\\\<>=\\'\\[\\]]");
var doubleOperators = new RegExp("^(('=)|(<=)|(>=)|('>)|('<)|([[)|(]])|(^$))");
var singleDelimiters = new RegExp("^[\\.,:]");
var brackets = new RegExp("[()]");
var identifiers = new RegExp("^[%A-Za-z][A-Za-z0-9]*");
var commandKeywords = ["break","close","do","else","for","goto", "halt", "hang", "if", "job","kill","lock","merge","new","open", "quit", "read", "set", "tcommit", "trollback", "tstart", "use", "view", "write", "xecute", "b","c","d","e","f","g", "h", "i", "j","k","l","m","n","o", "q", "r", "s", "tc", "tro", "ts", "u", "v", "w", "x"];
// The following list includes instrinsic functions _and_ special variables
var intrinsicFuncsWords = ["\\$ascii", "\\$char", "\\$data", "\\$ecode", "\\$estack", "\\$etrap", "\\$extract", "\\$find", "\\$fnumber", "\\$get", "\\$horolog", "\\$io", "\\$increment", "\\$job", "\\$justify", "\\$length", "\\$name", "\\$next", "\\$order", "\\$piece", "\\$qlength", "\\$qsubscript", "\\$query", "\\$quit", "\\$random", "\\$reverse", "\\$select", "\\$stack", "\\$test", "\\$text", "\\$translate", "\\$view", "\\$x", "\\$y", "\\$a", "\\$c", "\\$d", "\\$e", "\\$ec", "\\$es", "\\$et", "\\$f", "\\$fn", "\\$g", "\\$h", "\\$i", "\\$j", "\\$l", "\\$n", "\\$na", "\\$o", "\\$p", "\\$q", "\\$ql", "\\$qs", "\\$r", "\\$re", "\\$s", "\\$st", "\\$t", "\\$tr", "\\$v", "\\$z"];
var intrinsicFuncs = wordRegexp(intrinsicFuncsWords);
var command = wordRegexp(commandKeywords);
function tokenBase(stream, state) {
if (stream.sol()) {
state.label = true;
state.commandMode = 0;
}
// The <space> character has meaning in MUMPS. Ignoring consecutive
// spaces would interfere with interpreting whether the next non-space
// character belongs to the command or argument context.
// Examine each character and update a mode variable whose interpretation is:
// >0 => command 0 => argument <0 => command post-conditional
var ch = stream.peek();
if (ch == " " || ch == "\t") { // Pre-process <space>
state.label = false;
if (state.commandMode == 0)
state.commandMode = 1;
else if ((state.commandMode < 0) || (state.commandMode == 2))
state.commandMode = 0;
} else if ((ch != ".") && (state.commandMode > 0)) {
if (ch == ":")
state.commandMode = -1; // SIS - Command post-conditional
else
state.commandMode = 2;
}
// Do not color parameter list as line tag
if ((ch === "(") || (ch === "\u0009"))
state.label = false;
// MUMPS comment starts with ";"
if (ch === ";") {
stream.skipToEnd();
return "comment";
}
// Number Literals // SIS/RLM - MUMPS permits canonic number followed by concatenate operator
if (stream.match(/^[-+]?\d+(\.\d+)?([eE][-+]?\d+)?/))
return "number";
// Handle Strings
if (ch == '"') {
if (stream.skipTo('"')) {
stream.next();
return "string";
} else {
stream.skipToEnd();
return "error";
}
}
// Handle operators and Delimiters
if (stream.match(doubleOperators) || stream.match(singleOperators))
return "operator";
// Prevents leading "." in DO block from falling through to error
if (stream.match(singleDelimiters))
return null;
if (brackets.test(ch)) {
stream.next();
return "bracket";
}
if (state.commandMode > 0 && stream.match(command))
return "variable-2";
if (stream.match(intrinsicFuncs))
return "builtin";
if (stream.match(identifiers))
return "variable";
// Detect dollar-sign when not a documented intrinsic function
// "^" may introduce a GVN or SSVN - Color same as function
if (ch === "$" || ch === "^") {
stream.next();
return "builtin";
}
// MUMPS Indirection
if (ch === "@") {
stream.next();
return "string-2";
}
if (/[\w%]/.test(ch)) {
stream.eatWhile(/[\w%]/);
return "variable";
}
// Handle non-detected items
stream.next();
return "error";
}
return {
startState: function() {
return {
label: false,
commandMode: 0
};
},
token: function(stream, state) {
var style = tokenBase(stream, state);
if (state.label) return "tag";
return style;
}
};
});
CodeMirror.defineMIME("text/x-mumps", "mumps");
});
|