pyret-npm 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,579 @@
1
+ define("pyret-base/js/pyret-tokenizer", ["jglr/jglr"], function(E) {
2
+ const SrcLoc = E.SrcLoc
3
+ const GenTokenizer = E.Tokenizer2;
4
+ const IGNORED_WS = {name: "WS"};
5
+
6
+ function Tokenizer(spec) {
7
+ [spec.keywords, spec.comments, spec.symbols].forEach(function(specs) {
8
+ for (var first in specs)
9
+ specs[first].forEach(function(s) {
10
+ if (s.parenIsForExp === true)
11
+ s.parenIsForExp = "PARENSPACE";
12
+ else if (!s.parenIsForExp)
13
+ s.parenIsForExp = false;
14
+ });
15
+ });
16
+ for (var first in spec.keywords) {
17
+ spec.keywords[first].forEach(function(s) { s.noFollow = spec.keywordsNoFollow; })
18
+ }
19
+ GenTokenizer.call(this, spec);
20
+ this.parenIsForExp = "PARENSPACE";
21
+ }
22
+ Tokenizer.prototype = Object.create(GenTokenizer.prototype);
23
+ Tokenizer.prototype.tokenizeFrom = function(str) {
24
+ GenTokenizer.prototype.tokenizeFrom.call(this, str);
25
+ this.parenIsForExp = "PARENSPACE";
26
+ }
27
+ Tokenizer.prototype.makeToken = function makeToken(tok_name, s, pos, tok_spec) {
28
+ var t = new E.Token(tok_name, s);
29
+ t.pos = pos;
30
+ this.parenIsForExp = tok_spec && tok_spec.parenIsForExp;
31
+ this.priorWhitespace = false;
32
+ return t;
33
+ };
34
+ Tokenizer.prototype.makeWSToken = function makeWSToken(startLine, startCol, startPos) {
35
+ this.parenIsForExp = true;
36
+ this.priorWhitespace = true;
37
+ this.addWhitespace(SrcLoc.make(startLine, startCol, startPos, this.line, this.col, this.pos));
38
+ return IGNORED_WS;
39
+ // var t = new E.Token("WS", this.str.slice(startPos, this.pos));
40
+ // t.pos = SrcLoc.make(startLine, startCol, startPos, this.line, this.col, this.pos);
41
+ // // Note: do not change parenIsForExp at all
42
+ // return t;
43
+ }
44
+
45
+ const escapes = new RegExp("^(.*?)\\\\([\\\\\"\'nrt]|u[0-9A-Fa-f]{1,4}|x[0-9A-Fa-f]{1,2}|[0-7]{1,3}|[\r\n]{1,2})");
46
+ function fixEscapes(s) {
47
+ var ret = "";
48
+ var match = escapes.exec(s);
49
+ while (match !== null) {
50
+ var esc = match[2];
51
+ ret += match[1];
52
+ s = s.slice(match[0].length);
53
+ if (esc === "\n") {}
54
+ else if (esc === "\r") {}
55
+ else if (esc === "\n\r") {}
56
+ else if (esc === "\r\n") {}
57
+ else if (esc === "n") { ret += "\n"; }
58
+ else if (esc === "r") { ret += "\r"; }
59
+ else if (esc === "t") { ret += "\t"; }
60
+ else if (esc === "\"") { ret += "\""; }
61
+ else if (esc === "'") { ret += "'"; }
62
+ else if (esc === "\\") { ret += "\\"; }
63
+ else if (esc[0] === 'u') { ret += String.fromCharCode(parseInt(esc.slice(1), 16)); }
64
+ else if (esc[0] === 'x') { ret += String.fromCharCode(parseInt(esc.slice(1), 16)); }
65
+ else { ret += String.fromCharCode(parseInt(esc, 8)); }
66
+ match = escapes.exec(s);
67
+ }
68
+ ret += s;
69
+ return ret;
70
+ }
71
+
72
+ function makeTrie(kwds) {
73
+ var ans = Object.create(null);
74
+ for (var i = 0; i < kwds.length; i++) {
75
+ var firsts = kwds[i].firsts || [kwds[i].val[0]];
76
+ firsts.forEach(function(first) {
77
+ var byFirst = ans[first];
78
+ if (byFirst === undefined)
79
+ byFirst = ans[first] = [];
80
+ byFirst.push(kwds[i]);
81
+ })
82
+ }
83
+ return ans;
84
+ }
85
+ function makeDict(str) {
86
+ var ans = {};
87
+ for (var i = 0; i < str.length; i++) {
88
+ ans[str[i]] = true;
89
+ }
90
+ return ans;
91
+ }
92
+
93
+ var keywords = makeTrie([
94
+ {name: "AND", val: "and", parenIsForExp: true},
95
+ {name: "AS", val: "as"},
96
+ {name: "ASCENDING", val: "ascending"},
97
+ {name: "ASK", val: "ask", parenIsForExp: true},
98
+ {name: "BY", val: "by"},
99
+ {name: "CASES", val: "cases"},
100
+ {name: "CHECK", val: "check"},
101
+ {name: "DATA", val: "data"},
102
+ {name: "DESCENDING", val: "descending"},
103
+ {name: "DO", val: "do"},
104
+ {name: "RAISESNOT", val: "does-not-raise", parenIsForExp: true},
105
+ {name: "ELSE", val: "else"},
106
+ {name: "ELSEIF", val: "else if"},
107
+ {name: "END", val: "end"},
108
+ {name: "EXAMPLES", val: "examples", parenIsForExp: true},
109
+ {name: "TABLE-EXTEND", val: "extend"},
110
+ {name: "TABLE-EXTRACT", val: "extract"},
111
+ {name: "FALSE", val: "false"},
112
+ {name: "FOR", val: "for"},
113
+ {name: "FROM", val: "from"},
114
+ {name: "FUN", val: "fun"},
115
+ {name: "HIDING", val: "hiding"},
116
+ {name: "IF", val: "if"},
117
+ {name: "IMPORT", val: "import"},
118
+ {name: "INCLUDE", val: "include"},
119
+ {name: "IS", val: "is", parenIsForExp: true},
120
+ {name: "ISEQUALEQUAL", val: "is==", parenIsForExp: true},
121
+ {name: "ISEQUALTILDE", val: "is=~", parenIsForExp: true},
122
+ {name: "ISNOT", val: "is-not", parenIsForExp: true},
123
+ {name: "ISNOTEQUALEQUAL", val: "is-not==", parenIsForExp: true},
124
+ {name: "ISNOTEQUALTILDE", val: "is-not=~", parenIsForExp: true},
125
+ {name: "ISNOTSPACESHIP", val: "is-not<=>", parenIsForExp: true},
126
+ {name: "ISROUGHLY", val: "is-roughly", parenIsForExp: true},
127
+ {name: "ISNOTROUGHLY", val: "is-not-roughly", parenIsForExp: true},
128
+ {name: "ISSPACESHIP", val: "is<=>", parenIsForExp: true},
129
+ {name: "BECAUSE", val: "because", parenIsForExp: true},
130
+ {name: "LAM", val: "lam"},
131
+ {name: "LAZY", val: "lazy"},
132
+ {name: "LET", val: "let"},
133
+ {name: "LETREC", val: "letrec"},
134
+ {name: "LOAD-TABLE", val: "load-table"},
135
+ {name: "METHOD", val: "method"},
136
+ {name: "MODULE", val: "module"},
137
+ {name: "NEWTYPE", val: "newtype"},
138
+ {name: "OF", val: "of"},
139
+ {name: "OR", val: "or", parenIsForExp: true},
140
+ {name: "PROVIDE", val: "provide"},
141
+ {name: "PROVIDE-TYPES", val: "provide-types"},
142
+ {name: "RAISES", val: "raises", parenIsForExp: true},
143
+ {name: "RAISESOTHER", val: "raises-other-than", parenIsForExp: true},
144
+ {name: "RAISESSATISFIES", val: "raises-satisfies", parenIsForExp: true},
145
+ {name: "RAISESVIOLATES", val: "raises-violates", parenIsForExp: true},
146
+ {name: "REACTOR", val: "reactor"},
147
+ {name: "REC", val: "rec"},
148
+ {name: "REF", val: "ref"},
149
+ {name: "SANITIZE", val: "sanitize"},
150
+ {name: "SATISFIES", val: "satisfies", parenIsForExp: true},
151
+ {name: "TABLE-SELECT", val: "select"},
152
+ {name: "SHADOW", val: "shadow"},
153
+ {name: "TABLE-FILTER", val: "sieve"},
154
+ {name: "SPY", val: "spy"},
155
+ {name: "TABLE-ORDER", val: "order"},
156
+ {name: "TABLE-UPDATE", val: "transform"},
157
+ {name: "TRUE", val: "true"},
158
+ {name: "TYPE", val: "type"},
159
+ {name: "TYPE-LET", val: "type-let"},
160
+ {name: "USING", val: "using"},
161
+ {name: "USE", val: "use"},
162
+ {name: "VAR", val: "var"},
163
+ {name: "SATISFIESNOT", val: "violates", parenIsForExp: true},
164
+ {name: "WHEN", val: "when", parenIsForExp: true}
165
+ ]);
166
+ const keywordsNoFollow = new Set("-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890");
167
+
168
+ const wsString = " \f\n\r\t\v\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff";
169
+ const whitespace = makeDict(wsString);
170
+
171
+ const wsMustFollow = new Set(wsString); wsMustFollow.add("#"); wsMustFollow.add(undefined); // EOF
172
+
173
+ //const identChars = new RegExp("[_a-zA-Z][_a-zA-Z0-9]*(?:-+[_a-zA-Z0-9]+)*", "g");
174
+ const identChars = makeDict("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
175
+
176
+
177
+ // const unsigned_decimal_part = "[0-9]+(?:\\.[0-9]+)?(?:[eE][-+]?[0-9]+)?";
178
+ // const unsigned_rational_part = "[0-9]+/[0-9]+";
179
+
180
+ // const number = new RegExp("[-+]?" + unsigned_decimal_part, "g");
181
+
182
+ const badNumber = new RegExp("~?[+-]?\\.[0-9]+(?:[eE][-+]?[0-9]+)?", "g");
183
+
184
+ // const roughnum = new RegExp("~[-+]?" + unsigned_decimal_part, "g");
185
+
186
+ // const rational = new RegExp("[-+]?" + unsigned_rational_part, "g");
187
+
188
+ // const roughrational = new RegExp("~[-+]?" + unsigned_rational_part, "g");
189
+
190
+ const badOp = new RegExp("(?:\\^|\\+|-|\\*|/|<=|>=|<=>|>=|==|=~|<>|<|>|<-)", "g");
191
+
192
+ const tquot_str =
193
+ new RegExp("```(?:" +
194
+ "\\\\[01234567]{1,3}" +
195
+ "|\\\\x[0-9a-fA-F]{1,2}" +
196
+ "|\\\\u[0-9a-fA-F]{1,4}" +
197
+ "|\\\\[\\\\nrt\"\'`]" +
198
+ "|`{1,2}(?!`)" +
199
+ "|[^`\\\\])*```", "g"); // NOTE: Allow unescaped newlines
200
+ const dquot_str =
201
+ new RegExp("\"(?:" +
202
+ "\\\\[01234567]{1,3}" +
203
+ "|\\\\x[0-9a-fA-F]{1,2}" +
204
+ "|\\\\u[0-9a-fA-F]{1,4}" +
205
+ "|\\\\[\\\\nrt\"\']" +
206
+ "|[^\\\\\"\n\r])*\"", "g");
207
+ const squot_str =
208
+ new RegExp("\'(?:" +
209
+ "\\\\[01234567]{1,3}" +
210
+ "|\\\\x[0-9a-fA-F]{1,2}" +
211
+ "|\\\\u[0-9a-fA-F]{1,4}" +
212
+ "|\\\\[\\\\nrt\"\']" +
213
+ "|[^\\\\\'\n\r])*\'", "g");
214
+
215
+ const unterminated_string = new RegExp("(?:[\"\']|```).*", "g");
216
+ const octit = makeDict("01234567");
217
+ const digit = makeDict("0123456789");
218
+ const hexit = makeDict("0123456789abcdefABCDEF");
219
+
220
+ var symbols = makeTrie([
221
+ {name: "BLOCK", val: "block:", parenIsForExp: true},
222
+ {name: "CHECKCOLON", val: "check:", parenIsForExp: true},
223
+ {name: "DOC", val: "doc:", parenIsForExp: true},
224
+ {name: "ELSECOLON", val: "else:", parenIsForExp: true},
225
+ {name: "EXAMPLESCOLON", val: "examples:", parenIsForExp: true},
226
+ {name: "OTHERWISECOLON", val: "otherwise:", parenIsForExp: true},
227
+ {name: "PROVIDECOLON", val: "provide:", parenIsForExp: true},
228
+ {name: "ROW", val: "row:"},
229
+ {name: "SHARING", val: "sharing:", parenIsForExp: true},
230
+ {name: "SOURCECOLON", val: "source:"},
231
+ {name: "TABLE", val: "table:"},
232
+ {name: "THENCOLON", val: "then:", parenIsForExp: true},
233
+ {name: "WHERE", val: "where:", parenIsForExp: true},
234
+ {name: "WITH", val: "with:", parenIsForExp: true},
235
+ {name: "LBRACK", val: "[", parenIsForExp: true},
236
+ {name: "RBRACK", val: "]"},
237
+ {name: "LBRACE", val: "{", parenIsForExp: "PARENAFTERBRACE"},
238
+ {name: "RBRACE", val: "}"},
239
+ { name: "LPAREN", val: "(", parenIsForExp: true,
240
+ process: function processLParen(tok_spec) {
241
+ var tok_type = this.parenIsForExp || "PARENNOSPACE";
242
+ if (this.priorWhitespace)
243
+ tok_type = "PARENSPACE";
244
+ var line = this.curLine, col = this.curCol, pos = this.pos;
245
+ this.curCol++;
246
+ this.pos++;
247
+ return this.makeToken(tok_type, "(",
248
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
249
+ tok_spec);
250
+ }},
251
+ {name: "RPAREN", val: ")"},
252
+ {name: "SEMI", val: ";"},
253
+ {name: "BACKSLASH", val: "\\"},
254
+ {name: "DOTDOTDOT", val: "..."},
255
+ {name: "DOT", val: ".", noFollow: new Set("1234567890")},
256
+ {name: "BANG", val: "!"},
257
+ {name: "PERCENT", val: "%"},
258
+ {name: "COMMA", val: ",", parenIsForExp: true},
259
+ {name: "THINARROW", val: "->"},
260
+ {name: "COLONEQUALS", val: ":=", parenIsForExp: true},
261
+ {name: "COLON", val: ":", parenIsForExp: true},
262
+ {name: "BAR", val: "|", parenIsForExp: true},
263
+ {name: "EQUALS", val: "=", noFollow: new Set("~"), parenIsForExp: true},
264
+ {name: "LANGLE", val: "<", noFollow: new Set(">=")},
265
+ {name: "STAR", val: "*", noFollow: new Set(wsString), needsWs: true, parenIsForExp: true},
266
+ {name: "RANGLE", val: ">", noFollow: new Set("=")},
267
+ { name: "NUMBER", val: "", firsts: new Set("~-+1234567890"),
268
+ process: function tokenizeNumber(tok_spec) {
269
+ var match = undefined;
270
+ var line = this.curLine, col = this.curCol, pos = this.pos;
271
+ var tok_type = "";
272
+ var rough = false;
273
+ if (this.str[this.pos] === "~") {
274
+ rough = true;
275
+ this.pos++; this.curCol++;
276
+ }
277
+ if (this.str[this.pos] === "-" || this.str[this.pos] === "+") {
278
+ this.pos++; this.curCol++;
279
+ }
280
+ if (this.str[this.pos] === ".") { // BAD-NUMBER
281
+ this.pos = pos; this.curCol = col;
282
+ return undefined;
283
+ }
284
+ if (digit[this.str[this.pos]]) {
285
+ // Integer portion, or numerator
286
+ this.pos++; this.curCol++;
287
+ while (digit[this.str[this.pos]]) {
288
+ this.pos++; this.curCol++;
289
+ }
290
+ if (this.str[this.pos] === "/") { // fraction
291
+ this.pos++; this.curCol++;
292
+ if (digit[this.str[this.pos]]) {
293
+ this.pos++; this.curCol++;
294
+ while (digit[this.str[this.pos]]) {
295
+ this.pos++; this.curCol++;
296
+ }
297
+ this.parenIsForExp = false;
298
+ this.priorWhitespace = false;
299
+ return this.makeToken(rough ? "ROUGHRATIONAL" : "RATIONAL", this.str.slice(pos, this.pos),
300
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
301
+ tok_spec);
302
+ } else {
303
+ this.pos = pos; this.curCol = col;
304
+ return undefined;
305
+ }
306
+ }
307
+ if (this.str[this.pos] === ".") {
308
+ this.pos++; this.curCol++;
309
+ // decimal portion
310
+ if (digit[this.str[this.pos]]) {
311
+ this.pos++; this.curCol++;
312
+ while (digit[this.str[this.pos]]) {
313
+ this.pos++; this.curCol++;
314
+ }
315
+ } else {
316
+ this.pos--; this.curCol--;
317
+ this.parenIsForExp = false;
318
+ this.priorWhitespace = false;
319
+ return this.makeToken("NUMBER", this.str.slice(pos, this.pos),
320
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
321
+ tok_spec);
322
+ }
323
+ }
324
+ if (this.str[this.pos] === "e" || this.str[this.pos] === "E") {
325
+ var advance = this.pos + 1;
326
+ if (this.str[advance] === "+" || this.str[advance] === "-") {
327
+ advance++;
328
+ }
329
+ if (digit[this.str[advance]]) {
330
+ advance++;
331
+ while (digit[this.str[advance]]) {
332
+ advance++;
333
+ }
334
+ this.curCol += (advance - this.pos);
335
+ this.pos = advance;
336
+ this.parenIsForExp = false;
337
+ this.priorWhitespace = false;
338
+ return this.makeToken("NUMBER", this.str.slice(pos, this.pos),
339
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
340
+ tok_spec);
341
+ }
342
+ }
343
+ this.parenIsForExp = false;
344
+ this.priorWhitespace = false;
345
+ return this.makeToken("NUMBER", this.str.slice(pos, this.pos),
346
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
347
+ tok_spec);
348
+ }
349
+ // BAD-NUMBER
350
+ this.pos = pos; this.curCol = col;
351
+ return undefined;
352
+ }
353
+
354
+ /*function tokenizeNumber(tok_spec) {
355
+ var match = undefined;
356
+ var line = this.curLine, col = this.curCol, pos = this.pos;
357
+ var tok_type = "";
358
+ number.lastIndex = this.pos;
359
+ roughnum.lastIndex = this.pos;
360
+ rational.lastIndex = this.pos;
361
+ roughrational.lastIndex = this.pos;
362
+ var rough = (this.str[this.pos] === "~")
363
+ if (rough) {
364
+ if ((this.str[this.pos + 1] === ".") ||
365
+ ((this.str[this.pos + 1] === "-" || this.str[this.pos + 1] === "+") && this.str[this.pos + 2] === ".")) {
366
+ return undefined;
367
+ } else if ((match = roughrational.exec(this.str)) && match.index === this.pos) {
368
+ tok_type = "ROUGHRATIONAL";
369
+ } else if ((match = rational.exec(this.str)) && match.index === this.pos) {
370
+ tok_type = "RATIONAL";
371
+ }
372
+ } else if ((match = roughnum.exec(this.str)) && match.index === this.pos) {
373
+ tok_type = "NUMBER";
374
+ } else if ((match = number.exec(this.str)) && match.index === this.pos) {
375
+ tok_type = "NUMBER";
376
+ } else {
377
+ return undefined;
378
+ }
379
+ this.pos += match[0].length;
380
+ this.curCol += match[0].length;
381
+ return this.makeToken(tok_type, match[0],
382
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
383
+ tok_spec);
384
+ }*/
385
+ },
386
+ { name: "BAD-NUMBER", val: "", firsts: new Set("~-+."),
387
+ process: function tokenizeNumber(tok_spec) {
388
+ var match = undefined;
389
+ var line = this.curLine, col = this.curCol, pos = this.pos;
390
+ var tok_type = "";
391
+ badNumber.lastIndex = this.pos;
392
+ if ((match = badNumber.exec(this.str))) {
393
+ tok_type = "BAD-NUMBER";
394
+ } else {
395
+ return undefined;
396
+ }
397
+ this.pos += match[0].length;
398
+ this.curCol += match[0].length;
399
+ return this.makeToken(tok_type, match[0],
400
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
401
+ tok_spec);
402
+ }},
403
+ { name: "NAME", val: "", firsts: new Set("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
404
+ process: function tokenizeName(tok_spec) {
405
+ var line = this.curLine, col = this.curCol, pos = this.pos;
406
+ this.pos++; this.curCol++;
407
+ while (this.pos < this.len) {
408
+ if (identChars[this.str[this.pos]]) {
409
+ this.pos++; this.curCol++;
410
+ } else if (this.str[this.pos] === "-") {
411
+ var front = this.pos + 1;
412
+ while (this.str[front] === "-")
413
+ front++;
414
+ if (identChars[this.str[front]]) {
415
+ this.curCol += (front - this.pos);
416
+ this.pos = front;
417
+ } else {
418
+ break;
419
+ }
420
+ } else {
421
+ break;
422
+ }
423
+ }
424
+ return this.makeToken("NAME", this.str.slice(pos, this.pos),
425
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
426
+ tok_spec);
427
+ }},
428
+ { name: "STRING", val: "\"",
429
+ process: function tokenizeDQString(tok_spec) {
430
+ var line = this.curLine, col = this.curCol, pos = this.pos;
431
+ dquot_str.lastIndex = this.pos;
432
+ unterminated_string.lastIndex = this.pos;
433
+ if ((match = dquot_str.exec(this.str))) {
434
+ this.pos += match[0].length;
435
+ this.curCol += match[0].length;
436
+ return this.makeToken("STRING", fixEscapes(this.str.slice(pos, this.pos)),
437
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
438
+ tok_spec);
439
+ } else if ((match = unterminated_string.exec(this.str))) {
440
+ this.pos += match[0].length;
441
+ this.curCol += match[0].length;
442
+ return this.makeToken("UNTERMINATED-STRING", this.str.slice(pos, this.pos), // no escaping
443
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
444
+ tok_spec);
445
+ }
446
+ }},
447
+ { name: "STRING", val: "'",
448
+ process: function tokenizeSQString(tok_spec) {
449
+ var line = this.curLine, col = this.curCol, pos = this.pos;
450
+ squot_str.lastIndex = this.pos;
451
+ unterminated_string.lastIndex = this.pos;
452
+ if ((match = squot_str.exec(this.str))) {
453
+ this.pos += match[0].length;
454
+ this.curCol += match[0].length;
455
+ return this.makeToken("STRING", fixEscapes(this.str.slice(pos, this.pos)),
456
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos));
457
+ } else if ((match = unterminated_string.exec(this.str))) {
458
+ this.pos += match[0].length;
459
+ this.curCol += match[0].length;
460
+ return this.makeToken("UNTERMINATED-STRING", this.str.slice(pos, this.pos), // no escaping
461
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
462
+ tok_spec);
463
+ }
464
+ }},
465
+ { name: "STRING", val: "```",
466
+ process: function tokenizeTQString(tok_spec) {
467
+ var line = this.curLine, col = this.curCol, pos = this.pos;
468
+ tquot_str.lastIndex = this.pos;
469
+ unterminated_string.lastIndex = this.pos;
470
+ if ((match = tquot_str.exec(this.str))) {
471
+ this.pos += match[0].length;
472
+ var lines = match[0].split("\n"); // From jsPerf, this is UNBELIEVABLY much faster than the prior implementation
473
+ this.curLine += lines.length - 1;
474
+ if (lines.length === 1)
475
+ this.curCol += match[0].length;
476
+ else
477
+ this.curCol = lines[lines.length - 1].length;
478
+ return this.makeToken("STRING", fixEscapes(this.str.slice(pos, this.pos)),
479
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
480
+ tok_spec);
481
+ } else if ((match = unterminated_string.exec(this.str))) {
482
+ this.pos += match[0].length;
483
+ this.curCol += match[0].length;
484
+ return this.makeToken("UNTERMINATED-STRING", this.str.slice(pos, this.pos), // no escaping
485
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
486
+ tok_spec);
487
+ }
488
+ }},
489
+ {name: "CARET", val: "^", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
490
+ {name: "PLUS", val: "+", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
491
+ {name: "DASH", val: "-", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
492
+ {name: "TIMES", val: "*", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
493
+ {name: "SLASH", val: "/", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
494
+ {name: "SPACESHIP", val: "<=>", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
495
+ {name: "LEQ", val: "<=", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
496
+ {name: "GEQ", val: ">=", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
497
+ {name: "EQUALEQUAL", val: "==", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
498
+ {name: "EQUALTILDE", val: "=~", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
499
+ {name: "NEQ", val: "<>", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
500
+ {name: "LT", val: "<", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
501
+ {name: "GT", val: ">", mustFollow: wsMustFollow, needsWs: true, parenIsForExp: true},
502
+ {name: "THICKARROW", val: "=>", mustFollow: wsMustFollow, parenIsForExp: true},
503
+ {name: "COLONCOLON", val: "::", mustFollow: wsMustFollow, parenIsForExp: true},
504
+ { name: "BAD-OPER", val: "", firsts: new Set("^+-*/\<>="),
505
+ process: function tokenizeBadOper(tok_spec) {
506
+ var line = this.curLine, col = this.curCol, pos = this.pos;
507
+ badOp.lastIndex = this.pos;
508
+ var match;
509
+ if ((match = badOp.exec(this.str))) {
510
+ this.pos += match[0].length;
511
+ this.curCol += match[0].length;
512
+ this.parenIsForExp = false;
513
+ this.priorWhitespace = false;
514
+ return this.makeToken("BAD-OPER", this.str.slice(pos, this.pos),
515
+ SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos),
516
+ tok_spec);
517
+ } else {
518
+ return undefined;
519
+ }
520
+ }}
521
+ ]);
522
+
523
+
524
+ const comments = makeTrie([
525
+ { name: "BLOCKCOMMENT", val: "#|",
526
+ process: function tokenizeBlockComment(tok_spec) {
527
+ var nestingDepth = 1;
528
+ var line = this.curLine, col = this.curCol, pos = this.pos;
529
+ this.pos += 2; this.curCol += 2;
530
+ while (nestingDepth > 0 && this.pos < this.len) {
531
+ if (this.str.startsWith("#|", this.pos)) {
532
+ nestingDepth++;
533
+ this.pos += 2;
534
+ this.curCol += 2;
535
+ } else if (this.str.startsWith("|#", this.pos)) {
536
+ nestingDepth--;
537
+ this.pos += 2;
538
+ this.curCol += 2;
539
+ } else if (this.str[this.pos] === "\n") {
540
+ this.curLine++;
541
+ this.curCol = 0;
542
+ this.pos++;
543
+ } else {
544
+ this.pos++;
545
+ this.curCol++;
546
+ }
547
+ }
548
+ if (nestingDepth === 0) {
549
+ return this.makeWSToken(line, col, pos);
550
+ } else {
551
+ var ws_loc = SrcLoc.make(line, col, pos, this.curLine, this.curCol, this.pos);
552
+ return this.makeToken("UNTERMINATED-BLOCK-COMMENT", this.str.slice(pos, this.pos), ws_loc, tok_spec);
553
+ }
554
+ }},
555
+ { name: "COMMENT", val: "#",
556
+ process: function tokenizeLineComment(tok_spec) {
557
+ var line = this.curLine, col = this.curCol, pos = this.pos;
558
+ while (this.pos < this.len && this.str[this.pos] !== "\n" && this.str[this.pos] !== "\r") {
559
+ this.pos++;
560
+ this.curCol++;
561
+ }
562
+ return this.makeToken("COMMENT", ""/*this.str.slice(pos, this.pos)*/, line, col, pos);
563
+ }}
564
+ ]);
565
+
566
+ const spec = {
567
+ keywords,
568
+ keywordsNoFollow,
569
+ symbols,
570
+ whitespace,
571
+ comments,
572
+ ignore: new Set(["WS", "COMMENT"])
573
+ };
574
+
575
+
576
+ return {
577
+ 'Tokenizer': new Tokenizer(spec)
578
+ };
579
+ });