|
- let source, pos, end,
- openTokenDepth,
- lastTokenPos,
- openTokenPosStack,
- openClassPosStack,
- curDynamicImport,
- templateStackDepth,
- facade,
- lastSlashWasDivision,
- nextBraceIsClass,
- templateDepth,
- templateStack,
- imports,
- exports,
- name;
-
- function addImport (ss, s, e, d) {
- const impt = { ss, se: d === -2 ? e : d === -1 ? e + 1 : 0, s, e, d, a: -1, n: undefined };
- imports.push(impt);
- return impt;
- }
-
- function addExport (s, e, ls, le) {
- exports.push({
- s,
- e,
- ls,
- le,
- n: s[0] === '"' ? readString(s, '"') : s[0] === "'" ? readString(s, "'") : source.slice(s, e),
- ln: ls[0] === '"' ? readString(ls, '"') : ls[0] === "'" ? readString(ls, "'") : source.slice(ls, le)
- });
- }
-
- function readName (impt) {
- let { d, s } = impt;
- if (d !== -1)
- s++;
- impt.n = readString(s, source.charCodeAt(s - 1));
- }
-
- // Note: parsing is based on the _assumption_ that the source is already valid
- export function parse (_source, _name) {
- openTokenDepth = 0;
- curDynamicImport = null;
- templateDepth = -1;
- lastTokenPos = -1;
- lastSlashWasDivision = false;
- templateStack = Array(1024);
- templateStackDepth = 0;
- openTokenPosStack = Array(1024);
- openClassPosStack = Array(1024);
- nextBraceIsClass = false;
- facade = true;
- name = _name || '@';
-
- imports = [];
- exports = [];
-
- source = _source;
- pos = -1;
- end = source.length - 1;
- let ch = 0;
-
- // start with a pure "module-only" parser
- m: while (pos++ < end) {
- ch = source.charCodeAt(pos);
-
- if (ch === 32 || ch < 14 && ch > 8)
- continue;
-
- switch (ch) {
- case 101/*e*/:
- if (openTokenDepth === 0 && keywordStart(pos) && source.startsWith('xport', pos + 1)) {
- tryParseExportStatement();
- // export might have been a non-pure declaration
- if (!facade) {
- lastTokenPos = pos;
- break m;
- }
- }
- break;
- case 105/*i*/:
- if (keywordStart(pos) && source.startsWith('mport', pos + 1))
- tryParseImportStatement();
- break;
- case 59/*;*/:
- break;
- case 47/*/*/: {
- const next_ch = source.charCodeAt(pos + 1);
- if (next_ch === 47/*/*/) {
- lineComment();
- // dont update lastToken
- continue;
- }
- else if (next_ch === 42/***/) {
- blockComment(true);
- // dont update lastToken
- continue;
- }
- // fallthrough
- }
- default:
- // as soon as we hit a non-module token, we go to main parser
- facade = false;
- pos--;
- break m;
- }
- lastTokenPos = pos;
- }
-
- while (pos++ < end) {
- ch = source.charCodeAt(pos);
-
- if (ch === 32 || ch < 14 && ch > 8)
- continue;
-
- switch (ch) {
- case 101/*e*/:
- if (openTokenDepth === 0 && keywordStart(pos) && source.startsWith('xport', pos + 1))
- tryParseExportStatement();
- break;
- case 105/*i*/:
- if (keywordStart(pos) && source.startsWith('mport', pos + 1))
- tryParseImportStatement();
- break;
- case 99/*c*/:
- if (keywordStart(pos) && source.startsWith('lass', pos + 1) && isBrOrWs(source.charCodeAt(pos + 5)))
- nextBraceIsClass = true;
- break;
- case 40/*(*/:
- openTokenPosStack[openTokenDepth++] = lastTokenPos;
- break;
- case 41/*)*/:
- if (openTokenDepth === 0)
- syntaxError();
- openTokenDepth--;
- if (curDynamicImport && curDynamicImport.d === openTokenPosStack[openTokenDepth]) {
- if (curDynamicImport.e === 0)
- curDynamicImport.e = pos;
- curDynamicImport.se = pos;
- curDynamicImport = null;
- }
- break;
- case 123/*{*/:
- // dynamic import followed by { is not a dynamic import (so remove)
- // this is a sneaky way to get around { import () {} } v { import () }
- // block / object ambiguity without a parser (assuming source is valid)
- if (source.charCodeAt(lastTokenPos) === 41/*)*/ && imports.length && imports[imports.length - 1].e === lastTokenPos) {
- imports.pop();
- }
- openClassPosStack[openTokenDepth] = nextBraceIsClass;
- nextBraceIsClass = false;
- openTokenPosStack[openTokenDepth++] = lastTokenPos;
- break;
- case 125/*}*/:
- if (openTokenDepth === 0)
- syntaxError();
- if (openTokenDepth-- === templateDepth) {
- templateDepth = templateStack[--templateStackDepth];
- templateString();
- }
- else {
- if (templateDepth !== -1 && openTokenDepth < templateDepth)
- syntaxError();
- }
- break;
- case 39/*'*/:
- case 34/*"*/:
- stringLiteral(ch);
- break;
- case 47/*/*/: {
- const next_ch = source.charCodeAt(pos + 1);
- if (next_ch === 47/*/*/) {
- lineComment();
- // dont update lastToken
- continue;
- }
- else if (next_ch === 42/***/) {
- blockComment(true);
- // dont update lastToken
- continue;
- }
- else {
- // Division / regex ambiguity handling based on checking backtrack analysis of:
- // - what token came previously (lastToken)
- // - if a closing brace or paren, what token came before the corresponding
- // opening brace or paren (lastOpenTokenIndex)
- const lastToken = source.charCodeAt(lastTokenPos);
- const lastExport = exports[exports.length - 1];
- if (isExpressionPunctuator(lastToken) &&
- !(lastToken === 46/*.*/ && (source.charCodeAt(lastTokenPos - 1) >= 48/*0*/ && source.charCodeAt(lastTokenPos - 1) <= 57/*9*/)) &&
- !(lastToken === 43/*+*/ && source.charCodeAt(lastTokenPos - 1) === 43/*+*/) && !(lastToken === 45/*-*/ && source.charCodeAt(lastTokenPos - 1) === 45/*-*/) ||
- lastToken === 41/*)*/ && isParenKeyword(openTokenPosStack[openTokenDepth]) ||
- lastToken === 125/*}*/ && (isExpressionTerminator(openTokenPosStack[openTokenDepth]) || openClassPosStack[openTokenDepth]) ||
- lastToken === 47/*/*/ && lastSlashWasDivision ||
- isExpressionKeyword(lastTokenPos) ||
- !lastToken) {
- regularExpression();
- lastSlashWasDivision = false;
- }
- else if (lastExport && lastTokenPos >= lastExport.s && lastTokenPos <= lastExport.e) {
- // export default /some-regexp/
- regularExpression();
- lastSlashWasDivision = false;
- }
- else {
- lastSlashWasDivision = true;
- }
- }
- break;
- }
- case 96/*`*/:
- templateString();
- break;
- }
- lastTokenPos = pos;
- }
-
- if (templateDepth !== -1 || openTokenDepth)
- syntaxError();
-
- return [imports, exports, facade];
- }
-
- function tryParseImportStatement () {
- const startPos = pos;
-
- pos += 6;
-
- let ch = commentWhitespace(true);
-
- switch (ch) {
- // dynamic import
- case 40/*(*/:
- openTokenPosStack[openTokenDepth++] = startPos;
- if (source.charCodeAt(lastTokenPos) === 46/*.*/)
- return;
- // dynamic import indicated by positive d
- const impt = addImport(startPos, pos + 1, 0, startPos);
- curDynamicImport = impt;
- // try parse a string, to record a safe dynamic import string
- pos++;
- ch = commentWhitespace(true);
- if (ch === 39/*'*/ || ch === 34/*"*/) {
- stringLiteral(ch);
- }
- else {
- pos--;
- return;
- }
- pos++;
- ch = commentWhitespace(true);
- if (ch === 44/*,*/) {
- impt.e = pos;
- pos++;
- ch = commentWhitespace(true);
- impt.a = pos;
- readName(impt);
- pos--;
- }
- else if (ch === 41/*)*/) {
- openTokenDepth--;
- impt.e = pos;
- impt.se = pos;
- readName(impt);
- }
- else {
- pos--;
- }
- return;
- // import.meta
- case 46/*.*/:
- pos++;
- ch = commentWhitespace(true);
- // import.meta indicated by d === -2
- if (ch === 109/*m*/ && source.startsWith('eta', pos + 1) && source.charCodeAt(lastTokenPos) !== 46/*.*/)
- addImport(startPos, startPos, pos + 4, -2);
- return;
-
- default:
- // no space after "import" -> not an import keyword
- if (pos === startPos + 6)
- break;
- case 34/*"*/:
- case 39/*'*/:
- case 123/*{*/:
- case 42/***/:
- // import statement only permitted at base-level
- if (openTokenDepth !== 0) {
- pos--;
- return;
- }
- while (pos < end) {
- ch = source.charCodeAt(pos);
- if (ch === 39/*'*/ || ch === 34/*"*/) {
- readImportString(startPos, ch);
- return;
- }
- pos++;
- }
- syntaxError();
- }
- }
-
- function tryParseExportStatement () {
- const sStartPos = pos;
- const prevExport = exports.length;
-
- pos += 6;
-
- const curPos = pos;
-
- let ch = commentWhitespace(true);
-
- if (pos === curPos && !isPunctuator(ch))
- return;
-
- switch (ch) {
- // export default ...
- case 100/*d*/:
- addExport(pos, pos + 7, -1, -1);
- return;
-
- // export async? function*? name () {
- case 97/*a*/:
- pos += 5;
- commentWhitespace(true);
- // fallthrough
- case 102/*f*/:
- pos += 8;
- ch = commentWhitespace(true);
- if (ch === 42/***/) {
- pos++;
- ch = commentWhitespace(true);
- }
- const startPos = pos;
- ch = readToWsOrPunctuator(ch);
- addExport(startPos, pos, startPos, pos);
- pos--;
- return;
-
- // export class name ...
- case 99/*c*/:
- if (source.startsWith('lass', pos + 1) && isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos + 5))) {
- pos += 5;
- ch = commentWhitespace(true);
- const startPos = pos;
- ch = readToWsOrPunctuator(ch);
- addExport(startPos, pos, startPos, pos);
- pos--;
- return;
- }
- pos += 2;
- // fallthrough
-
- // export var/let/const name = ...(, name = ...)+
- case 118/*v*/:
- case 109/*l*/:
- // destructured initializations not currently supported (skipped for { or [)
- // also, lexing names after variable equals is skipped (export var p = function () { ... }, q = 5 skips "q")
- pos += 2;
- facade = false;
- do {
- pos++;
- ch = commentWhitespace(true);
- const startPos = pos;
- ch = readToWsOrPunctuator(ch);
- // dont yet handle [ { destructurings
- if (ch === 123/*{*/ || ch === 91/*[*/) {
- pos--;
- return;
- }
- if (pos === startPos)
- return;
- addExport(startPos, pos, startPos, pos);
- ch = commentWhitespace(true);
- if (ch === 61/*=*/) {
- pos--;
- return;
- }
- } while (ch === 44/*,*/);
- pos--;
- return;
-
-
- // export {...}
- case 123/*{*/:
- pos++;
- ch = commentWhitespace(true);
- while (true) {
- const startPos = pos;
- readToWsOrPunctuator(ch);
- const endPos = pos;
- commentWhitespace(true);
- ch = readExportAs(startPos, endPos);
- // ,
- if (ch === 44/*,*/) {
- pos++;
- ch = commentWhitespace(true);
- }
- if (ch === 125/*}*/)
- break;
- if (pos === startPos)
- return syntaxError();
- if (pos > end)
- return syntaxError();
- }
- pos++;
- ch = commentWhitespace(true);
- break;
-
- // export *
- // export * as X
- case 42/***/:
- pos++;
- commentWhitespace(true);
- ch = readExportAs(pos, pos);
- ch = commentWhitespace(true);
- break;
- }
-
- // from ...
- if (ch === 102/*f*/ && source.startsWith('rom', pos + 1)) {
- pos += 4;
- readImportString(sStartPos, commentWhitespace(true));
-
- // There were no local names.
- for (let i = prevExport; i < exports.length; ++i) {
- exports[i].ls = exports[i].le = -1;
- exports[i].ln = undefined;
- }
- }
- else {
- pos--;
- }
- }
-
- /*
- * Ported from Acorn
- *
- * MIT License
-
- * Copyright (C) 2012-2020 by various contributors (see AUTHORS)
-
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
-
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
-
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- let acornPos;
- function readString (start, quote) {
- acornPos = start;
- let out = '', chunkStart = acornPos;
- for (;;) {
- if (acornPos >= source.length) syntaxError();
- const ch = source.charCodeAt(acornPos);
- if (ch === quote) break;
- if (ch === 92) { // '\'
- out += source.slice(chunkStart, acornPos);
- out += readEscapedChar();
- chunkStart = acornPos;
- }
- else if (ch === 0x2028 || ch === 0x2029) {
- ++acornPos;
- }
- else {
- if (isBr(ch)) syntaxError();
- ++acornPos;
- }
- }
- out += source.slice(chunkStart, acornPos++);
- return out;
- }
-
- // Used to read escaped characters
-
- function readEscapedChar () {
- let ch = source.charCodeAt(++acornPos);
- ++acornPos;
- switch (ch) {
- case 110: return '\n'; // 'n' -> '\n'
- case 114: return '\r'; // 'r' -> '\r'
- case 120: return String.fromCharCode(readHexChar(2)); // 'x'
- case 117: return readCodePointToString(); // 'u'
- case 116: return '\t'; // 't' -> '\t'
- case 98: return '\b'; // 'b' -> '\b'
- case 118: return '\u000b'; // 'v' -> '\u000b'
- case 102: return '\f'; // 'f' -> '\f'
- case 13: if (source.charCodeAt(acornPos) === 10) ++acornPos; // '\r\n'
- case 10: // ' \n'
- return '';
- case 56:
- case 57:
- syntaxError();
- default:
- if (ch >= 48 && ch <= 55) {
- let octalStr = source.substr(acornPos - 1, 3).match(/^[0-7]+/)[0];
- let octal = parseInt(octalStr, 8);
- if (octal > 255) {
- octalStr = octalStr.slice(0, -1);
- octal = parseInt(octalStr, 8);
- }
- acornPos += octalStr.length - 1;
- ch = source.charCodeAt(acornPos);
- if (octalStr !== '0' || ch === 56 || ch === 57)
- syntaxError();
- return String.fromCharCode(octal);
- }
- if (isBr(ch)) {
- // Unicode new line characters after \ get removed from output in both
- // template literals and strings
- return '';
- }
- return String.fromCharCode(ch);
- }
- }
-
- // Used to read character escape sequences ('\x', '\u', '\U').
-
- function readHexChar (len) {
- const start = acornPos;
- let total = 0, lastCode = 0;
- for (let i = 0; i < len; ++i, ++acornPos) {
- let code = source.charCodeAt(acornPos), val;
-
- if (code === 95) {
- if (lastCode === 95 || i === 0) syntaxError();
- lastCode = code;
- continue;
- }
-
- if (code >= 97) val = code - 97 + 10; // a
- else if (code >= 65) val = code - 65 + 10; // A
- else if (code >= 48 && code <= 57) val = code - 48; // 0-9
- else break;
- if (val >= 16) break;
- lastCode = code;
- total = total * 16 + val;
- }
-
- if (lastCode === 95 || acornPos - start !== len) syntaxError();
-
- return total;
- }
-
- // Read a string value, interpreting backslash-escapes.
-
- function readCodePointToString () {
- const ch = source.charCodeAt(acornPos);
- let code;
- if (ch === 123) { // '{'
- ++acornPos;
- code = readHexChar(source.indexOf('}', acornPos) - acornPos);
- ++acornPos;
- if (code > 0x10FFFF) syntaxError();
- } else {
- code = readHexChar(4);
- }
- // UTF-16 Decoding
- if (code <= 0xFFFF) return String.fromCharCode(code);
- code -= 0x10000;
- return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00);
- }
-
- /*
- * </ Acorn Port>
- */
-
- function readExportAs (startPos, endPos) {
- let ch = source.charCodeAt(pos);
- let ls = startPos, le = endPos;
- if (ch === 97 /*a*/) {
- pos += 2;
- ch = commentWhitespace(true);
- startPos = pos;
- readToWsOrPunctuator(ch);
- endPos = pos;
- ch = commentWhitespace(true);
- }
- if (pos !== startPos)
- addExport(startPos, endPos, ls, le);
- return ch;
- }
-
- function readImportString (ss, ch) {
- const startPos = pos + 1;
- if (ch === 39/*'*/ || ch === 34/*"*/) {
- stringLiteral(ch);
- }
- else {
- syntaxError();
- return;
- }
- const impt = addImport(ss, startPos, pos, -1);
- readName(impt);
- pos++;
- ch = commentWhitespace(false);
- if (ch !== 97/*a*/ || !source.startsWith('ssert', pos + 1)) {
- pos--;
- return;
- }
- const assertIndex = pos;
-
- pos += 6;
- ch = commentWhitespace(true);
- if (ch !== 123/*{*/) {
- pos = assertIndex;
- return;
- }
- const assertStart = pos;
- do {
- pos++;
- ch = commentWhitespace(true);
- if (ch === 39/*'*/ || ch === 34/*"*/) {
- stringLiteral(ch);
- pos++;
- ch = commentWhitespace(true);
- }
- else {
- ch = readToWsOrPunctuator(ch);
- }
- if (ch !== 58/*:*/) {
- pos = assertIndex;
- return;
- }
- pos++;
- ch = commentWhitespace(true);
- if (ch === 39/*'*/ || ch === 34/*"*/) {
- stringLiteral(ch);
- }
- else {
- pos = assertIndex;
- return;
- }
- pos++;
- ch = commentWhitespace(true);
- if (ch === 44/*,*/) {
- pos++;
- ch = commentWhitespace(true);
- if (ch === 125/*}*/)
- break;
- continue;
- }
- if (ch === 125/*}*/)
- break;
- pos = assertIndex;
- return;
- } while (true);
- impt.a = assertStart;
- impt.se = pos + 1;
- }
-
- function commentWhitespace (br) {
- let ch;
- do {
- ch = source.charCodeAt(pos);
- if (ch === 47/*/*/) {
- const next_ch = source.charCodeAt(pos + 1);
- if (next_ch === 47/*/*/)
- lineComment();
- else if (next_ch === 42/***/)
- blockComment(br);
- else
- return ch;
- }
- else if (br ? !isBrOrWs(ch): !isWsNotBr(ch)) {
- return ch;
- }
- } while (pos++ < end);
- return ch;
- }
-
- function templateString () {
- while (pos++ < end) {
- const ch = source.charCodeAt(pos);
- if (ch === 36/*$*/ && source.charCodeAt(pos + 1) === 123/*{*/) {
- pos++;
- templateStack[templateStackDepth++] = templateDepth;
- templateDepth = ++openTokenDepth;
- return;
- }
- if (ch === 96/*`*/)
- return;
- if (ch === 92/*\*/)
- pos++;
- }
- syntaxError();
- }
-
- function blockComment (br) {
- pos++;
- while (pos++ < end) {
- const ch = source.charCodeAt(pos);
- if (!br && isBr(ch))
- return;
- if (ch === 42/***/ && source.charCodeAt(pos + 1) === 47/*/*/) {
- pos++;
- return;
- }
- }
- }
-
- function lineComment () {
- while (pos++ < end) {
- const ch = source.charCodeAt(pos);
- if (ch === 10/*\n*/ || ch === 13/*\r*/)
- return;
- }
- }
-
- function stringLiteral (quote) {
- while (pos++ < end) {
- let ch = source.charCodeAt(pos);
- if (ch === quote)
- return;
- if (ch === 92/*\*/) {
- ch = source.charCodeAt(++pos);
- if (ch === 13/*\r*/ && source.charCodeAt(pos + 1) === 10/*\n*/)
- pos++;
- }
- else if (isBr(ch))
- break;
- }
- syntaxError();
- }
-
- function regexCharacterClass () {
- while (pos++ < end) {
- let ch = source.charCodeAt(pos);
- if (ch === 93/*]*/)
- return ch;
- if (ch === 92/*\*/)
- pos++;
- else if (ch === 10/*\n*/ || ch === 13/*\r*/)
- break;
- }
- syntaxError();
- }
-
- function regularExpression () {
- while (pos++ < end) {
- let ch = source.charCodeAt(pos);
- if (ch === 47/*/*/)
- return;
- if (ch === 91/*[*/)
- ch = regexCharacterClass();
- else if (ch === 92/*\*/)
- pos++;
- else if (ch === 10/*\n*/ || ch === 13/*\r*/)
- break;
- }
- syntaxError();
- }
-
- function readToWsOrPunctuator (ch) {
- do {
- if (isBrOrWs(ch) || isPunctuator(ch))
- return ch;
- } while (ch = source.charCodeAt(++pos));
- return ch;
- }
-
- // Note: non-asii BR and whitespace checks omitted for perf / footprint
- // if there is a significant user need this can be reconsidered
- function isBr (c) {
- return c === 13/*\r*/ || c === 10/*\n*/;
- }
-
- function isWsNotBr (c) {
- return c === 9 || c === 11 || c === 12 || c === 32 || c === 160;
- }
-
- function isBrOrWs (c) {
- return c > 8 && c < 14 || c === 32 || c === 160;
- }
-
- function isBrOrWsOrPunctuatorNotDot (c) {
- return c > 8 && c < 14 || c === 32 || c === 160 || isPunctuator(c) && c !== 46/*.*/;
- }
-
- function keywordStart (pos) {
- return pos === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos - 1));
- }
-
- function readPrecedingKeyword (pos, match) {
- if (pos < match.length - 1)
- return false;
- return source.startsWith(match, pos - match.length + 1) && (pos === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos - match.length)));
- }
-
- function readPrecedingKeyword1 (pos, ch) {
- return source.charCodeAt(pos) === ch && (pos === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos - 1)));
- }
-
- // Detects one of case, debugger, delete, do, else, in, instanceof, new,
- // return, throw, typeof, void, yield, await
- function isExpressionKeyword (pos) {
- switch (source.charCodeAt(pos)) {
- case 100/*d*/:
- switch (source.charCodeAt(pos - 1)) {
- case 105/*i*/:
- // void
- return readPrecedingKeyword(pos - 2, 'vo');
- case 108/*l*/:
- // yield
- return readPrecedingKeyword(pos - 2, 'yie');
- default:
- return false;
- }
- case 101/*e*/:
- switch (source.charCodeAt(pos - 1)) {
- case 115/*s*/:
- switch (source.charCodeAt(pos - 2)) {
- case 108/*l*/:
- // else
- return readPrecedingKeyword1(pos - 3, 101/*e*/);
- case 97/*a*/:
- // case
- return readPrecedingKeyword1(pos - 3, 99/*c*/);
- default:
- return false;
- }
- case 116/*t*/:
- // delete
- return readPrecedingKeyword(pos - 2, 'dele');
- default:
- return false;
- }
- case 102/*f*/:
- if (source.charCodeAt(pos - 1) !== 111/*o*/ || source.charCodeAt(pos - 2) !== 101/*e*/)
- return false;
- switch (source.charCodeAt(pos - 3)) {
- case 99/*c*/:
- // instanceof
- return readPrecedingKeyword(pos - 4, 'instan');
- case 112/*p*/:
- // typeof
- return readPrecedingKeyword(pos - 4, 'ty');
- default:
- return false;
- }
- case 110/*n*/:
- // in, return
- return readPrecedingKeyword1(pos - 1, 105/*i*/) || readPrecedingKeyword(pos - 1, 'retur');
- case 111/*o*/:
- // do
- return readPrecedingKeyword1(pos - 1, 100/*d*/);
- case 114/*r*/:
- // debugger
- return readPrecedingKeyword(pos - 1, 'debugge');
- case 116/*t*/:
- // await
- return readPrecedingKeyword(pos - 1, 'awai');
- case 119/*w*/:
- switch (source.charCodeAt(pos - 1)) {
- case 101/*e*/:
- // new
- return readPrecedingKeyword1(pos - 2, 110/*n*/);
- case 111/*o*/:
- // throw
- return readPrecedingKeyword(pos - 2, 'thr');
- default:
- return false;
- }
- }
- return false;
- }
-
- function isParenKeyword (curPos) {
- return source.charCodeAt(curPos) === 101/*e*/ && source.startsWith('whil', curPos - 4) ||
- source.charCodeAt(curPos) === 114/*r*/ && source.startsWith('fo', curPos - 2) ||
- source.charCodeAt(curPos - 1) === 105/*i*/ && source.charCodeAt(curPos) === 102/*f*/;
- }
-
- function isPunctuator (ch) {
- // 23 possible punctuator endings: !%&()*+,-./:;<=>?[]^{}|~
- return ch === 33/*!*/ || ch === 37/*%*/ || ch === 38/*&*/ ||
- ch > 39 && ch < 48 || ch > 57 && ch < 64 ||
- ch === 91/*[*/ || ch === 93/*]*/ || ch === 94/*^*/ ||
- ch > 122 && ch < 127;
- }
-
- function isExpressionPunctuator (ch) {
- // 20 possible expression endings: !%&(*+,-.:;<=>?[^{|~
- return ch === 33/*!*/ || ch === 37/*%*/ || ch === 38/*&*/ ||
- ch > 39 && ch < 47 && ch !== 41 || ch > 57 && ch < 64 ||
- ch === 91/*[*/ || ch === 94/*^*/ || ch > 122 && ch < 127 && ch !== 125/*}*/;
- }
-
- function isExpressionTerminator (curPos) {
- // detects:
- // => ; ) finally catch else
- // as all of these followed by a { will indicate a statement brace
- switch (source.charCodeAt(curPos)) {
- case 62/*>*/:
- return source.charCodeAt(curPos - 1) === 61/*=*/;
- case 59/*;*/:
- case 41/*)*/:
- return true;
- case 104/*h*/:
- return source.startsWith('catc', curPos - 4);
- case 121/*y*/:
- return source.startsWith('finall', curPos - 6);
- case 101/*e*/:
- return source.startsWith('els', curPos - 3);
- }
- return false;
- }
-
- function syntaxError () {
- throw Object.assign(new Error(`Parse error ${name}:${source.slice(0, pos).split('\n').length}:${pos - source.lastIndexOf('\n', pos - 1)}`), { idx: pos });
- }
|