1 |
|
2 |
|
3 |
|
4 | (function(mod) {
|
5 | if (typeof exports == "object" && typeof module == "object")
|
6 | mod(require("../../lib/codemirror"));
|
7 | else if (typeof define == "function" && define.amd)
|
8 | define(["../../lib/codemirror"], mod);
|
9 | else
|
10 | mod(CodeMirror);
|
11 | })(function(CodeMirror) {
|
12 | "use strict";
|
13 |
|
14 | CodeMirror.defineMode("ttcn", function(config, parserConfig) {
|
15 | var indentUnit = config.indentUnit,
|
16 | keywords = parserConfig.keywords || {},
|
17 | builtin = parserConfig.builtin || {},
|
18 | timerOps = parserConfig.timerOps || {},
|
19 | portOps = parserConfig.portOps || {},
|
20 | configOps = parserConfig.configOps || {},
|
21 | verdictOps = parserConfig.verdictOps || {},
|
22 | sutOps = parserConfig.sutOps || {},
|
23 | functionOps = parserConfig.functionOps || {},
|
24 |
|
25 | verdictConsts = parserConfig.verdictConsts || {},
|
26 | booleanConsts = parserConfig.booleanConsts || {},
|
27 | otherConsts = parserConfig.otherConsts || {},
|
28 |
|
29 | types = parserConfig.types || {},
|
30 | visibilityModifiers = parserConfig.visibilityModifiers || {},
|
31 | templateMatch = parserConfig.templateMatch || {},
|
32 | multiLineStrings = parserConfig.multiLineStrings,
|
33 | indentStatements = parserConfig.indentStatements !== false;
|
34 | var isOperatorChar = /[+\-*&@=<>!\/]/;
|
35 | var curPunc;
|
36 |
|
37 | function tokenBase(stream, state) {
|
38 | var ch = stream.next();
|
39 |
|
40 | if (ch == '"' || ch == "'") {
|
41 | state.tokenize = tokenString(ch);
|
42 | return state.tokenize(stream, state);
|
43 | }
|
44 | if (/[\[\]{}\(\),;\\:\?\.]/.test(ch)) {
|
45 | curPunc = ch;
|
46 | return "punctuation";
|
47 | }
|
48 | if (ch == "#"){
|
49 | stream.skipToEnd();
|
50 | return "atom preprocessor";
|
51 | }
|
52 | if (ch == "%"){
|
53 | stream.eatWhile(/\b/);
|
54 | return "atom ttcn3Macros";
|
55 | }
|
56 | if (/\d/.test(ch)) {
|
57 | stream.eatWhile(/[\w\.]/);
|
58 | return "number";
|
59 | }
|
60 | if (ch == "/") {
|
61 | if (stream.eat("*")) {
|
62 | state.tokenize = tokenComment;
|
63 | return tokenComment(stream, state);
|
64 | }
|
65 | if (stream.eat("/")) {
|
66 | stream.skipToEnd();
|
67 | return "comment";
|
68 | }
|
69 | }
|
70 | if (isOperatorChar.test(ch)) {
|
71 | if(ch == "@"){
|
72 | if(stream.match("try") || stream.match("catch")
|
73 | || stream.match("lazy")){
|
74 | return "keyword";
|
75 | }
|
76 | }
|
77 | stream.eatWhile(isOperatorChar);
|
78 | return "operator";
|
79 | }
|
80 | stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
81 | var cur = stream.current();
|
82 |
|
83 | if (keywords.propertyIsEnumerable(cur)) return "keyword";
|
84 | if (builtin.propertyIsEnumerable(cur)) return "builtin";
|
85 |
|
86 | if (timerOps.propertyIsEnumerable(cur)) return "def timerOps";
|
87 | if (configOps.propertyIsEnumerable(cur)) return "def configOps";
|
88 | if (verdictOps.propertyIsEnumerable(cur)) return "def verdictOps";
|
89 | if (portOps.propertyIsEnumerable(cur)) return "def portOps";
|
90 | if (sutOps.propertyIsEnumerable(cur)) return "def sutOps";
|
91 | if (functionOps.propertyIsEnumerable(cur)) return "def functionOps";
|
92 |
|
93 | if (verdictConsts.propertyIsEnumerable(cur)) return "string verdictConsts";
|
94 | if (booleanConsts.propertyIsEnumerable(cur)) return "string booleanConsts";
|
95 | if (otherConsts.propertyIsEnumerable(cur)) return "string otherConsts";
|
96 |
|
97 | if (types.propertyIsEnumerable(cur)) return "builtin types";
|
98 | if (visibilityModifiers.propertyIsEnumerable(cur))
|
99 | return "builtin visibilityModifiers";
|
100 | if (templateMatch.propertyIsEnumerable(cur)) return "atom templateMatch";
|
101 |
|
102 | return "variable";
|
103 | }
|
104 |
|
105 | function tokenString(quote) {
|
106 | return function(stream, state) {
|
107 | var escaped = false, next, end = false;
|
108 | while ((next = stream.next()) != null) {
|
109 | if (next == quote && !escaped){
|
110 | var afterQuote = stream.peek();
|
111 |
|
112 | if (afterQuote){
|
113 | afterQuote = afterQuote.toLowerCase();
|
114 | if(afterQuote == "b" || afterQuote == "h" || afterQuote == "o")
|
115 | stream.next();
|
116 | }
|
117 | end = true; break;
|
118 | }
|
119 | escaped = !escaped && next == "\\";
|
120 | }
|
121 | if (end || !(escaped || multiLineStrings))
|
122 | state.tokenize = null;
|
123 | return "string";
|
124 | };
|
125 | }
|
126 |
|
127 | function tokenComment(stream, state) {
|
128 | var maybeEnd = false, ch;
|
129 | while (ch = stream.next()) {
|
130 | if (ch == "/" && maybeEnd) {
|
131 | state.tokenize = null;
|
132 | break;
|
133 | }
|
134 | maybeEnd = (ch == "*");
|
135 | }
|
136 | return "comment";
|
137 | }
|
138 |
|
139 | function Context(indented, column, type, align, prev) {
|
140 | this.indented = indented;
|
141 | this.column = column;
|
142 | this.type = type;
|
143 | this.align = align;
|
144 | this.prev = prev;
|
145 | }
|
146 |
|
147 | function pushContext(state, col, type) {
|
148 | var indent = state.indented;
|
149 | if (state.context && state.context.type == "statement")
|
150 | indent = state.context.indented;
|
151 | return state.context = new Context(indent, col, type, null, state.context);
|
152 | }
|
153 |
|
154 | function popContext(state) {
|
155 | var t = state.context.type;
|
156 | if (t == ")" || t == "]" || t == "}")
|
157 | state.indented = state.context.indented;
|
158 | return state.context = state.context.prev;
|
159 | }
|
160 |
|
161 |
|
162 | return {
|
163 | startState: function(basecolumn) {
|
164 | return {
|
165 | tokenize: null,
|
166 | context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
|
167 | indented: 0,
|
168 | startOfLine: true
|
169 | };
|
170 | },
|
171 |
|
172 | token: function(stream, state) {
|
173 | var ctx = state.context;
|
174 | if (stream.sol()) {
|
175 | if (ctx.align == null) ctx.align = false;
|
176 | state.indented = stream.indentation();
|
177 | state.startOfLine = true;
|
178 | }
|
179 | if (stream.eatSpace()) return null;
|
180 | curPunc = null;
|
181 | var style = (state.tokenize || tokenBase)(stream, state);
|
182 | if (style == "comment") return style;
|
183 | if (ctx.align == null) ctx.align = true;
|
184 |
|
185 | if ((curPunc == ";" || curPunc == ":" || curPunc == ",")
|
186 | && ctx.type == "statement"){
|
187 | popContext(state);
|
188 | }
|
189 | else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
190 | else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
191 | else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
192 | else if (curPunc == "}") {
|
193 | while (ctx.type == "statement") ctx = popContext(state);
|
194 | if (ctx.type == "}") ctx = popContext(state);
|
195 | while (ctx.type == "statement") ctx = popContext(state);
|
196 | }
|
197 | else if (curPunc == ctx.type) popContext(state);
|
198 | else if (indentStatements &&
|
199 | (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
|
200 | (ctx.type == "statement" && curPunc == "newstatement")))
|
201 | pushContext(state, stream.column(), "statement");
|
202 |
|
203 | state.startOfLine = false;
|
204 |
|
205 | return style;
|
206 | },
|
207 |
|
208 | electricChars: "{}",
|
209 | blockCommentStart: "/*",
|
210 | blockCommentEnd: "*/",
|
211 | lineComment: "//",
|
212 | fold: "brace"
|
213 | };
|
214 | });
|
215 |
|
216 | function words(str) {
|
217 | var obj = {}, words = str.split(" ");
|
218 | for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
219 | return obj;
|
220 | }
|
221 |
|
222 | function def(mimes, mode) {
|
223 | if (typeof mimes == "string") mimes = [mimes];
|
224 | var words = [];
|
225 | function add(obj) {
|
226 | if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
|
227 | words.push(prop);
|
228 | }
|
229 |
|
230 | add(mode.keywords);
|
231 | add(mode.builtin);
|
232 | add(mode.timerOps);
|
233 | add(mode.portOps);
|
234 |
|
235 | if (words.length) {
|
236 | mode.helperType = mimes[0];
|
237 | CodeMirror.registerHelper("hintWords", mimes[0], words);
|
238 | }
|
239 |
|
240 | for (var i = 0; i < mimes.length; ++i)
|
241 | CodeMirror.defineMIME(mimes[i], mode);
|
242 | }
|
243 |
|
244 | def(["text/x-ttcn", "text/x-ttcn3", "text/x-ttcnpp"], {
|
245 | name: "ttcn",
|
246 | keywords: words("activate address alive all alt altstep and and4b any" +
|
247 | " break case component const continue control deactivate" +
|
248 | " display do else encode enumerated except exception" +
|
249 | " execute extends extension external for from function" +
|
250 | " goto group if import in infinity inout interleave" +
|
251 | " label language length log match message mixed mod" +
|
252 | " modifies module modulepar mtc noblock not not4b nowait" +
|
253 | " of on optional or or4b out override param pattern port" +
|
254 | " procedure record recursive rem repeat return runs select" +
|
255 | " self sender set signature system template testcase to" +
|
256 | " type union value valueof var variant while with xor xor4b"),
|
257 | builtin: words("bit2hex bit2int bit2oct bit2str char2int char2oct encvalue" +
|
258 | " decomp decvalue float2int float2str hex2bit hex2int" +
|
259 | " hex2oct hex2str int2bit int2char int2float int2hex" +
|
260 | " int2oct int2str int2unichar isbound ischosen ispresent" +
|
261 | " isvalue lengthof log2str oct2bit oct2char oct2hex oct2int" +
|
262 | " oct2str regexp replace rnd sizeof str2bit str2float" +
|
263 | " str2hex str2int str2oct substr unichar2int unichar2char" +
|
264 | " enum2int"),
|
265 | types: words("anytype bitstring boolean char charstring default float" +
|
266 | " hexstring integer objid octetstring universal verdicttype timer"),
|
267 | timerOps: words("read running start stop timeout"),
|
268 | portOps: words("call catch check clear getcall getreply halt raise receive" +
|
269 | " reply send trigger"),
|
270 | configOps: words("create connect disconnect done kill killed map unmap"),
|
271 | verdictOps: words("getverdict setverdict"),
|
272 | sutOps: words("action"),
|
273 | functionOps: words("apply derefers refers"),
|
274 |
|
275 | verdictConsts: words("error fail inconc none pass"),
|
276 | booleanConsts: words("true false"),
|
277 | otherConsts: words("null NULL omit"),
|
278 |
|
279 | visibilityModifiers: words("private public friend"),
|
280 | templateMatch: words("complement ifpresent subset superset permutation"),
|
281 | multiLineStrings: true
|
282 | });
|
283 | });
|