corrade-nucleus-nucleons – Blame information for rev 2
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
2 | office | 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others |
2 | // Distributed under an MIT license: http://codemirror.net/LICENSE |
||
3 | |||
4 | // TODO actually recognize syntax of TypeScript constructs |
||
5 | |||
6 | (function(mod) { |
||
7 | if (typeof exports == "object" && typeof module == "object") // CommonJS |
||
8 | mod(require("../../lib/codemirror")); |
||
9 | else if (typeof define == "function" && define.amd) // AMD |
||
10 | define(["../../lib/codemirror"], mod); |
||
11 | else // Plain browser env |
||
12 | mod(CodeMirror); |
||
13 | })(function(CodeMirror) { |
||
14 | "use strict"; |
||
15 | |||
16 | CodeMirror.defineMode("javascript", function(config, parserConfig) { |
||
17 | var indentUnit = config.indentUnit; |
||
18 | var statementIndent = parserConfig.statementIndent; |
||
19 | var jsonldMode = parserConfig.jsonld; |
||
20 | var jsonMode = parserConfig.json || jsonldMode; |
||
21 | var isTS = parserConfig.typescript; |
||
22 | var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; |
||
23 | |||
24 | // Tokenizer |
||
25 | |||
26 | var keywords = function(){ |
||
27 | function kw(type) {return {type: type, style: "keyword"};} |
||
28 | var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); |
||
29 | var operator = kw("operator"), atom = {type: "atom", style: "atom"}; |
||
30 | |||
31 | var jsKeywords = { |
||
32 | "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, |
||
33 | "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, |
||
34 | "var": kw("var"), "const": kw("var"), "let": kw("var"), |
||
35 | "function": kw("function"), "catch": kw("catch"), |
||
36 | "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), |
||
37 | "in": operator, "typeof": operator, "instanceof": operator, |
||
38 | "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, |
||
39 | "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), |
||
40 | "yield": C, "export": kw("export"), "import": kw("import"), "extends": C |
||
41 | }; |
||
42 | |||
43 | // Extend the 'normal' keywords with the TypeScript language extensions |
||
44 | if (isTS) { |
||
45 | var type = {type: "variable", style: "variable-3"}; |
||
46 | var tsKeywords = { |
||
47 | // object-like things |
||
48 | "interface": kw("interface"), |
||
49 | "extends": kw("extends"), |
||
50 | "constructor": kw("constructor"), |
||
51 | |||
52 | // scope modifiers |
||
53 | "public": kw("public"), |
||
54 | "private": kw("private"), |
||
55 | "protected": kw("protected"), |
||
56 | "static": kw("static"), |
||
57 | |||
58 | // types |
||
59 | "string": type, "number": type, "bool": type, "any": type |
||
60 | }; |
||
61 | |||
62 | for (var attr in tsKeywords) { |
||
63 | jsKeywords[attr] = tsKeywords[attr]; |
||
64 | } |
||
65 | } |
||
66 | |||
67 | return jsKeywords; |
||
68 | }(); |
||
69 | |||
70 | var isOperatorChar = /[+\-*&%=<>!?|~^]/;> |
||
71 | <> var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;> |
||
72 | |||
73 | <> function readRegexp(stream) {> |
||
74 | <> var escaped = false, next, inSet = false;> |
||
75 | <> while ((next = stream.next()) != null) {> |
||
76 | <> if (!escaped) {> |
||
77 | <> if (next == "/" && !inSet) return;> |
||
78 | <> if (next == "[") inSet = true;> |
||
79 | <> else if (inSet && next == "]") inSet = false;> |
||
80 | <> }> |
||
81 | <> escaped = !escaped && next == "\\";> |
||
82 | <> }> |
||
83 | <> }> |
||
84 | |||
85 | <> // Used as scratch variables to communicate multiple values without> |
||
86 | <> // consing up tons of objects.> |
||
87 | <> var type, content;> |
||
88 | <> function ret(tp, style, cont) {> |
||
89 | <> type = tp; content = cont;> |
||
90 | <> return style;> |
||
91 | <> }> |
||
92 | <> function tokenBase(stream, state) {> |
||
93 | <> var ch = stream.next();> |
||
94 | <> if (ch == '"' || ch == "'") {> |
||
95 | <> state.tokenize = tokenString(ch);> |
||
96 | <> return state.tokenize(stream, state);> |
||
97 | <> } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {> |
||
98 | <> return ret("number", "number");> |
||
99 | <> } else if (ch == "." && stream.match("..")) {> |
||
100 | <> return ret("spread", "meta");> |
||
101 | <> } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {> |
||
102 | <> return ret(ch);> |
||
103 | <> } else if (ch == "=" && stream.eat(">")) {> |
||
104 | <> return ret("=>", "operator");> |
||
105 | <> } else if (ch == "0" && stream.eat(/x/i)) {> |
||
106 | <> stream.eatWhile(/[\da-f]/i);> |
||
107 | <> return ret("number", "number");> |
||
108 | <> } else if (/\d/.test(ch)) {> |
||
109 | <> stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);> |
||
110 | <> return ret("number", "number");> |
||
111 | <> } else if (ch == "/") {> |
||
112 | <> if (stream.eat("*")) {> |
||
113 | <> state.tokenize = tokenComment;> |
||
114 | <> return tokenComment(stream, state);> |
||
115 | <> } else if (stream.eat("/")) {> |
||
116 | <> stream.skipToEnd();> |
||
117 | <> return ret("comment", "comment");> |
||
118 | <> } else if (state.lastType == "operator" || state.lastType == "keyword c" ||> |
||
119 | <> state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {> |
||
120 | <> readRegexp(stream);> |
||
121 | <> stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);> |
||
122 | <> return ret("regexp", "string-2");> |
||
123 | <> } else {> |
||
124 | <> stream.eatWhile(isOperatorChar);> |
||
125 | <> return ret("operator", "operator", stream.current());> |
||
126 | <> }> |
||
127 | <> } else if (ch == "`") {> |
||
128 | <> state.tokenize = tokenQuasi;> |
||
129 | <> return tokenQuasi(stream, state);> |
||
130 | <> } else if (ch == "#") {> |
||
131 | <> stream.skipToEnd();> |
||
132 | <> return ret("error", "error");> |
||
133 | <> } else if (isOperatorChar.test(ch)) {> |
||
134 | <> stream.eatWhile(isOperatorChar);> |
||
135 | <> return ret("operator", "operator", stream.current());> |
||
136 | <> } else if (wordRE.test(ch)) {> |
||
137 | <> stream.eatWhile(wordRE);> |
||
138 | <> var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];> |
||
139 | <> return (known && state.lastType != ".") ? ret(known.type, known.style, word) :> |
||
140 | <> ret("variable", "variable", word);> |
||
141 | <> }> |
||
142 | <> }> |
||
143 | |||
144 | <> function tokenString(quote) {> |
||
145 | <> return function(stream, state) {> |
||
146 | <> var escaped = false, next;> |
||
147 | <> if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){> |
||
148 | <> state.tokenize = tokenBase;> |
||
149 | <> return ret("jsonld-keyword", "meta");> |
||
150 | <> }> |
||
151 | <> while ((next = stream.next()) != null) {> |
||
152 | <> if (next == quote && !escaped) break;> |
||
153 | <> escaped = !escaped && next == "\\";> |
||
154 | <> }> |
||
155 | <> if (!escaped) state.tokenize = tokenBase;> |
||
156 | <> return ret("string", "string");> |
||
157 | <> };> |
||
158 | <> }> |
||
159 | |||
160 | <> function tokenComment(stream, state) {> |
||
161 | <> var maybeEnd = false, ch;> |
||
162 | <> while (ch = stream.next()) {> |
||
163 | <> if (ch == "/" && maybeEnd) {> |
||
164 | <> state.tokenize = tokenBase;> |
||
165 | <> break;> |
||
166 | <> }> |
||
167 | <> maybeEnd = (ch == "*");> |
||
168 | <> }> |
||
169 | <> return ret("comment", "comment");> |
||
170 | <> }> |
||
171 | |||
172 | <> function tokenQuasi(stream, state) {> |
||
173 | <> var escaped = false, next;> |
||
174 | <> while ((next = stream.next()) != null) {> |
||
175 | <> if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {> |
||
176 | <> state.tokenize = tokenBase;> |
||
177 | <> break;> |
||
178 | <> }> |
||
179 | <> escaped = !escaped && next == "\\";> |
||
180 | <> }> |
||
181 | <> return ret("quasi", "string-2", stream.current());> |
||
182 | <> }> |
||
183 | |||
184 | <> var brackets = "([{}])";> |
||
185 | <> // This is a crude lookahead trick to try and notice that we're> |
||
186 | <> // parsing the argument patterns for a fat-arrow function before we> |
||
187 | <> // actually hit the arrow token. It only works if the arrow is on> |
||
188 | <> // the same line as the arguments and there's no strange noise> |
||
189 | <> // (comments) in between. Fallback is to only notice when we hit the> |
||
190 | <> // arrow, and not declare the arguments as locals for the arrow> |
||
191 | <> // body.> |
||
192 | <> function findFatArrow(stream, state) {> |
||
193 | <> if (state.fatArrowAt) state.fatArrowAt = null;> |
||
194 | <> var arrow = stream.string.indexOf("=>", stream.start);> |
||
195 | <> if (arrow < 0) return;> |
||
196 | |||
197 | <> var depth = 0, sawSomething = false;> |
||
198 | <> for (var pos = arrow - 1; pos >= 0; --pos) {> |
||
199 | <> var ch = stream.string.charAt(pos);> |
||
200 | <> var bracket = brackets.indexOf(ch);> |
||
201 | <> if (bracket >= 0 && bracket < 3) {> |
||
202 | <> if (!depth) { ++pos; break; }> |
||
203 | <> if (--depth == 0) break;> |
||
204 | <> } else if (bracket >= 3 && bracket < 6) {> |
||
205 | <> ++depth;> |
||
206 | <> } else if (wordRE.test(ch)) {> |
||
207 | <> sawSomething = true;> |
||
208 | <> } else if (/["'\/]/.test(ch)) {> |
||
209 | <> return;> |
||
210 | <> } else if (sawSomething && !depth) {> |
||
211 | <> ++pos;> |
||
212 | <> break;> |
||
213 | <> }> |
||
214 | <> }> |
||
215 | <> if (sawSomething && !depth) state.fatArrowAt = pos;> |
||
216 | <> }> |
||
217 | |||
218 | <> // Parser> |
||
219 | |||
220 | <> var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};> |
||
221 | |||
222 | <> function JSLexical(indented, column, type, align, prev, info) {> |
||
223 | <> this.indented = indented;> |
||
224 | <> this.column = column;> |
||
225 | <> this.type = type;> |
||
226 | <> this.prev = prev;> |
||
227 | <> this.info = info;> |
||
228 | <> if (align != null) this.align = align;> |
||
229 | <> }> |
||
230 | |||
231 | <> function inScope(state, varname) {> |
||
232 | <> for (var v = state.localVars; v; v = v.next)> |
||
233 | <> if (v.name == varname) return true;> |
||
234 | <> for (var cx = state.context; cx; cx = cx.prev) {> |
||
235 | <> for (var v = cx.vars; v; v = v.next)> |
||
236 | <> if (v.name == varname) return true;> |
||
237 | <> }> |
||
238 | <> }> |
||
239 | |||
240 | <> function parseJS(state, style, type, content, stream) {> |
||
241 | <> var cc = state.cc;> |
||
242 | <> // Communicate our context to the combinators.> |
||
243 | <> // (Less wasteful than consing up a hundred closures on every call.)> |
||
244 | <> cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;> |
||
245 | |||
246 | <> if (!state.lexical.hasOwnProperty("align"))> |
||
247 | <> state.lexical.align = true;> |
||
248 | |||
249 | <> while(true) {> |
||
250 | <> var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;> |
||
251 | <> if (combinator(type, content)) {> |
||
252 | <> while(cc.length && cc[cc.length - 1].lex)> |
||
253 | <> cc.pop()();> |
||
254 | <> if (cx.marked) return cx.marked;> |
||
255 | <> if (type == "variable" && inScope(state, content)) return "variable-2";> |
||
256 | <> return style;> |
||
257 | <> }> |
||
258 | <> }> |
||
259 | <> }> |
||
260 | |||
261 | <> // Combinator utils> |
||
262 | |||
263 | <> var cx = {state: null, column: null, marked: null, cc: null};> |
||
264 | <> function pass() {> |
||
265 | <> for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);> |
||
266 | <> }> |
||
267 | <> function cont() {> |
||
268 | <> pass.apply(null, arguments);> |
||
269 | <> return true;> |
||
270 | <> }> |
||
271 | <> function register(varname) {> |
||
272 | <> function inList(list) {> |
||
273 | <> for (var v = list; v; v = v.next)> |
||
274 | <> if (v.name == varname) return true;> |
||
275 | <> return false;> |
||
276 | <> }> |
||
277 | <> var state = cx.state;> |
||
278 | <> if (state.context) {> |
||
279 | <> cx.marked = "def";> |
||
280 | <> if (inList(state.localVars)) return;> |
||
281 | <> state.localVars = {name: varname, next: state.localVars};> |
||
282 | <> } else {> |
||
283 | <> if (inList(state.globalVars)) return;> |
||
284 | <> if (parserConfig.globalVars)> |
||
285 | <> state.globalVars = {name: varname, next: state.globalVars};> |
||
286 | <> }> |
||
287 | <> }> |
||
288 | |||
289 | <> // Combinators> |
||
290 | |||
291 | <> var defaultVars = {name: "this", next: {name: "arguments"}};> |
||
292 | <> function pushcontext() {> |
||
293 | <> cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};> |
||
294 | <> cx.state.localVars = defaultVars;> |
||
295 | <> }> |
||
296 | <> function popcontext() {> |
||
297 | <> cx.state.localVars = cx.state.context.vars;> |
||
298 | <> cx.state.context = cx.state.context.prev;> |
||
299 | <> }> |
||
300 | <> function pushlex(type, info) {> |
||
301 | <> var result = function() {> |
||
302 | <> var state = cx.state, indent = state.indented;> |
||
303 | <> if (state.lexical.type == "stat") indent = state.lexical.indented;> |
||
304 | <> else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)> |
||
305 | <> indent = outer.indented;> |
||
306 | <> state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);> |
||
307 | <> };> |
||
308 | <> result.lex = true;> |
||
309 | <> return result;> |
||
310 | <> }> |
||
311 | <> function poplex() {> |
||
312 | <> var state = cx.state;> |
||
313 | <> if (state.lexical.prev) {> |
||
314 | <> if (state.lexical.type == ")")> |
||
315 | <> state.indented = state.lexical.indented;> |
||
316 | <> state.lexical = state.lexical.prev;> |
||
317 | <> }> |
||
318 | <> }> |
||
319 | <> poplex.lex = true;> |
||
320 | |||
321 | <> function expect(wanted) {> |
||
322 | <> function exp(type) {> |
||
323 | <> if (type == wanted) return cont();> |
||
324 | <> else if (wanted == ";") return pass();> |
||
325 | <> else return cont(exp);> |
||
326 | <> };> |
||
327 | <> return exp;> |
||
328 | <> }> |
||
329 | |||
330 | <> function statement(type, value) {> |
||
331 | <> if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);> |
||
332 | <> if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);> |
||
333 | <> if (type == "keyword b") return cont(pushlex("form"), statement, poplex);> |
||
334 | <> if (type == "{") return cont(pushlex("}"), block, poplex);> |
||
335 | <> if (type == ";") return cont();> |
||
336 | <> if (type == "if") {> |
||
337 | <> if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)> |
||
338 | <> cx.state.cc.pop()();> |
||
339 | <> return cont(pushlex("form"), expression, statement, poplex, maybeelse);> |
||
340 | <> }> |
||
341 | <> if (type == "function") return cont(functiondef);> |
||
342 | <> if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);> |
||
343 | <> if (type == "variable") return cont(pushlex("stat"), maybelabel);> |
||
344 | <> if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),> |
||
345 | <> block, poplex, poplex);> |
||
346 | <> if (type == "case") return cont(expression, expect(":"));> |
||
347 | <> if (type == "default") return cont(expect(":"));> |
||
348 | <> if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),> |
||
349 | <> statement, poplex, popcontext);> |
||
350 | <> if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);> |
||
351 | <> if (type == "class") return cont(pushlex("form"), className, poplex);> |
||
352 | <> if (type == "export") return cont(pushlex("form"), afterExport, poplex);> |
||
353 | <> if (type == "import") return cont(pushlex("form"), afterImport, poplex);> |
||
354 | <> return pass(pushlex("stat"), expression, expect(";"), poplex);> |
||
355 | <> }> |
||
356 | <> function expression(type) {> |
||
357 | <> return expressionInner(type, false);> |
||
358 | <> }> |
||
359 | <> function expressionNoComma(type) {> |
||
360 | <> return expressionInner(type, true);> |
||
361 | <> }> |
||
362 | <> function expressionInner(type, noComma) {> |
||
363 | <> if (cx.state.fatArrowAt == cx.stream.start) {> |
||
364 | <> var body = noComma ? arrowBodyNoComma : arrowBody;> |
||
365 | <> if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);> |
||
366 | <> else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);> |
||
367 | <> }> |
||
368 | |||
369 | <> var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;> |
||
370 | <> if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);> |
||
371 | <> if (type == "function") return cont(functiondef, maybeop);> |
||
372 | <> if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);> |
||
373 | <> if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);> |
||
374 | <> if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);> |
||
375 | <> if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);> |
||
376 | <> if (type == "{") return contCommasep(objprop, "}", null, maybeop);> |
||
377 | <> if (type == "quasi") { return pass(quasi, maybeop); }> |
||
378 | <> return cont();> |
||
379 | <> }> |
||
380 | <> function maybeexpression(type) {> |
||
381 | <> if (type.match(/[;\}\)\],]/)) return pass();> |
||
382 | <> return pass(expression);> |
||
383 | <> }> |
||
384 | <> function maybeexpressionNoComma(type) {> |
||
385 | <> if (type.match(/[;\}\)\],]/)) return pass();> |
||
386 | <> return pass(expressionNoComma);> |
||
387 | <> }> |
||
388 | |||
389 | <> function maybeoperatorComma(type, value) {> |
||
390 | <> if (type == ",") return cont(expression);> |
||
391 | <> return maybeoperatorNoComma(type, value, false);> |
||
392 | <> }> |
||
393 | <> function maybeoperatorNoComma(type, value, noComma) {> |
||
394 | <> var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;> |
||
395 | <> var expr = noComma == false ? expression : expressionNoComma;> |
||
396 | <> if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);> |
||
397 | <> if (type == "operator") {> |
||
398 | <> if (/\+\+|--/.test(value)) return cont(me);> |
||
399 | <> if (value == "?") return cont(expression, expect(":"), expr);> |
||
400 | <> return cont(expr);> |
||
401 | <> }> |
||
402 | <> if (type == "quasi") { return pass(quasi, me); }> |
||
403 | <> if (type == ";") return;> |
||
404 | <> if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);> |
||
405 | <> if (type == ".") return cont(property, me);> |
||
406 | <> if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);> |
||
407 | <> }> |
||
408 | <> function quasi(type, value) {> |
||
409 | <> if (type != "quasi") return pass();> |
||
410 | <> if (value.slice(value.length - 2) != "${") return cont(quasi);> |
||
411 | <> return cont(expression, continueQuasi);> |
||
412 | <> }> |
||
413 | <> function continueQuasi(type) {> |
||
414 | <> if (type == "}") {> |
||
415 | <> cx.marked = "string-2";> |
||
416 | <> cx.state.tokenize = tokenQuasi;> |
||
417 | <> return cont(quasi);> |
||
418 | <> }> |
||
419 | <> }> |
||
420 | <> function arrowBody(type) {> |
||
421 | <> findFatArrow(cx.stream, cx.state);> |
||
422 | <> return pass(type == "{" ? statement : expression);> |
||
423 | <> }> |
||
424 | <> function arrowBodyNoComma(type) {> |
||
425 | <> findFatArrow(cx.stream, cx.state);> |
||
426 | <> return pass(type == "{" ? statement : expressionNoComma);> |
||
427 | <> }> |
||
428 | <> function maybelabel(type) {> |
||
429 | <> if (type == ":") return cont(poplex, statement);> |
||
430 | <> return pass(maybeoperatorComma, expect(";"), poplex);> |
||
431 | <> }> |
||
432 | <> function property(type) {> |
||
433 | <> if (type == "variable") {cx.marked = "property"; return cont();}> |
||
434 | <> }> |
||
435 | <> function objprop(type, value) {> |
||
436 | <> if (type == "variable" || cx.style == "keyword") {> |
||
437 | <> cx.marked = "property";> |
||
438 | <> if (value == "get" || value == "set") return cont(getterSetter);> |
||
439 | <> return cont(afterprop);> |
||
440 | <> } else if (type == "number" || type == "string") {> |
||
441 | <> cx.marked = jsonldMode ? "property" : (cx.style + " property");> |
||
442 | <> return cont(afterprop);> |
||
443 | <> } else if (type == "jsonld-keyword") {> |
||
444 | <> return cont(afterprop);> |
||
445 | <> } else if (type == "[") {> |
||
446 | <> return cont(expression, expect("]"), afterprop);> |
||
447 | <> }> |
||
448 | <> }> |
||
449 | <> function getterSetter(type) {> |
||
450 | <> if (type != "variable") return pass(afterprop);> |
||
451 | <> cx.marked = "property";> |
||
452 | <> return cont(functiondef);> |
||
453 | <> }> |
||
454 | <> function afterprop(type) {> |
||
455 | <> if (type == ":") return cont(expressionNoComma);> |
||
456 | <> if (type == "(") return pass(functiondef);> |
||
457 | <> }> |
||
458 | <> function commasep(what, end) {> |
||
459 | <> function proceed(type) {> |
||
460 | <> if (type == ",") {> |
||
461 | <> var lex = cx.state.lexical;> |
||
462 | <> if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;> |
||
463 | <> return cont(what, proceed);> |
||
464 | <> }> |
||
465 | <> if (type == end) return cont();> |
||
466 | <> return cont(expect(end));> |
||
467 | <> }> |
||
468 | <> return function(type) {> |
||
469 | <> if (type == end) return cont();> |
||
470 | <> return pass(what, proceed);> |
||
471 | <> };> |
||
472 | <> }> |
||
473 | <> function contCommasep(what, end, info) {> |
||
474 | <> for (var i = 3; i < arguments.length; i++)> |
||
475 | <> cx.cc.push(arguments[i]);> |
||
476 | <> return cont(pushlex(end, info), commasep(what, end), poplex);> |
||
477 | <> }> |
||
478 | <> function block(type) {> |
||
479 | <> if (type == "}") return cont();> |
||
480 | <> return pass(statement, block);> |
||
481 | <> }> |
||
482 | <> function maybetype(type) {> |
||
483 | <> if (isTS && type == ":") return cont(typedef);> |
||
484 | <> }> |
||
485 | <> function typedef(type) {> |
||
486 | <> if (type == "variable"){cx.marked = "variable-3"; return cont();}> |
||
487 | <> }> |
||
488 | <> function vardef() {> |
||
489 | <> return pass(pattern, maybetype, maybeAssign, vardefCont);> |
||
490 | <> }> |
||
491 | <> function pattern(type, value) {> |
||
492 | <> if (type == "variable") { register(value); return cont(); }> |
||
493 | <> if (type == "[") return contCommasep(pattern, "]");> |
||
494 | <> if (type == "{") return contCommasep(proppattern, "}");> |
||
495 | <> }> |
||
496 | <> function proppattern(type, value) {> |
||
497 | <> if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {> |
||
498 | <> register(value);> |
||
499 | <> return cont(maybeAssign);> |
||
500 | <> }> |
||
501 | <> if (type == "variable") cx.marked = "property";> |
||
502 | <> return cont(expect(":"), pattern, maybeAssign);> |
||
503 | <> }> |
||
504 | <> function maybeAssign(_type, value) {> |
||
505 | <> if (value == "=") return cont(expressionNoComma);> |
||
506 | <> }> |
||
507 | <> function vardefCont(type) {> |
||
508 | <> if (type == ",") return cont(vardef);> |
||
509 | <> }> |
||
510 | <> function maybeelse(type, value) {> |
||
511 | <> if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);> |
||
512 | <> }> |
||
513 | <> function forspec(type) {> |
||
514 | <> if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);> |
||
515 | <> }> |
||
516 | <> function forspec1(type) {> |
||
517 | <> if (type == "var") return cont(vardef, expect(";"), forspec2);> |
||
518 | <> if (type == ";") return cont(forspec2);> |
||
519 | <> if (type == "variable") return cont(formaybeinof);> |
||
520 | <> return pass(expression, expect(";"), forspec2);> |
||
521 | <> }> |
||
522 | <> function formaybeinof(_type, value) {> |
||
523 | <> if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }> |
||
524 | <> return cont(maybeoperatorComma, forspec2);> |
||
525 | <> }> |
||
526 | <> function forspec2(type, value) {> |
||
527 | <> if (type == ";") return cont(forspec3);> |
||
528 | <> if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }> |
||
529 | <> return pass(expression, expect(";"), forspec3);> |
||
530 | <> }> |
||
531 | <> function forspec3(type) {> |
||
532 | <> if (type != ")") cont(expression);> |
||
533 | <> }> |
||
534 | <> function functiondef(type, value) {> |
||
535 | <> if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}> |
||
536 | <> if (type == "variable") {register(value); return cont(functiondef);}> |
||
537 | <> if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);> |
||
538 | <> }> |
||
539 | <> function funarg(type) {> |
||
540 | <> if (type == "spread") return cont(funarg);> |
||
541 | <> return pass(pattern, maybetype);> |
||
542 | <> }> |
||
543 | <> function className(type, value) {> |
||
544 | <> if (type == "variable") {register(value); return cont(classNameAfter);}> |
||
545 | <> }> |
||
546 | <> function classNameAfter(type, value) {> |
||
547 | <> if (value == "extends") return cont(expression, classNameAfter);> |
||
548 | <> if (type == "{") return cont(pushlex("}"), classBody, poplex);> |
||
549 | <> }> |
||
550 | <> function classBody(type, value) {> |
||
551 | <> if (type == "variable" || cx.style == "keyword") {> |
||
552 | <> cx.marked = "property";> |
||
553 | <> if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);> |
||
554 | <> return cont(functiondef, classBody);> |
||
555 | <> }> |
||
556 | <> if (value == "*") {> |
||
557 | <> cx.marked = "keyword";> |
||
558 | <> return cont(classBody);> |
||
559 | <> }> |
||
560 | <> if (type == ";") return cont(classBody);> |
||
561 | <> if (type == "}") return cont();> |
||
562 | <> }> |
||
563 | <> function classGetterSetter(type) {> |
||
564 | <> if (type != "variable") return pass();> |
||
565 | <> cx.marked = "property";> |
||
566 | <> return cont();> |
||
567 | <> }> |
||
568 | <> function afterModule(type, value) {> |
||
569 | <> if (type == "string") return cont(statement);> |
||
570 | <> if (type == "variable") { register(value); return cont(maybeFrom); }> |
||
571 | <> }> |
||
572 | <> function afterExport(_type, value) {> |
||
573 | <> if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }> |
||
574 | <> if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }> |
||
575 | <> return pass(statement);> |
||
576 | <> }> |
||
577 | <> function afterImport(type) {> |
||
578 | <> if (type == "string") return cont();> |
||
579 | <> return pass(importSpec, maybeFrom);> |
||
580 | <> }> |
||
581 | <> function importSpec(type, value) {> |
||
582 | <> if (type == "{") return contCommasep(importSpec, "}");> |
||
583 | <> if (type == "variable") register(value);> |
||
584 | <> return cont();> |
||
585 | <> }> |
||
586 | <> function maybeFrom(_type, value) {> |
||
587 | <> if (value == "from") { cx.marked = "keyword"; return cont(expression); }> |
||
588 | <> }> |
||
589 | <> function arrayLiteral(type) {> |
||
590 | <> if (type == "]") return cont();> |
||
591 | <> return pass(expressionNoComma, maybeArrayComprehension);> |
||
592 | <> }> |
||
593 | <> function maybeArrayComprehension(type) {> |
||
594 | <> if (type == "for") return pass(comprehension, expect("]"));> |
||
595 | <> if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));> |
||
596 | <> return pass(commasep(expressionNoComma, "]"));> |
||
597 | <> }> |
||
598 | <> function comprehension(type) {> |
||
599 | <> if (type == "for") return cont(forspec, comprehension);> |
||
600 | <> if (type == "if") return cont(expression, comprehension);> |
||
601 | <> }> |
||
602 | |||
603 | <> function isContinuedStatement(state, textAfter) {> |
||
604 | <> return state.lastType == "operator" || state.lastType == "," ||> |
||
605 | <> isOperatorChar.test(textAfter.charAt(0)) ||> |
||
606 | <> /[,.]/.test(textAfter.charAt(0));> |
||
607 | <> }> |
||
608 | |||
609 | <> // Interface> |
||
610 | |||
611 | <> return {> |
||
612 | <> startState: function(basecolumn) {> |
||
613 | <> var state = {> |
||
614 | <> tokenize: tokenBase,> |
||
615 | <> lastType: "sof",> |
||
616 | <> cc: [],> |
||
617 | <> lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),> |
||
618 | <> localVars: parserConfig.localVars,> |
||
619 | <> context: parserConfig.localVars && {vars: parserConfig.localVars},> |
||
620 | <> indented: 0> |
||
621 | <> };> |
||
622 | <> if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")> |
||
623 | <> state.globalVars = parserConfig.globalVars;> |
||
624 | <> return state;> |
||
625 | <> },> |
||
626 | |||
627 | <> token: function(stream, state) {> |
||
628 | <> if (stream.sol()) {> |
||
629 | <> if (!state.lexical.hasOwnProperty("align"))> |
||
630 | <> state.lexical.align = false;> |
||
631 | <> state.indented = stream.indentation();> |
||
632 | <> findFatArrow(stream, state);> |
||
633 | <> }> |
||
634 | <> if (state.tokenize != tokenComment && stream.eatSpace()) return null;> |
||
635 | <> var style = state.tokenize(stream, state);> |
||
636 | <> if (type == "comment") return style;> |
||
637 | <> state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;> |
||
638 | <> return parseJS(state, style, type, content, stream);> |
||
639 | <> },> |
||
640 | |||
641 | <> indent: function(state, textAfter) {> |
||
642 | <> if (state.tokenize == tokenComment) return CodeMirror.Pass;> |
||
643 | <> if (state.tokenize != tokenBase) return 0;> |
||
644 | <> var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;> |
||
645 | <> // Kludge to prevent 'maybelse' from blocking lexical scope pops> |
||
646 | <> if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {> |
||
647 | <> var c = state.cc[i];> |
||
648 | <> if (c == poplex) lexical = lexical.prev;> |
||
649 | <> else if (c != maybeelse) break;> |
||
650 | <> }> |
||
651 | <> if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;> |
||
652 | <> if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")> |
||
653 | <> lexical = lexical.prev;> |
||
654 | <> var type = lexical.type, closing = firstChar == type;> |
||
655 | |||
656 | <> if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);> |
||
657 | <> else if (type == "form" && firstChar == "{") return lexical.indented;> |
||
658 | <> else if (type == "form") return lexical.indented + indentUnit;> |
||
659 | <> else if (type == "stat")> |
||
660 | <> return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);> |
||
661 | <> else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)> |
||
662 | <> return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);> |
||
663 | <> else if (lexical.align) return lexical.column + (closing ? 0 : 1);> |
||
664 | <> else return lexical.indented + (closing ? 0 : indentUnit);> |
||
665 | <> },> |
||
666 | |||
667 | <> electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,> |
||
668 | <> blockCommentStart: jsonMode ? null : "/*",> |
||
669 | <> blockCommentEnd: jsonMode ? null : "*/",> |
||
670 | <> lineComment: jsonMode ? null : "//",> |
||
671 | <> fold: "brace",> |
||
672 | |||
673 | <> helperType: jsonMode ? "json" : "javascript",> |
||
674 | <> jsonldMode: jsonldMode,> |
||
675 | <> jsonMode: jsonMode> |
||
676 | <> };> |
||
677 | <>});> |
||
678 | |||
679 | <>CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);> |
||
680 | |||
681 | <>CodeMirror.defineMIME("text/javascript", "javascript");> |
||
682 | <>CodeMirror.defineMIME("text/ecmascript", "javascript");> |
||
683 | <>CodeMirror.defineMIME("application/javascript", "javascript");> |
||
684 | <>CodeMirror.defineMIME("application/x-javascript", "javascript");> |
||
685 | <>CodeMirror.defineMIME("application/ecmascript", "javascript");> |
||
686 | <>CodeMirror.defineMIME("application/json", {name: "javascript", json: true});> |
||
687 | <>CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});> |
||
688 | <>CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});> |
||
689 | <>CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });> |
||
690 | <>CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });> |
||
691 | |||
692 | <>});> |