123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925 |
- 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 });
- }
|