source: imaps-frontend/node_modules/es-module-lexer/lexer.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 25.7 KB
Line 
1let source, pos, end,
2 openTokenDepth,
3 lastTokenPos,
4 openTokenPosStack,
5 openClassPosStack,
6 curDynamicImport,
7 templateStackDepth,
8 facade,
9 lastSlashWasDivision,
10 nextBraceIsClass,
11 templateDepth,
12 templateStack,
13 imports,
14 exports,
15 name;
16
17function addImport (ss, s, e, d) {
18 const impt = { ss, se: d === -2 ? e : d === -1 ? e + 1 : 0, s, e, d, a: -1, n: undefined };
19 imports.push(impt);
20 return impt;
21}
22
23function addExport (s, e, ls, le) {
24 exports.push({
25 s,
26 e,
27 ls,
28 le,
29 n: s[0] === '"' ? readString(s, '"') : s[0] === "'" ? readString(s, "'") : source.slice(s, e),
30 ln: ls[0] === '"' ? readString(ls, '"') : ls[0] === "'" ? readString(ls, "'") : source.slice(ls, le)
31 });
32}
33
34function readName (impt) {
35 let { d, s } = impt;
36 if (d !== -1)
37 s++;
38 impt.n = readString(s, source.charCodeAt(s - 1));
39}
40
41// Note: parsing is based on the _assumption_ that the source is already valid
42export function parse (_source, _name) {
43 openTokenDepth = 0;
44 curDynamicImport = null;
45 templateDepth = -1;
46 lastTokenPos = -1;
47 lastSlashWasDivision = false;
48 templateStack = Array(1024);
49 templateStackDepth = 0;
50 openTokenPosStack = Array(1024);
51 openClassPosStack = Array(1024);
52 nextBraceIsClass = false;
53 facade = true;
54 name = _name || '@';
55
56 imports = [];
57 exports = [];
58
59 source = _source;
60 pos = -1;
61 end = source.length - 1;
62 let ch = 0;
63
64 // start with a pure "module-only" parser
65 m: while (pos++ < end) {
66 ch = source.charCodeAt(pos);
67
68 if (ch === 32 || ch < 14 && ch > 8)
69 continue;
70
71 switch (ch) {
72 case 101/*e*/:
73 if (openTokenDepth === 0 && keywordStart(pos) && source.startsWith('xport', pos + 1)) {
74 tryParseExportStatement();
75 // export might have been a non-pure declaration
76 if (!facade) {
77 lastTokenPos = pos;
78 break m;
79 }
80 }
81 break;
82 case 105/*i*/:
83 if (keywordStart(pos) && source.startsWith('mport', pos + 1))
84 tryParseImportStatement();
85 break;
86 case 59/*;*/:
87 break;
88 case 47/*/*/: {
89 const next_ch = source.charCodeAt(pos + 1);
90 if (next_ch === 47/*/*/) {
91 lineComment();
92 // dont update lastToken
93 continue;
94 }
95 else if (next_ch === 42/***/) {
96 blockComment(true);
97 // dont update lastToken
98 continue;
99 }
100 // fallthrough
101 }
102 default:
103 // as soon as we hit a non-module token, we go to main parser
104 facade = false;
105 pos--;
106 break m;
107 }
108 lastTokenPos = pos;
109 }
110
111 while (pos++ < end) {
112 ch = source.charCodeAt(pos);
113
114 if (ch === 32 || ch < 14 && ch > 8)
115 continue;
116
117 switch (ch) {
118 case 101/*e*/:
119 if (openTokenDepth === 0 && keywordStart(pos) && source.startsWith('xport', pos + 1))
120 tryParseExportStatement();
121 break;
122 case 105/*i*/:
123 if (keywordStart(pos) && source.startsWith('mport', pos + 1))
124 tryParseImportStatement();
125 break;
126 case 99/*c*/:
127 if (keywordStart(pos) && source.startsWith('lass', pos + 1) && isBrOrWs(source.charCodeAt(pos + 5)))
128 nextBraceIsClass = true;
129 break;
130 case 40/*(*/:
131 openTokenPosStack[openTokenDepth++] = lastTokenPos;
132 break;
133 case 41/*)*/:
134 if (openTokenDepth === 0)
135 syntaxError();
136 openTokenDepth--;
137 if (curDynamicImport && curDynamicImport.d === openTokenPosStack[openTokenDepth]) {
138 if (curDynamicImport.e === 0)
139 curDynamicImport.e = pos;
140 curDynamicImport.se = pos;
141 curDynamicImport = null;
142 }
143 break;
144 case 123/*{*/:
145 // dynamic import followed by { is not a dynamic import (so remove)
146 // this is a sneaky way to get around { import () {} } v { import () }
147 // block / object ambiguity without a parser (assuming source is valid)
148 if (source.charCodeAt(lastTokenPos) === 41/*)*/ && imports.length && imports[imports.length - 1].e === lastTokenPos) {
149 imports.pop();
150 }
151 openClassPosStack[openTokenDepth] = nextBraceIsClass;
152 nextBraceIsClass = false;
153 openTokenPosStack[openTokenDepth++] = lastTokenPos;
154 break;
155 case 125/*}*/:
156 if (openTokenDepth === 0)
157 syntaxError();
158 if (openTokenDepth-- === templateDepth) {
159 templateDepth = templateStack[--templateStackDepth];
160 templateString();
161 }
162 else {
163 if (templateDepth !== -1 && openTokenDepth < templateDepth)
164 syntaxError();
165 }
166 break;
167 case 39/*'*/:
168 case 34/*"*/:
169 stringLiteral(ch);
170 break;
171 case 47/*/*/: {
172 const next_ch = source.charCodeAt(pos + 1);
173 if (next_ch === 47/*/*/) {
174 lineComment();
175 // dont update lastToken
176 continue;
177 }
178 else if (next_ch === 42/***/) {
179 blockComment(true);
180 // dont update lastToken
181 continue;
182 }
183 else {
184 // Division / regex ambiguity handling based on checking backtrack analysis of:
185 // - what token came previously (lastToken)
186 // - if a closing brace or paren, what token came before the corresponding
187 // opening brace or paren (lastOpenTokenIndex)
188 const lastToken = source.charCodeAt(lastTokenPos);
189 const lastExport = exports[exports.length - 1];
190 if (isExpressionPunctuator(lastToken) &&
191 !(lastToken === 46/*.*/ && (source.charCodeAt(lastTokenPos - 1) >= 48/*0*/ && source.charCodeAt(lastTokenPos - 1) <= 57/*9*/)) &&
192 !(lastToken === 43/*+*/ && source.charCodeAt(lastTokenPos - 1) === 43/*+*/) && !(lastToken === 45/*-*/ && source.charCodeAt(lastTokenPos - 1) === 45/*-*/) ||
193 lastToken === 41/*)*/ && isParenKeyword(openTokenPosStack[openTokenDepth]) ||
194 lastToken === 125/*}*/ && (isExpressionTerminator(openTokenPosStack[openTokenDepth]) || openClassPosStack[openTokenDepth]) ||
195 lastToken === 47/*/*/ && lastSlashWasDivision ||
196 isExpressionKeyword(lastTokenPos) ||
197 !lastToken) {
198 regularExpression();
199 lastSlashWasDivision = false;
200 }
201 else if (lastExport && lastTokenPos >= lastExport.s && lastTokenPos <= lastExport.e) {
202 // export default /some-regexp/
203 regularExpression();
204 lastSlashWasDivision = false;
205 }
206 else {
207 lastSlashWasDivision = true;
208 }
209 }
210 break;
211 }
212 case 96/*`*/:
213 templateString();
214 break;
215 }
216 lastTokenPos = pos;
217 }
218
219 if (templateDepth !== -1 || openTokenDepth)
220 syntaxError();
221
222 return [imports, exports, facade];
223}
224
225function tryParseImportStatement () {
226 const startPos = pos;
227
228 pos += 6;
229
230 let ch = commentWhitespace(true);
231
232 switch (ch) {
233 // dynamic import
234 case 40/*(*/:
235 openTokenPosStack[openTokenDepth++] = startPos;
236 if (source.charCodeAt(lastTokenPos) === 46/*.*/)
237 return;
238 // dynamic import indicated by positive d
239 const impt = addImport(startPos, pos + 1, 0, startPos);
240 curDynamicImport = impt;
241 // try parse a string, to record a safe dynamic import string
242 pos++;
243 ch = commentWhitespace(true);
244 if (ch === 39/*'*/ || ch === 34/*"*/) {
245 stringLiteral(ch);
246 }
247 else {
248 pos--;
249 return;
250 }
251 pos++;
252 ch = commentWhitespace(true);
253 if (ch === 44/*,*/) {
254 impt.e = pos;
255 pos++;
256 ch = commentWhitespace(true);
257 impt.a = pos;
258 readName(impt);
259 pos--;
260 }
261 else if (ch === 41/*)*/) {
262 openTokenDepth--;
263 impt.e = pos;
264 impt.se = pos;
265 readName(impt);
266 }
267 else {
268 pos--;
269 }
270 return;
271 // import.meta
272 case 46/*.*/:
273 pos++;
274 ch = commentWhitespace(true);
275 // import.meta indicated by d === -2
276 if (ch === 109/*m*/ && source.startsWith('eta', pos + 1) && source.charCodeAt(lastTokenPos) !== 46/*.*/)
277 addImport(startPos, startPos, pos + 4, -2);
278 return;
279
280 default:
281 // no space after "import" -> not an import keyword
282 if (pos === startPos + 6)
283 break;
284 case 34/*"*/:
285 case 39/*'*/:
286 case 123/*{*/:
287 case 42/***/:
288 // import statement only permitted at base-level
289 if (openTokenDepth !== 0) {
290 pos--;
291 return;
292 }
293 while (pos < end) {
294 ch = source.charCodeAt(pos);
295 if (ch === 39/*'*/ || ch === 34/*"*/) {
296 readImportString(startPos, ch);
297 return;
298 }
299 pos++;
300 }
301 syntaxError();
302 }
303}
304
305function tryParseExportStatement () {
306 const sStartPos = pos;
307 const prevExport = exports.length;
308
309 pos += 6;
310
311 const curPos = pos;
312
313 let ch = commentWhitespace(true);
314
315 if (pos === curPos && !isPunctuator(ch))
316 return;
317
318 switch (ch) {
319 // export default ...
320 case 100/*d*/:
321 addExport(pos, pos + 7, -1, -1);
322 return;
323
324 // export async? function*? name () {
325 case 97/*a*/:
326 pos += 5;
327 commentWhitespace(true);
328 // fallthrough
329 case 102/*f*/:
330 pos += 8;
331 ch = commentWhitespace(true);
332 if (ch === 42/***/) {
333 pos++;
334 ch = commentWhitespace(true);
335 }
336 const startPos = pos;
337 ch = readToWsOrPunctuator(ch);
338 addExport(startPos, pos, startPos, pos);
339 pos--;
340 return;
341
342 // export class name ...
343 case 99/*c*/:
344 if (source.startsWith('lass', pos + 1) && isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos + 5))) {
345 pos += 5;
346 ch = commentWhitespace(true);
347 const startPos = pos;
348 ch = readToWsOrPunctuator(ch);
349 addExport(startPos, pos, startPos, pos);
350 pos--;
351 return;
352 }
353 pos += 2;
354 // fallthrough
355
356 // export var/let/const name = ...(, name = ...)+
357 case 118/*v*/:
358 case 109/*l*/:
359 // destructured initializations not currently supported (skipped for { or [)
360 // also, lexing names after variable equals is skipped (export var p = function () { ... }, q = 5 skips "q")
361 pos += 2;
362 facade = false;
363 do {
364 pos++;
365 ch = commentWhitespace(true);
366 const startPos = pos;
367 ch = readToWsOrPunctuator(ch);
368 // dont yet handle [ { destructurings
369 if (ch === 123/*{*/ || ch === 91/*[*/) {
370 pos--;
371 return;
372 }
373 if (pos === startPos)
374 return;
375 addExport(startPos, pos, startPos, pos);
376 ch = commentWhitespace(true);
377 if (ch === 61/*=*/) {
378 pos--;
379 return;
380 }
381 } while (ch === 44/*,*/);
382 pos--;
383 return;
384
385
386 // export {...}
387 case 123/*{*/:
388 pos++;
389 ch = commentWhitespace(true);
390 while (true) {
391 const startPos = pos;
392 readToWsOrPunctuator(ch);
393 const endPos = pos;
394 commentWhitespace(true);
395 ch = readExportAs(startPos, endPos);
396 // ,
397 if (ch === 44/*,*/) {
398 pos++;
399 ch = commentWhitespace(true);
400 }
401 if (ch === 125/*}*/)
402 break;
403 if (pos === startPos)
404 return syntaxError();
405 if (pos > end)
406 return syntaxError();
407 }
408 pos++;
409 ch = commentWhitespace(true);
410 break;
411
412 // export *
413 // export * as X
414 case 42/***/:
415 pos++;
416 commentWhitespace(true);
417 ch = readExportAs(pos, pos);
418 ch = commentWhitespace(true);
419 break;
420 }
421
422 // from ...
423 if (ch === 102/*f*/ && source.startsWith('rom', pos + 1)) {
424 pos += 4;
425 readImportString(sStartPos, commentWhitespace(true));
426
427 // There were no local names.
428 for (let i = prevExport; i < exports.length; ++i) {
429 exports[i].ls = exports[i].le = -1;
430 exports[i].ln = undefined;
431 }
432 }
433 else {
434 pos--;
435 }
436}
437
438/*
439 * Ported from Acorn
440 *
441 * MIT License
442
443 * Copyright (C) 2012-2020 by various contributors (see AUTHORS)
444
445 * Permission is hereby granted, free of charge, to any person obtaining a copy
446 * of this software and associated documentation files (the "Software"), to deal
447 * in the Software without restriction, including without limitation the rights
448 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
449 * copies of the Software, and to permit persons to whom the Software is
450 * furnished to do so, subject to the following conditions:
451
452 * The above copyright notice and this permission notice shall be included in
453 * all copies or substantial portions of the Software.
454
455 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
456 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
457 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
458 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
459 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
460 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
461 * THE SOFTWARE.
462 */
463let acornPos;
464function readString (start, quote) {
465 acornPos = start;
466 let out = '', chunkStart = acornPos;
467 for (;;) {
468 if (acornPos >= source.length) syntaxError();
469 const ch = source.charCodeAt(acornPos);
470 if (ch === quote) break;
471 if (ch === 92) { // '\'
472 out += source.slice(chunkStart, acornPos);
473 out += readEscapedChar();
474 chunkStart = acornPos;
475 }
476 else if (ch === 0x2028 || ch === 0x2029) {
477 ++acornPos;
478 }
479 else {
480 if (isBr(ch)) syntaxError();
481 ++acornPos;
482 }
483 }
484 out += source.slice(chunkStart, acornPos++);
485 return out;
486}
487
488// Used to read escaped characters
489
490function readEscapedChar () {
491 let ch = source.charCodeAt(++acornPos);
492 ++acornPos;
493 switch (ch) {
494 case 110: return '\n'; // 'n' -> '\n'
495 case 114: return '\r'; // 'r' -> '\r'
496 case 120: return String.fromCharCode(readHexChar(2)); // 'x'
497 case 117: return readCodePointToString(); // 'u'
498 case 116: return '\t'; // 't' -> '\t'
499 case 98: return '\b'; // 'b' -> '\b'
500 case 118: return '\u000b'; // 'v' -> '\u000b'
501 case 102: return '\f'; // 'f' -> '\f'
502 case 13: if (source.charCodeAt(acornPos) === 10) ++acornPos; // '\r\n'
503 case 10: // ' \n'
504 return '';
505 case 56:
506 case 57:
507 syntaxError();
508 default:
509 if (ch >= 48 && ch <= 55) {
510 let octalStr = source.substr(acornPos - 1, 3).match(/^[0-7]+/)[0];
511 let octal = parseInt(octalStr, 8);
512 if (octal > 255) {
513 octalStr = octalStr.slice(0, -1);
514 octal = parseInt(octalStr, 8);
515 }
516 acornPos += octalStr.length - 1;
517 ch = source.charCodeAt(acornPos);
518 if (octalStr !== '0' || ch === 56 || ch === 57)
519 syntaxError();
520 return String.fromCharCode(octal);
521 }
522 if (isBr(ch)) {
523 // Unicode new line characters after \ get removed from output in both
524 // template literals and strings
525 return '';
526 }
527 return String.fromCharCode(ch);
528 }
529}
530
531// Used to read character escape sequences ('\x', '\u', '\U').
532
533function readHexChar (len) {
534 const start = acornPos;
535 let total = 0, lastCode = 0;
536 for (let i = 0; i < len; ++i, ++acornPos) {
537 let code = source.charCodeAt(acornPos), val;
538
539 if (code === 95) {
540 if (lastCode === 95 || i === 0) syntaxError();
541 lastCode = code;
542 continue;
543 }
544
545 if (code >= 97) val = code - 97 + 10; // a
546 else if (code >= 65) val = code - 65 + 10; // A
547 else if (code >= 48 && code <= 57) val = code - 48; // 0-9
548 else break;
549 if (val >= 16) break;
550 lastCode = code;
551 total = total * 16 + val;
552 }
553
554 if (lastCode === 95 || acornPos - start !== len) syntaxError();
555
556 return total;
557}
558
559// Read a string value, interpreting backslash-escapes.
560
561function readCodePointToString () {
562 const ch = source.charCodeAt(acornPos);
563 let code;
564 if (ch === 123) { // '{'
565 ++acornPos;
566 code = readHexChar(source.indexOf('}', acornPos) - acornPos);
567 ++acornPos;
568 if (code > 0x10FFFF) syntaxError();
569 } else {
570 code = readHexChar(4);
571 }
572 // UTF-16 Decoding
573 if (code <= 0xFFFF) return String.fromCharCode(code);
574 code -= 0x10000;
575 return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00);
576}
577
578/*
579 * </ Acorn Port>
580 */
581
582function readExportAs (startPos, endPos) {
583 let ch = source.charCodeAt(pos);
584 let ls = startPos, le = endPos;
585 if (ch === 97 /*a*/) {
586 pos += 2;
587 ch = commentWhitespace(true);
588 startPos = pos;
589 readToWsOrPunctuator(ch);
590 endPos = pos;
591 ch = commentWhitespace(true);
592 }
593 if (pos !== startPos)
594 addExport(startPos, endPos, ls, le);
595 return ch;
596}
597
598function readImportString (ss, ch) {
599 const startPos = pos + 1;
600 if (ch === 39/*'*/ || ch === 34/*"*/) {
601 stringLiteral(ch);
602 }
603 else {
604 syntaxError();
605 return;
606 }
607 const impt = addImport(ss, startPos, pos, -1);
608 readName(impt);
609 pos++;
610 ch = commentWhitespace(false);
611 if (ch !== 97/*a*/ || !source.startsWith('ssert', pos + 1)) {
612 pos--;
613 return;
614 }
615 const assertIndex = pos;
616
617 pos += 6;
618 ch = commentWhitespace(true);
619 if (ch !== 123/*{*/) {
620 pos = assertIndex;
621 return;
622 }
623 const assertStart = pos;
624 do {
625 pos++;
626 ch = commentWhitespace(true);
627 if (ch === 39/*'*/ || ch === 34/*"*/) {
628 stringLiteral(ch);
629 pos++;
630 ch = commentWhitespace(true);
631 }
632 else {
633 ch = readToWsOrPunctuator(ch);
634 }
635 if (ch !== 58/*:*/) {
636 pos = assertIndex;
637 return;
638 }
639 pos++;
640 ch = commentWhitespace(true);
641 if (ch === 39/*'*/ || ch === 34/*"*/) {
642 stringLiteral(ch);
643 }
644 else {
645 pos = assertIndex;
646 return;
647 }
648 pos++;
649 ch = commentWhitespace(true);
650 if (ch === 44/*,*/) {
651 pos++;
652 ch = commentWhitespace(true);
653 if (ch === 125/*}*/)
654 break;
655 continue;
656 }
657 if (ch === 125/*}*/)
658 break;
659 pos = assertIndex;
660 return;
661 } while (true);
662 impt.a = assertStart;
663 impt.se = pos + 1;
664}
665
666function commentWhitespace (br) {
667 let ch;
668 do {
669 ch = source.charCodeAt(pos);
670 if (ch === 47/*/*/) {
671 const next_ch = source.charCodeAt(pos + 1);
672 if (next_ch === 47/*/*/)
673 lineComment();
674 else if (next_ch === 42/***/)
675 blockComment(br);
676 else
677 return ch;
678 }
679 else if (br ? !isBrOrWs(ch): !isWsNotBr(ch)) {
680 return ch;
681 }
682 } while (pos++ < end);
683 return ch;
684}
685
686function templateString () {
687 while (pos++ < end) {
688 const ch = source.charCodeAt(pos);
689 if (ch === 36/*$*/ && source.charCodeAt(pos + 1) === 123/*{*/) {
690 pos++;
691 templateStack[templateStackDepth++] = templateDepth;
692 templateDepth = ++openTokenDepth;
693 return;
694 }
695 if (ch === 96/*`*/)
696 return;
697 if (ch === 92/*\*/)
698 pos++;
699 }
700 syntaxError();
701}
702
703function blockComment (br) {
704 pos++;
705 while (pos++ < end) {
706 const ch = source.charCodeAt(pos);
707 if (!br && isBr(ch))
708 return;
709 if (ch === 42/***/ && source.charCodeAt(pos + 1) === 47/*/*/) {
710 pos++;
711 return;
712 }
713 }
714}
715
716function lineComment () {
717 while (pos++ < end) {
718 const ch = source.charCodeAt(pos);
719 if (ch === 10/*\n*/ || ch === 13/*\r*/)
720 return;
721 }
722}
723
724function stringLiteral (quote) {
725 while (pos++ < end) {
726 let ch = source.charCodeAt(pos);
727 if (ch === quote)
728 return;
729 if (ch === 92/*\*/) {
730 ch = source.charCodeAt(++pos);
731 if (ch === 13/*\r*/ && source.charCodeAt(pos + 1) === 10/*\n*/)
732 pos++;
733 }
734 else if (isBr(ch))
735 break;
736 }
737 syntaxError();
738}
739
740function regexCharacterClass () {
741 while (pos++ < end) {
742 let ch = source.charCodeAt(pos);
743 if (ch === 93/*]*/)
744 return ch;
745 if (ch === 92/*\*/)
746 pos++;
747 else if (ch === 10/*\n*/ || ch === 13/*\r*/)
748 break;
749 }
750 syntaxError();
751}
752
753function regularExpression () {
754 while (pos++ < end) {
755 let ch = source.charCodeAt(pos);
756 if (ch === 47/*/*/)
757 return;
758 if (ch === 91/*[*/)
759 ch = regexCharacterClass();
760 else if (ch === 92/*\*/)
761 pos++;
762 else if (ch === 10/*\n*/ || ch === 13/*\r*/)
763 break;
764 }
765 syntaxError();
766}
767
768function readToWsOrPunctuator (ch) {
769 do {
770 if (isBrOrWs(ch) || isPunctuator(ch))
771 return ch;
772 } while (ch = source.charCodeAt(++pos));
773 return ch;
774}
775
776// Note: non-asii BR and whitespace checks omitted for perf / footprint
777// if there is a significant user need this can be reconsidered
778function isBr (c) {
779 return c === 13/*\r*/ || c === 10/*\n*/;
780}
781
782function isWsNotBr (c) {
783 return c === 9 || c === 11 || c === 12 || c === 32 || c === 160;
784}
785
786function isBrOrWs (c) {
787 return c > 8 && c < 14 || c === 32 || c === 160;
788}
789
790function isBrOrWsOrPunctuatorNotDot (c) {
791 return c > 8 && c < 14 || c === 32 || c === 160 || isPunctuator(c) && c !== 46/*.*/;
792}
793
794function keywordStart (pos) {
795 return pos === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos - 1));
796}
797
798function readPrecedingKeyword (pos, match) {
799 if (pos < match.length - 1)
800 return false;
801 return source.startsWith(match, pos - match.length + 1) && (pos === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos - match.length)));
802}
803
804function readPrecedingKeyword1 (pos, ch) {
805 return source.charCodeAt(pos) === ch && (pos === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos - 1)));
806}
807
808// Detects one of case, debugger, delete, do, else, in, instanceof, new,
809// return, throw, typeof, void, yield, await
810function isExpressionKeyword (pos) {
811 switch (source.charCodeAt(pos)) {
812 case 100/*d*/:
813 switch (source.charCodeAt(pos - 1)) {
814 case 105/*i*/:
815 // void
816 return readPrecedingKeyword(pos - 2, 'vo');
817 case 108/*l*/:
818 // yield
819 return readPrecedingKeyword(pos - 2, 'yie');
820 default:
821 return false;
822 }
823 case 101/*e*/:
824 switch (source.charCodeAt(pos - 1)) {
825 case 115/*s*/:
826 switch (source.charCodeAt(pos - 2)) {
827 case 108/*l*/:
828 // else
829 return readPrecedingKeyword1(pos - 3, 101/*e*/);
830 case 97/*a*/:
831 // case
832 return readPrecedingKeyword1(pos - 3, 99/*c*/);
833 default:
834 return false;
835 }
836 case 116/*t*/:
837 // delete
838 return readPrecedingKeyword(pos - 2, 'dele');
839 default:
840 return false;
841 }
842 case 102/*f*/:
843 if (source.charCodeAt(pos - 1) !== 111/*o*/ || source.charCodeAt(pos - 2) !== 101/*e*/)
844 return false;
845 switch (source.charCodeAt(pos - 3)) {
846 case 99/*c*/:
847 // instanceof
848 return readPrecedingKeyword(pos - 4, 'instan');
849 case 112/*p*/:
850 // typeof
851 return readPrecedingKeyword(pos - 4, 'ty');
852 default:
853 return false;
854 }
855 case 110/*n*/:
856 // in, return
857 return readPrecedingKeyword1(pos - 1, 105/*i*/) || readPrecedingKeyword(pos - 1, 'retur');
858 case 111/*o*/:
859 // do
860 return readPrecedingKeyword1(pos - 1, 100/*d*/);
861 case 114/*r*/:
862 // debugger
863 return readPrecedingKeyword(pos - 1, 'debugge');
864 case 116/*t*/:
865 // await
866 return readPrecedingKeyword(pos - 1, 'awai');
867 case 119/*w*/:
868 switch (source.charCodeAt(pos - 1)) {
869 case 101/*e*/:
870 // new
871 return readPrecedingKeyword1(pos - 2, 110/*n*/);
872 case 111/*o*/:
873 // throw
874 return readPrecedingKeyword(pos - 2, 'thr');
875 default:
876 return false;
877 }
878 }
879 return false;
880}
881
882function isParenKeyword (curPos) {
883 return source.charCodeAt(curPos) === 101/*e*/ && source.startsWith('whil', curPos - 4) ||
884 source.charCodeAt(curPos) === 114/*r*/ && source.startsWith('fo', curPos - 2) ||
885 source.charCodeAt(curPos - 1) === 105/*i*/ && source.charCodeAt(curPos) === 102/*f*/;
886}
887
888function isPunctuator (ch) {
889 // 23 possible punctuator endings: !%&()*+,-./:;<=>?[]^{}|~
890 return ch === 33/*!*/ || ch === 37/*%*/ || ch === 38/*&*/ ||
891 ch > 39 && ch < 48 || ch > 57 && ch < 64 ||
892 ch === 91/*[*/ || ch === 93/*]*/ || ch === 94/*^*/ ||
893 ch > 122 && ch < 127;
894}
895
896function isExpressionPunctuator (ch) {
897 // 20 possible expression endings: !%&(*+,-.:;<=>?[^{|~
898 return ch === 33/*!*/ || ch === 37/*%*/ || ch === 38/*&*/ ||
899 ch > 39 && ch < 47 && ch !== 41 || ch > 57 && ch < 64 ||
900 ch === 91/*[*/ || ch === 94/*^*/ || ch > 122 && ch < 127 && ch !== 125/*}*/;
901}
902
903function isExpressionTerminator (curPos) {
904 // detects:
905 // => ; ) finally catch else
906 // as all of these followed by a { will indicate a statement brace
907 switch (source.charCodeAt(curPos)) {
908 case 62/*>*/:
909 return source.charCodeAt(curPos - 1) === 61/*=*/;
910 case 59/*;*/:
911 case 41/*)*/:
912 return true;
913 case 104/*h*/:
914 return source.startsWith('catc', curPos - 4);
915 case 121/*y*/:
916 return source.startsWith('finall', curPos - 6);
917 case 101/*e*/:
918 return source.startsWith('els', curPos - 3);
919 }
920 return false;
921}
922
923function syntaxError () {
924 throw Object.assign(new Error(`Parse error ${name}:${source.slice(0, pos).split('\n').length}:${pos - source.lastIndexOf('\n', pos - 1)}`), { idx: pos });
925}
Note: See TracBrowser for help on using the repository browser.