🏡 index : cold-air-networks/mirror-jetstream.git

/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ "./node_modules/esprima-next/dist/esprima.js":
/*!***************************************************!*\
  !*** ./node_modules/esprima-next/dist/esprima.js ***!
  \***************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   ArrayExpression: () => (/* binding */ ArrayExpression),
/* harmony export */   ArrayPattern: () => (/* binding */ ArrayPattern),
/* harmony export */   ArrowFunctionExpression: () => (/* binding */ ArrowFunctionExpression),
/* harmony export */   AssignmentExpression: () => (/* binding */ AssignmentExpression),
/* harmony export */   AssignmentPattern: () => (/* binding */ AssignmentPattern),
/* harmony export */   AsyncFunctionDeclaration: () => (/* binding */ AsyncFunctionDeclaration),
/* harmony export */   AwaitExpression: () => (/* binding */ AwaitExpression),
/* harmony export */   BigIntLiteral: () => (/* binding */ BigIntLiteral),
/* harmony export */   BinaryExpression: () => (/* binding */ BinaryExpression),
/* harmony export */   BlockStatement: () => (/* binding */ BlockStatement),
/* harmony export */   BreakStatement: () => (/* binding */ BreakStatement),
/* harmony export */   CallExpression: () => (/* binding */ CallExpression),
/* harmony export */   CatchClause: () => (/* binding */ CatchClause),
/* harmony export */   ChainExpression: () => (/* binding */ ChainExpression),
/* harmony export */   ClassBody: () => (/* binding */ ClassBody),
/* harmony export */   ClassDeclaration: () => (/* binding */ ClassDeclaration),
/* harmony export */   ClassExpression: () => (/* binding */ ClassExpression),
/* harmony export */   ConditionalExpression: () => (/* binding */ ConditionalExpression),
/* harmony export */   ContinueStatement: () => (/* binding */ ContinueStatement),
/* harmony export */   DebuggerStatement: () => (/* binding */ DebuggerStatement),
/* harmony export */   Decorator: () => (/* binding */ Decorator),
/* harmony export */   Directive: () => (/* binding */ Directive),
/* harmony export */   DoWhileStatement: () => (/* binding */ DoWhileStatement),
/* harmony export */   EmptyStatement: () => (/* binding */ EmptyStatement),
/* harmony export */   ExportAllDeclaration: () => (/* binding */ ExportAllDeclaration),
/* harmony export */   ExportDefaultDeclaration: () => (/* binding */ ExportDefaultDeclaration),
/* harmony export */   ExportNamedDeclaration: () => (/* binding */ ExportNamedDeclaration),
/* harmony export */   ExportSpecifier: () => (/* binding */ ExportSpecifier),
/* harmony export */   ExpressionStatement: () => (/* binding */ ExpressionStatement),
/* harmony export */   ForInStatement: () => (/* binding */ ForInStatement),
/* harmony export */   ForOfStatement: () => (/* binding */ ForOfStatement),
/* harmony export */   ForStatement: () => (/* binding */ ForStatement),
/* harmony export */   FunctionDeclaration: () => (/* binding */ FunctionDeclaration),
/* harmony export */   FunctionExpression: () => (/* binding */ FunctionExpression),
/* harmony export */   Identifier: () => (/* binding */ Identifier),
/* harmony export */   IfStatement: () => (/* binding */ IfStatement),
/* harmony export */   ImportAttribute: () => (/* binding */ ImportAttribute),
/* harmony export */   ImportDeclaration: () => (/* binding */ ImportDeclaration),
/* harmony export */   ImportDefaultSpecifier: () => (/* binding */ ImportDefaultSpecifier),
/* harmony export */   ImportExpression: () => (/* binding */ ImportExpression),
/* harmony export */   ImportNamespaceSpecifier: () => (/* binding */ ImportNamespaceSpecifier),
/* harmony export */   ImportSpecifier: () => (/* binding */ ImportSpecifier),
/* harmony export */   LabeledStatement: () => (/* binding */ LabeledStatement),
/* harmony export */   Literal: () => (/* binding */ Literal),
/* harmony export */   LogicalExpression: () => (/* binding */ LogicalExpression),
/* harmony export */   MemberExpression: () => (/* binding */ MemberExpression),
/* harmony export */   MetaProperty: () => (/* binding */ MetaProperty),
/* harmony export */   MethodDefinition: () => (/* binding */ MethodDefinition),
/* harmony export */   Module: () => (/* binding */ Module),
/* harmony export */   NewExpression: () => (/* binding */ NewExpression),
/* harmony export */   Nodes: () => (/* binding */ nodes_exports),
/* harmony export */   ObjectExpression: () => (/* binding */ ObjectExpression),
/* harmony export */   ObjectPattern: () => (/* binding */ ObjectPattern),
/* harmony export */   PrivateIdentifier: () => (/* binding */ PrivateIdentifier),
/* harmony export */   Program: () => (/* binding */ Program),
/* harmony export */   Property: () => (/* binding */ Property),
/* harmony export */   PropertyDefinition: () => (/* binding */ PropertyDefinition),
/* harmony export */   RegexLiteral: () => (/* binding */ RegexLiteral),
/* harmony export */   RestElement: () => (/* binding */ RestElement),
/* harmony export */   ReturnStatement: () => (/* binding */ ReturnStatement),
/* harmony export */   Script: () => (/* binding */ Script),
/* harmony export */   SequenceExpression: () => (/* binding */ SequenceExpression),
/* harmony export */   SpreadElement: () => (/* binding */ SpreadElement),
/* harmony export */   StaticBlock: () => (/* binding */ StaticBlock),
/* harmony export */   Super: () => (/* binding */ Super),
/* harmony export */   SwitchCase: () => (/* binding */ SwitchCase),
/* harmony export */   SwitchStatement: () => (/* binding */ SwitchStatement),
/* harmony export */   Syntax: () => (/* binding */ Syntax),
/* harmony export */   TaggedTemplateExpression: () => (/* binding */ TaggedTemplateExpression),
/* harmony export */   TemplateElement: () => (/* binding */ TemplateElement),
/* harmony export */   TemplateLiteral: () => (/* binding */ TemplateLiteral),
/* harmony export */   ThisExpression: () => (/* binding */ ThisExpression),
/* harmony export */   ThrowStatement: () => (/* binding */ ThrowStatement),
/* harmony export */   TryStatement: () => (/* binding */ TryStatement),
/* harmony export */   UnaryExpression: () => (/* binding */ UnaryExpression),
/* harmony export */   UpdateExpression: () => (/* binding */ UpdateExpression),
/* harmony export */   VariableDeclaration: () => (/* binding */ VariableDeclaration),
/* harmony export */   VariableDeclarator: () => (/* binding */ VariableDeclarator),
/* harmony export */   Visitor: () => (/* binding */ Visitor),
/* harmony export */   WhileStatement: () => (/* binding */ WhileStatement),
/* harmony export */   WithStatement: () => (/* binding */ WithStatement),
/* harmony export */   YieldExpression: () => (/* binding */ YieldExpression),
/* harmony export */   "default": () => (/* binding */ esprima_default),
/* harmony export */   parse: () => (/* binding */ parse),
/* harmony export */   parseModule: () => (/* binding */ parseModule),
/* harmony export */   parseScript: () => (/* binding */ parseScript),
/* harmony export */   tokenize: () => (/* binding */ tokenize),
/* harmony export */   version: () => (/* binding */ version)
/* harmony export */ });
var __defProp = Object.defineProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};

// src/syntax.ts
var Syntax = /* @__PURE__ */ ((Syntax2) => {
  Syntax2["AssignmentExpression"] = "AssignmentExpression";
  Syntax2["AssignmentPattern"] = "AssignmentPattern";
  Syntax2["ArrayExpression"] = "ArrayExpression";
  Syntax2["ArrayPattern"] = "ArrayPattern";
  Syntax2["ArrowFunctionExpression"] = "ArrowFunctionExpression";
  Syntax2["AwaitExpression"] = "AwaitExpression";
  Syntax2["BlockStatement"] = "BlockStatement";
  Syntax2["BinaryExpression"] = "BinaryExpression";
  Syntax2["BreakStatement"] = "BreakStatement";
  Syntax2["CallExpression"] = "CallExpression";
  Syntax2["CatchClause"] = "CatchClause";
  Syntax2["ChainExpression"] = "ChainExpression";
  Syntax2["ClassBody"] = "ClassBody";
  Syntax2["ClassDeclaration"] = "ClassDeclaration";
  Syntax2["ClassExpression"] = "ClassExpression";
  Syntax2["ConditionalExpression"] = "ConditionalExpression";
  Syntax2["ContinueStatement"] = "ContinueStatement";
  Syntax2["Decorator"] = "Decorator";
  Syntax2["DoWhileStatement"] = "DoWhileStatement";
  Syntax2["DebuggerStatement"] = "DebuggerStatement";
  Syntax2["EmptyStatement"] = "EmptyStatement";
  Syntax2["ExportAllDeclaration"] = "ExportAllDeclaration";
  Syntax2["ExportDefaultDeclaration"] = "ExportDefaultDeclaration";
  Syntax2["ExportNamedDeclaration"] = "ExportNamedDeclaration";
  Syntax2["ExportSpecifier"] = "ExportSpecifier";
  Syntax2["ExpressionStatement"] = "ExpressionStatement";
  Syntax2["ForStatement"] = "ForStatement";
  Syntax2["ForOfStatement"] = "ForOfStatement";
  Syntax2["ForInStatement"] = "ForInStatement";
  Syntax2["FunctionDeclaration"] = "FunctionDeclaration";
  Syntax2["FunctionExpression"] = "FunctionExpression";
  Syntax2["Identifier"] = "Identifier";
  Syntax2["IfStatement"] = "IfStatement";
  Syntax2["ImportAttribute"] = "ImportAttribute";
  Syntax2["ImportExpression"] = "ImportExpression";
  Syntax2["ImportDeclaration"] = "ImportDeclaration";
  Syntax2["ImportDefaultSpecifier"] = "ImportDefaultSpecifier";
  Syntax2["ImportNamespaceSpecifier"] = "ImportNamespaceSpecifier";
  Syntax2["ImportSpecifier"] = "ImportSpecifier";
  Syntax2["Literal"] = "Literal";
  Syntax2["LabeledStatement"] = "LabeledStatement";
  Syntax2["LogicalExpression"] = "LogicalExpression";
  Syntax2["MemberExpression"] = "MemberExpression";
  Syntax2["MetaProperty"] = "MetaProperty";
  Syntax2["MethodDefinition"] = "MethodDefinition";
  Syntax2["NewExpression"] = "NewExpression";
  Syntax2["ObjectExpression"] = "ObjectExpression";
  Syntax2["ObjectPattern"] = "ObjectPattern";
  Syntax2["Program"] = "Program";
  Syntax2["Property"] = "Property";
  Syntax2["PrivateIdentifier"] = "PrivateIdentifier";
  Syntax2["RestElement"] = "RestElement";
  Syntax2["ReturnStatement"] = "ReturnStatement";
  Syntax2["SequenceExpression"] = "SequenceExpression";
  Syntax2["SpreadElement"] = "SpreadElement";
  Syntax2["StaticBlock"] = "StaticBlock";
  Syntax2["Super"] = "Super";
  Syntax2["SwitchCase"] = "SwitchCase";
  Syntax2["SwitchStatement"] = "SwitchStatement";
  Syntax2["TaggedTemplateExpression"] = "TaggedTemplateExpression";
  Syntax2["TemplateElement"] = "TemplateElement";
  Syntax2["TemplateLiteral"] = "TemplateLiteral";
  Syntax2["ThisExpression"] = "ThisExpression";
  Syntax2["ThrowStatement"] = "ThrowStatement";
  Syntax2["TryStatement"] = "TryStatement";
  Syntax2["UnaryExpression"] = "UnaryExpression";
  Syntax2["UpdateExpression"] = "UpdateExpression";
  Syntax2["VariableDeclaration"] = "VariableDeclaration";
  Syntax2["VariableDeclarator"] = "VariableDeclarator";
  Syntax2["WhileStatement"] = "WhileStatement";
  Syntax2["WithStatement"] = "WithStatement";
  Syntax2["YieldExpression"] = "YieldExpression";
  return Syntax2;
})(Syntax || {});

// src/comment-handler.ts
var CommentHandler = class {
  attach;
  comments;
  stack;
  leading;
  trailing;
  constructor() {
    this.attach = false;
    this.comments = [];
    this.stack = [];
    this.leading = [];
    this.trailing = [];
  }
  insertInnerComments(node, metadata) {
    if (node.type === "BlockStatement" /* BlockStatement */ && node.body.length === 0) {
      const innerComments = [];
      for (let i = this.leading.length - 1; i >= 0; --i) {
        const entry = this.leading[i];
        if (metadata.end.offset >= entry.start) {
          innerComments.unshift(entry.comment);
          this.leading.splice(i, 1);
          this.trailing.splice(i, 1);
        }
      }
      if (innerComments.length) {
        node.innerComments = innerComments;
      }
    }
  }
  findTrailingComments(metadata) {
    let trailingComments = [];
    if (this.trailing.length > 0) {
      for (let i = this.trailing.length - 1; i >= 0; --i) {
        const entry = this.trailing[i];
        if (entry.start >= metadata.end.offset) {
          trailingComments.unshift(entry.comment);
        }
      }
      this.trailing.length = 0;
      return trailingComments;
    }
    const last = this.stack[this.stack.length - 1];
    if (last && last.node.trailingComments) {
      const firstComment = last.node.trailingComments[0];
      if (firstComment && firstComment.range[0] >= metadata.end.offset) {
        trailingComments = last.node.trailingComments;
        delete last.node.trailingComments;
      }
    }
    return trailingComments;
  }
  findLeadingComments(metadata) {
    const leadingComments = [];
    let target;
    while (this.stack.length > 0) {
      const entry = this.stack[this.stack.length - 1];
      if (entry && entry.start >= metadata.start.offset) {
        target = entry.node;
        this.stack.pop();
      } else {
        break;
      }
    }
    if (target) {
      const count = target.leadingComments ? target.leadingComments.length : 0;
      for (let i = count - 1; i >= 0; --i) {
        const comment = target.leadingComments[i];
        if (comment.range[1] <= metadata.start.offset) {
          leadingComments.unshift(comment);
          target.leadingComments.splice(i, 1);
        }
      }
      if (target.leadingComments && target.leadingComments.length === 0) {
        delete target.leadingComments;
      }
      return leadingComments;
    }
    for (let i = this.leading.length - 1; i >= 0; --i) {
      const entry = this.leading[i];
      if (entry.start <= metadata.start.offset) {
        leadingComments.unshift(entry.comment);
        this.leading.splice(i, 1);
      }
    }
    return leadingComments;
  }
  visitNode(node, metadata) {
    if (node.type === "Program" /* Program */ && node.body.length > 0) {
      return;
    }
    this.insertInnerComments(node, metadata);
    const trailingComments = this.findTrailingComments(metadata);
    const leadingComments = this.findLeadingComments(metadata);
    if (leadingComments.length > 0) {
      node.leadingComments = leadingComments;
    }
    if (trailingComments.length > 0) {
      node.trailingComments = trailingComments;
    }
    this.stack.push({
      node,
      start: metadata.start.offset
    });
  }
  visitComment(node, metadata) {
    const type = node.type[0] === "L" ? "Line" : "Block";
    const comment = {
      type,
      value: node.value
    };
    if (node.range) {
      comment.range = node.range;
    }
    if (node.loc) {
      comment.loc = node.loc;
    }
    this.comments.push(comment);
    if (this.attach) {
      const entry = {
        comment: {
          type,
          value: node.value,
          range: [metadata.start.offset, metadata.end.offset]
        },
        start: metadata.start.offset
      };
      if (node.loc) {
        entry.comment.loc = node.loc;
      }
      node.type = type;
      this.leading.push(entry);
      this.trailing.push(entry);
    }
  }
  visit(node, metadata) {
    if (node.type === "LineComment") {
      this.visitComment(node, metadata);
    } else if (node.type === "BlockComment") {
      this.visitComment(node, metadata);
    } else if (this.attach) {
      this.visitNode(node, metadata);
    }
  }
};

// src/character.ts
var Regex = {
  // Unicode v12.1.0 NonAsciiIdentifierStart:
  NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7C6\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB67\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD23\uDF00-\uDF1C\uDF27\uDF30-\uDF45\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD44\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC5F\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDEB8\uDF00-\uDF1A]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCDF\uDCFF\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDEE0-\uDEF2]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD4E\uDEC0-\uDEEB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43\uDD4B]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/,
  // Unicode v12.1.0 NonAsciiIdentifierPart:
  // eslint-disable-next-line no-misleading-character-class
  NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05EF-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u07FD\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D3-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u09FE\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1878\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CD0-\u1CD2\u1CD4-\u1CFA\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEF\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7C6\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB67\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDD00-\uDD27\uDD30-\uDD39\uDF00-\uDF1C\uDF27\uDF30-\uDF50\uDFE0-\uDFF6]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD44-\uDD46\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDC9-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3B-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC5E\uDC5F\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDC00-\uDC3A\uDCA0-\uDCE9\uDCFF\uDDA0-\uDDA7\uDDAA-\uDDD7\uDDDA-\uDDE1\uDDE3\uDDE4\uDE00-\uDE3E\uDE47\uDE50-\uDE99\uDE9D\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD8E\uDD90\uDD91\uDD93-\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF6]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE7F\uDF00-\uDF4A\uDF4F-\uDF87\uDF8F-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A\uDD00-\uDD2C\uDD30-\uDD3D\uDD40-\uDD49\uDD4E\uDEC0-\uDEF9]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4B\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
};
var Character = {
  fromCodePoint(cp) {
    return cp < 65536 ? String.fromCharCode(cp) : String.fromCharCode(55296 + (cp - 65536 >> 10)) + String.fromCharCode(56320 + (cp - 65536 & 1023));
  },
  isStringWellFormedUnicode(text) {
    for (let i = 0; i < text.length; i++) {
      let c = text.charCodeAt(i);
      if (c >= 55296 && c <= 56319) {
        if (i === text.length - 1) {
          return false;
        }
        i++;
        c = text.charCodeAt(i);
        if (c < 56320 && c > 57343) {
          return false;
        }
      } else if (c >= 56320 && c <= 57343) {
        return false;
      }
    }
    return true;
  },
  // https://tc39.github.io/ecma262/#sec-white-space
  isWhiteSpace(cp) {
    return cp === 32 || cp === 9 || cp === 11 || cp === 12 || cp === 160 || cp >= 5760 && [5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279].indexOf(cp) >= 0;
  },
  // https://tc39.github.io/ecma262/#sec-line-terminators
  isLineTerminator(cp) {
    return cp === 10 || cp === 13 || cp === 8232 || cp === 8233;
  },
  // https://tc39.github.io/ecma262/#sec-names-and-keywords
  isIdentifierStart(cp) {
    return cp === 36 || cp === 95 || // $ (dollar) and _ (underscore)
    cp >= 65 && cp <= 90 || // A..Z
    cp >= 97 && cp <= 122 || // a..z
    cp === 92 || // \ (backslash)
    cp >= 128 && Regex.NonAsciiIdentifierStart.test(Character.fromCodePoint(cp));
  },
  isIdentifierPart(cp) {
    return cp === 36 || cp === 95 || // $ (dollar) and _ (underscore)
    cp >= 65 && cp <= 90 || // A..Z
    cp >= 97 && cp <= 122 || // a..z
    cp >= 48 && cp <= 57 || // 0..9
    cp === 92 || // \ (backslash)
    cp >= 128 && Regex.NonAsciiIdentifierPart.test(Character.fromCodePoint(cp));
  },
  // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
  isDecimalDigit(cp) {
    return cp >= 48 && cp <= 57;
  },
  isDecimalDigitChar(ch) {
    return ch.length === 1 && Character.isDecimalDigit(ch.charCodeAt(0));
  },
  isHexDigit(cp) {
    return cp >= 48 && cp <= 57 || // 0..9
    cp >= 65 && cp <= 70 || // A..F
    cp >= 97 && cp <= 102;
  },
  isHexDigitChar(ch) {
    return ch.length === 1 && Character.isHexDigit(ch.charCodeAt(0));
  },
  isOctalDigit(cp) {
    return cp >= 48 && cp <= 55;
  },
  isOctalDigitChar(ch) {
    return ch.length === 1 && Character.isOctalDigit(ch.charCodeAt(0));
  }
};

// src/jsx-nodes.ts
var JSXClosingElement = class {
  type;
  name;
  constructor(name) {
    this.type = "JSXClosingElement" /* JSXClosingElement */;
    this.name = name;
  }
};
var JSXClosingFragment = class {
  type;
  constructor() {
    this.type = "JSXClosingFragment" /* JSXClosingFragment */;
  }
};
var JSXElement = class {
  type;
  openingElement;
  children;
  closingElement;
  constructor(openingElement, children, closingElement) {
    this.type = "JSXElement" /* JSXElement */;
    this.openingElement = openingElement;
    this.children = children;
    this.closingElement = closingElement;
  }
};
var JSXEmptyExpression = class {
  type;
  constructor() {
    this.type = "JSXEmptyExpression" /* JSXEmptyExpression */;
  }
};
var JSXExpressionContainer = class {
  type;
  expression;
  constructor(expression) {
    this.type = "JSXExpressionContainer" /* JSXExpressionContainer */;
    this.expression = expression;
  }
};
var JSXIdentifier = class {
  type;
  name;
  constructor(name) {
    this.type = "JSXIdentifier" /* JSXIdentifier */;
    this.name = name;
  }
};
var JSXMemberExpression = class {
  type;
  object;
  property;
  constructor(object, property) {
    this.type = "JSXMemberExpression" /* JSXMemberExpression */;
    this.object = object;
    this.property = property;
  }
};
var JSXAttribute = class {
  type;
  name;
  value;
  constructor(name, value) {
    this.type = "JSXAttribute" /* JSXAttribute */;
    this.name = name;
    this.value = value;
  }
};
var JSXNamespacedName = class {
  type;
  namespace;
  name;
  constructor(namespace, name) {
    this.type = "JSXNamespacedName" /* JSXNamespacedName */;
    this.namespace = namespace;
    this.name = name;
  }
};
var JSXOpeningElement = class {
  type;
  name;
  selfClosing;
  attributes;
  constructor(name, selfClosing, attributes) {
    this.type = "JSXOpeningElement" /* JSXOpeningElement */;
    this.name = name;
    this.selfClosing = selfClosing;
    this.attributes = attributes;
  }
};
var JSXOpeningFragment = class {
  type;
  selfClosing;
  constructor(selfClosing) {
    this.type = "JSXOpeningFragment" /* JSXOpeningFragment */;
    this.selfClosing = selfClosing;
  }
};
var JSXSpreadAttribute = class {
  type;
  argument;
  constructor(argument) {
    this.type = "JSXSpreadAttribute" /* JSXSpreadAttribute */;
    this.argument = argument;
  }
};
var JSXText = class {
  type;
  value;
  raw;
  constructor(value, raw) {
    this.type = "JSXText" /* JSXText */;
    this.value = value;
    this.raw = raw;
  }
};

// src/nodes.ts
var nodes_exports = {};
__export(nodes_exports, {
  ArrayExpression: () => ArrayExpression,
  ArrayPattern: () => ArrayPattern,
  ArrowFunctionExpression: () => ArrowFunctionExpression,
  AssignmentExpression: () => AssignmentExpression,
  AssignmentPattern: () => AssignmentPattern,
  AsyncFunctionDeclaration: () => AsyncFunctionDeclaration,
  AwaitExpression: () => AwaitExpression,
  BigIntLiteral: () => BigIntLiteral,
  BinaryExpression: () => BinaryExpression,
  BlockStatement: () => BlockStatement,
  BreakStatement: () => BreakStatement,
  CallExpression: () => CallExpression,
  CatchClause: () => CatchClause,
  ChainExpression: () => ChainExpression,
  ClassBody: () => ClassBody,
  ClassDeclaration: () => ClassDeclaration,
  ClassExpression: () => ClassExpression,
  ConditionalExpression: () => ConditionalExpression,
  ContinueStatement: () => ContinueStatement,
  DebuggerStatement: () => DebuggerStatement,
  Decorator: () => Decorator,
  Directive: () => Directive,
  DoWhileStatement: () => DoWhileStatement,
  EmptyStatement: () => EmptyStatement,
  ExportAllDeclaration: () => ExportAllDeclaration,
  ExportDefaultDeclaration: () => ExportDefaultDeclaration,
  ExportNamedDeclaration: () => ExportNamedDeclaration,
  ExportSpecifier: () => ExportSpecifier,
  ExpressionStatement: () => ExpressionStatement,
  ForInStatement: () => ForInStatement,
  ForOfStatement: () => ForOfStatement,
  ForStatement: () => ForStatement,
  FunctionDeclaration: () => FunctionDeclaration,
  FunctionExpression: () => FunctionExpression,
  Identifier: () => Identifier,
  IfStatement: () => IfStatement,
  ImportAttribute: () => ImportAttribute,
  ImportDeclaration: () => ImportDeclaration,
  ImportDefaultSpecifier: () => ImportDefaultSpecifier,
  ImportExpression: () => ImportExpression,
  ImportNamespaceSpecifier: () => ImportNamespaceSpecifier,
  ImportSpecifier: () => ImportSpecifier,
  LabeledStatement: () => LabeledStatement,
  Literal: () => Literal,
  LogicalExpression: () => LogicalExpression,
  MemberExpression: () => MemberExpression,
  MetaProperty: () => MetaProperty,
  MethodDefinition: () => MethodDefinition,
  Module: () => Module,
  NewExpression: () => NewExpression,
  ObjectExpression: () => ObjectExpression,
  ObjectPattern: () => ObjectPattern,
  PrivateIdentifier: () => PrivateIdentifier,
  Program: () => Program,
  Property: () => Property,
  PropertyDefinition: () => PropertyDefinition,
  RegexLiteral: () => RegexLiteral,
  RestElement: () => RestElement,
  ReturnStatement: () => ReturnStatement,
  Script: () => Script,
  SequenceExpression: () => SequenceExpression,
  SpreadElement: () => SpreadElement,
  StaticBlock: () => StaticBlock,
  Super: () => Super,
  SwitchCase: () => SwitchCase,
  SwitchStatement: () => SwitchStatement,
  TaggedTemplateExpression: () => TaggedTemplateExpression,
  TemplateElement: () => TemplateElement,
  TemplateLiteral: () => TemplateLiteral,
  ThisExpression: () => ThisExpression,
  ThrowStatement: () => ThrowStatement,
  TryStatement: () => TryStatement,
  UnaryExpression: () => UnaryExpression,
  UpdateExpression: () => UpdateExpression,
  VariableDeclaration: () => VariableDeclaration,
  VariableDeclarator: () => VariableDeclarator,
  WhileStatement: () => WhileStatement,
  WithStatement: () => WithStatement,
  YieldExpression: () => YieldExpression
});
var ArrayExpression = class {
  type;
  elements;
  constructor(elements) {
    this.type = "ArrayExpression" /* ArrayExpression */;
    this.elements = elements;
  }
};
var ArrayPattern = class {
  type;
  elements;
  constructor(elements) {
    this.type = "ArrayPattern" /* ArrayPattern */;
    this.elements = elements;
  }
};
var ArrowFunctionExpression = class {
  type;
  id;
  params;
  body;
  generator;
  expression;
  async;
  constructor(params, body, expression, isAsync) {
    this.type = "ArrowFunctionExpression" /* ArrowFunctionExpression */;
    this.id = null;
    this.params = params;
    this.body = body;
    this.generator = false;
    this.expression = expression;
    this.async = isAsync;
  }
};
var AssignmentExpression = class {
  type;
  operator;
  left;
  right;
  constructor(operator, left, right) {
    this.type = "AssignmentExpression" /* AssignmentExpression */;
    this.operator = operator;
    this.left = left;
    this.right = right;
  }
};
var AssignmentPattern = class {
  type;
  left;
  right;
  constructor(left, right) {
    this.type = "AssignmentPattern" /* AssignmentPattern */;
    this.left = left;
    this.right = right;
  }
};
var AsyncFunctionDeclaration = class {
  type;
  id;
  params;
  body;
  generator;
  expression;
  async;
  constructor(id, params, body, generator) {
    this.type = "FunctionDeclaration" /* FunctionDeclaration */;
    this.id = id;
    this.params = params;
    this.body = body;
    this.generator = generator;
    this.expression = false;
    this.async = true;
  }
};
var AwaitExpression = class {
  type;
  argument;
  constructor(argument) {
    this.type = "AwaitExpression" /* AwaitExpression */;
    this.argument = argument;
  }
};
var BigIntLiteral = class {
  type;
  value;
  raw;
  bigint;
  constructor(value, raw, bigint) {
    this.type = "Literal" /* Literal */;
    this.value = value;
    this.raw = raw;
    this.bigint = bigint;
  }
};
var BinaryExpression = class {
  type;
  operator;
  left;
  right;
  constructor(operator, left, right) {
    this.type = "BinaryExpression" /* BinaryExpression */;
    this.operator = operator;
    this.left = left;
    this.right = right;
  }
};
var BlockStatement = class {
  type;
  body;
  constructor(body) {
    this.type = "BlockStatement" /* BlockStatement */;
    this.body = body;
  }
};
var BreakStatement = class {
  type;
  label;
  constructor(label) {
    this.type = "BreakStatement" /* BreakStatement */;
    this.label = label;
  }
};
var CallExpression = class {
  type;
  callee;
  arguments;
  optional;
  constructor(callee, args, optional) {
    this.type = "CallExpression" /* CallExpression */;
    this.callee = callee;
    this.arguments = args;
    this.optional = optional;
  }
};
var CatchClause = class {
  type;
  param;
  body;
  constructor(param, body) {
    this.type = "CatchClause" /* CatchClause */;
    this.param = param;
    this.body = body;
  }
};
var ChainExpression = class {
  type;
  expression;
  constructor(expression) {
    this.type = "ChainExpression" /* ChainExpression */;
    this.expression = expression;
  }
};
var ClassBody = class {
  type;
  body;
  constructor(body) {
    this.type = "ClassBody" /* ClassBody */;
    this.body = body;
  }
};
var ClassDeclaration = class {
  type;
  id;
  superClass;
  body;
  decorators;
  constructor(id, superClass, body, decorators) {
    this.type = "ClassDeclaration" /* ClassDeclaration */;
    this.id = id;
    this.superClass = superClass;
    this.body = body;
    this.decorators = decorators;
  }
};
var ClassExpression = class {
  type;
  id;
  superClass;
  body;
  decorators;
  constructor(id, superClass, body, decorators) {
    this.type = "ClassExpression" /* ClassExpression */;
    this.id = id;
    this.superClass = superClass;
    this.body = body;
    this.decorators = decorators;
  }
};
var ConditionalExpression = class {
  type;
  test;
  consequent;
  alternate;
  constructor(test, consequent, alternate) {
    this.type = "ConditionalExpression" /* ConditionalExpression */;
    this.test = test;
    this.consequent = consequent;
    this.alternate = alternate;
  }
};
var ContinueStatement = class {
  type;
  label;
  constructor(label) {
    this.type = "ContinueStatement" /* ContinueStatement */;
    this.label = label;
  }
};
var DebuggerStatement = class {
  type;
  constructor() {
    this.type = "DebuggerStatement" /* DebuggerStatement */;
  }
};
var Decorator = class {
  type;
  expression;
  constructor(expression) {
    this.type = "Decorator" /* Decorator */;
    this.expression = expression;
  }
};
var Directive = class {
  type;
  expression;
  directive;
  constructor(expression, directive) {
    this.type = "ExpressionStatement" /* ExpressionStatement */;
    this.expression = expression;
    this.directive = directive;
  }
};
var DoWhileStatement = class {
  type;
  body;
  test;
  constructor(body, test) {
    this.type = "DoWhileStatement" /* DoWhileStatement */;
    this.body = body;
    this.test = test;
  }
};
var EmptyStatement = class {
  type;
  constructor() {
    this.type = "EmptyStatement" /* EmptyStatement */;
  }
};
var ExportAllDeclaration = class {
  type;
  source;
  exported;
  assertions;
  constructor(source, exported, assertions) {
    this.type = "ExportAllDeclaration" /* ExportAllDeclaration */;
    this.source = source;
    this.exported = exported;
    this.assertions = assertions;
  }
};
var ExportDefaultDeclaration = class {
  type;
  declaration;
  constructor(declaration) {
    this.type = "ExportDefaultDeclaration" /* ExportDefaultDeclaration */;
    this.declaration = declaration;
  }
};
var ExportNamedDeclaration = class {
  type;
  declaration;
  specifiers;
  source;
  assertions;
  constructor(declaration, specifiers, source, assertions) {
    this.type = "ExportNamedDeclaration" /* ExportNamedDeclaration */;
    this.declaration = declaration;
    this.specifiers = specifiers;
    this.source = source;
    this.assertions = assertions;
  }
};
var ExportSpecifier = class {
  type;
  exported;
  local;
  constructor(local, exported) {
    this.type = "ExportSpecifier" /* ExportSpecifier */;
    this.exported = exported;
    this.local = local;
  }
};
var ExpressionStatement = class {
  type;
  expression;
  constructor(expression) {
    this.type = "ExpressionStatement" /* ExpressionStatement */;
    this.expression = expression;
  }
};
var ForInStatement = class {
  type;
  left;
  right;
  body;
  each;
  constructor(left, right, body) {
    this.type = "ForInStatement" /* ForInStatement */;
    this.left = left;
    this.right = right;
    this.body = body;
    this.each = false;
  }
};
var ForOfStatement = class {
  type;
  await;
  left;
  right;
  body;
  constructor(left, right, body, _await) {
    this.type = "ForOfStatement" /* ForOfStatement */;
    this.await = _await;
    this.left = left;
    this.right = right;
    this.body = body;
  }
};
var ForStatement = class {
  type;
  init;
  test;
  update;
  body;
  constructor(init, test, update, body) {
    this.type = "ForStatement" /* ForStatement */;
    this.init = init;
    this.test = test;
    this.update = update;
    this.body = body;
  }
};
var FunctionDeclaration = class {
  type;
  id;
  params;
  body;
  generator;
  expression;
  async;
  constructor(id, params, body, generator) {
    this.type = "FunctionDeclaration" /* FunctionDeclaration */;
    this.id = id;
    this.params = params;
    this.body = body;
    this.generator = generator;
    this.expression = false;
    this.async = false;
  }
};
var FunctionExpression = class {
  type;
  id;
  params;
  body;
  generator;
  expression;
  async;
  constructor(id, params, body, generator, isAsync) {
    this.type = "FunctionExpression" /* FunctionExpression */;
    this.id = id;
    this.params = params;
    this.body = body;
    this.generator = generator;
    this.expression = false;
    this.async = isAsync;
  }
};
var Identifier = class {
  type;
  name;
  constructor(name) {
    this.type = "Identifier" /* Identifier */;
    this.name = name;
  }
};
var IfStatement = class {
  type;
  test;
  consequent;
  alternate;
  constructor(test, consequent, alternate) {
    this.type = "IfStatement" /* IfStatement */;
    this.test = test;
    this.consequent = consequent;
    this.alternate = alternate;
  }
};
var ImportAttribute = class {
  type;
  key;
  value;
  constructor(key, value) {
    this.type = "ImportAttribute" /* ImportAttribute */;
    this.key = key;
    this.value = value;
  }
};
var ImportExpression = class {
  type;
  source;
  attributes;
  constructor(source, attributes) {
    this.type = "ImportExpression" /* ImportExpression */;
    this.source = source;
    this.attributes = attributes;
  }
};
var ImportDeclaration = class {
  type;
  specifiers;
  source;
  assertions;
  constructor(specifiers, source, assertions) {
    this.type = "ImportDeclaration" /* ImportDeclaration */;
    this.specifiers = specifiers;
    this.source = source;
    this.assertions = assertions;
  }
};
var ImportDefaultSpecifier = class {
  type;
  local;
  constructor(local) {
    this.type = "ImportDefaultSpecifier" /* ImportDefaultSpecifier */;
    this.local = local;
  }
};
var ImportNamespaceSpecifier = class {
  type;
  local;
  constructor(local) {
    this.type = "ImportNamespaceSpecifier" /* ImportNamespaceSpecifier */;
    this.local = local;
  }
};
var ImportSpecifier = class {
  type;
  local;
  imported;
  constructor(local, imported) {
    this.type = "ImportSpecifier" /* ImportSpecifier */;
    this.local = local;
    this.imported = imported;
  }
};
var LabeledStatement = class {
  type;
  label;
  body;
  constructor(label, body) {
    this.type = "LabeledStatement" /* LabeledStatement */;
    this.label = label;
    this.body = body;
  }
};
var Literal = class {
  type;
  value;
  raw;
  constructor(value, raw) {
    this.type = "Literal" /* Literal */;
    this.value = value;
    this.raw = raw;
  }
};
var LogicalExpression = class {
  type;
  operator;
  left;
  right;
  constructor(operator, left, right) {
    this.type = "LogicalExpression" /* LogicalExpression */;
    this.operator = operator;
    this.left = left;
    this.right = right;
  }
};
var MemberExpression = class {
  type;
  computed;
  object;
  property;
  optional;
  constructor(computed, object, property, optional) {
    this.type = "MemberExpression" /* MemberExpression */;
    this.computed = computed;
    this.object = object;
    this.property = property;
    this.optional = optional;
  }
};
var MetaProperty = class {
  type;
  meta;
  property;
  constructor(meta, property) {
    this.type = "MetaProperty" /* MetaProperty */;
    this.meta = meta;
    this.property = property;
  }
};
var MethodDefinition = class {
  type;
  key;
  computed;
  value;
  kind;
  static;
  decorators;
  constructor(key, computed, value, kind, isStatic, decorators) {
    this.type = "MethodDefinition" /* MethodDefinition */;
    this.key = key;
    this.computed = computed;
    this.value = value;
    this.kind = kind;
    this.static = isStatic;
    this.decorators = decorators;
  }
};
var Module = class {
  type;
  body;
  sourceType;
  constructor(body) {
    this.type = "Program" /* Program */;
    this.body = body;
    this.sourceType = "module";
  }
};
var NewExpression = class {
  type;
  callee;
  arguments;
  constructor(callee, args) {
    this.type = "NewExpression" /* NewExpression */;
    this.callee = callee;
    this.arguments = args;
  }
};
var ObjectExpression = class {
  type;
  properties;
  constructor(properties) {
    this.type = "ObjectExpression" /* ObjectExpression */;
    this.properties = properties;
  }
};
var ObjectPattern = class {
  type;
  properties;
  constructor(properties) {
    this.type = "ObjectPattern" /* ObjectPattern */;
    this.properties = properties;
  }
};
var PrivateIdentifier = class {
  type;
  name;
  constructor(name) {
    this.type = "PrivateIdentifier" /* PrivateIdentifier */;
    this.name = name;
  }
};
var Program = class {
  type;
  body;
  sourceType;
  constructor(sourceType, body) {
    this.type = "Program" /* Program */;
    this.sourceType = sourceType;
    this.body = body;
  }
};
var Property = class {
  type;
  key;
  computed;
  value;
  kind;
  method;
  shorthand;
  constructor(kind, key, computed, value, method, shorthand) {
    this.type = "Property" /* Property */;
    this.key = key;
    this.computed = computed;
    this.value = value;
    this.kind = kind;
    this.method = method;
    this.shorthand = shorthand;
  }
};
var PropertyDefinition = class {
  type;
  key;
  computed;
  value;
  static;
  decorators;
  constructor(key, computed, value, isStatic, decorators) {
    this.type = "Property" /* Property */;
    this.key = key;
    this.computed = computed;
    this.value = value;
    this.static = isStatic;
    this.decorators = decorators;
  }
};
var RegexLiteral = class {
  type;
  value;
  raw;
  regex;
  constructor(value, raw, pattern, flags) {
    this.type = "Literal" /* Literal */;
    this.value = value;
    this.raw = raw;
    this.regex = { pattern, flags };
  }
};
var RestElement = class {
  type;
  argument;
  constructor(argument) {
    this.type = "RestElement" /* RestElement */;
    this.argument = argument;
  }
};
var ReturnStatement = class {
  type;
  argument;
  constructor(argument) {
    this.type = "ReturnStatement" /* ReturnStatement */;
    this.argument = argument;
  }
};
var Script = class {
  type;
  body;
  sourceType;
  constructor(body) {
    this.type = "Program" /* Program */;
    this.body = body;
    this.sourceType = "script";
  }
};
var SequenceExpression = class {
  type;
  expressions;
  constructor(expressions) {
    this.type = "SequenceExpression" /* SequenceExpression */;
    this.expressions = expressions;
  }
};
var SpreadElement = class {
  type;
  argument;
  constructor(argument) {
    this.type = "SpreadElement" /* SpreadElement */;
    this.argument = argument;
  }
};
var StaticBlock = class {
  type;
  body;
  constructor(body) {
    this.type = "StaticBlock" /* StaticBlock */;
    this.body = body;
  }
};
var Super = class {
  type;
  constructor() {
    this.type = "Super" /* Super */;
  }
};
var SwitchCase = class {
  type;
  test;
  consequent;
  constructor(test, consequent) {
    this.type = "SwitchCase" /* SwitchCase */;
    this.test = test;
    this.consequent = consequent;
  }
};
var SwitchStatement = class {
  type;
  discriminant;
  cases;
  constructor(discriminant, cases) {
    this.type = "SwitchStatement" /* SwitchStatement */;
    this.discriminant = discriminant;
    this.cases = cases;
  }
};
var TaggedTemplateExpression = class {
  type;
  tag;
  quasi;
  constructor(tag, quasi) {
    this.type = "TaggedTemplateExpression" /* TaggedTemplateExpression */;
    this.tag = tag;
    this.quasi = quasi;
  }
};
var TemplateElement = class {
  type;
  value;
  tail;
  constructor(value, tail) {
    this.type = "TemplateElement" /* TemplateElement */;
    this.value = value;
    this.tail = tail;
  }
};
var TemplateLiteral = class {
  type;
  quasis;
  expressions;
  constructor(quasis, expressions) {
    this.type = "TemplateLiteral" /* TemplateLiteral */;
    this.quasis = quasis;
    this.expressions = expressions;
  }
};
var ThisExpression = class {
  type;
  constructor() {
    this.type = "ThisExpression" /* ThisExpression */;
  }
};
var ThrowStatement = class {
  type;
  argument;
  constructor(argument) {
    this.type = "ThrowStatement" /* ThrowStatement */;
    this.argument = argument;
  }
};
var TryStatement = class {
  type;
  block;
  handler;
  finalizer;
  constructor(block, handler, finalizer) {
    this.type = "TryStatement" /* TryStatement */;
    this.block = block;
    this.handler = handler;
    this.finalizer = finalizer;
  }
};
var UnaryExpression = class {
  type;
  operator;
  argument;
  prefix;
  constructor(operator, argument) {
    this.type = "UnaryExpression" /* UnaryExpression */;
    this.operator = operator;
    this.argument = argument;
    this.prefix = true;
  }
};
var UpdateExpression = class {
  type;
  operator;
  argument;
  prefix;
  constructor(operator, argument, prefix) {
    this.type = "UpdateExpression" /* UpdateExpression */;
    this.operator = operator;
    this.argument = argument;
    this.prefix = prefix;
  }
};
var VariableDeclaration = class {
  type;
  declarations;
  kind;
  constructor(declarations, kind) {
    this.type = "VariableDeclaration" /* VariableDeclaration */;
    this.declarations = declarations;
    this.kind = kind;
  }
};
var VariableDeclarator = class {
  type;
  id;
  init;
  constructor(id, init) {
    this.type = "VariableDeclarator" /* VariableDeclarator */;
    this.id = id;
    this.init = init;
  }
};
var WhileStatement = class {
  type;
  test;
  body;
  constructor(test, body) {
    this.type = "WhileStatement" /* WhileStatement */;
    this.test = test;
    this.body = body;
  }
};
var WithStatement = class {
  type;
  object;
  body;
  constructor(object, body) {
    this.type = "WithStatement" /* WithStatement */;
    this.object = object;
    this.body = body;
  }
};
var YieldExpression = class {
  type;
  argument;
  delegate;
  constructor(argument, delegate) {
    this.type = "YieldExpression" /* YieldExpression */;
    this.argument = argument;
    this.delegate = delegate;
  }
};

// src/assert.ts
function assert(condition, message) {
  if (!condition) {
    throw new Error("ASSERT: " + message);
  }
}

// src/error-handler.ts
var ErrorHandler = class {
  errors;
  tolerant;
  constructor() {
    this.errors = [];
    this.tolerant = false;
  }
  recordError(error) {
    this.errors.push(error);
  }
  tolerate(error) {
    if (this.tolerant) {
      this.recordError(error);
    } else {
      throw error;
    }
  }
  constructError(msg, column) {
    let error = new Error(msg);
    try {
      throw error;
    } catch (base) {
      if (Object.create && Object.defineProperty) {
        error = Object.create(base);
        Object.defineProperty(error, "column", { value: column });
      }
    }
    return error;
  }
  createError(index, line, col, description) {
    const msg = "Line " + line + ": " + description;
    const _error = this.constructError(msg, col);
    _error.index = index;
    _error.lineNumber = line;
    _error.description = description;
    const error = _error;
    return error;
  }
  throwError(index, line, col, description) {
    throw this.createError(index, line, col, description);
  }
  tolerateError(index, line, col, description) {
    const error = this.createError(index, line, col, description);
    if (this.tolerant) {
      this.recordError(error);
    } else {
      throw error;
    }
  }
};

// src/messages.ts
var Messages = {
  AsyncFunctionInSingleStatementContext: "Async functions can only be declared at the top level or inside a block.",
  BadImportCallArity: "Unexpected token",
  BadGetterArity: "Getter must not have any formal parameters",
  BadSetterArity: "Setter must have exactly one formal parameter",
  BadSetterRestParameter: "Setter function argument must not be a rest parameter",
  CannotUseImportMetaOutsideAModule: "Cannot use 'import.meta' outside a module",
  ConstructorIsAsync: "Class constructor may not be an async method",
  ConstructorIsPrivate: "Class constructor may not be a private method",
  ConstructorSpecialMethod: "Class constructor may not be an accessor",
  DeclarationMissingInitializer: "Missing initializer in %0 declaration",
  DefaultRestParameter: "Unexpected token =",
  DefaultRestProperty: "Unexpected token =",
  DuplicateBinding: "Duplicate binding %0",
  DuplicateConstructor: "A class may only have one constructor",
  DuplicateParameter: "Duplicate parameter name not allowed in this context",
  DuplicateProtoProperty: "Duplicate __proto__ fields are not allowed in object literals",
  ForInOfLoopInitializer: "%0 loop variable declaration may not have an initializer",
  GeneratorInLegacyContext: "Generator declarations are not allowed in legacy contexts",
  IllegalBreak: "Illegal break statement",
  IllegalContinue: "Illegal continue statement",
  IllegalExportDeclaration: "Unexpected token",
  IllegalImportDeclaration: "Unexpected token",
  IllegalLanguageModeDirective: "Illegal 'use strict' directive in function with non-simple parameter list",
  IllegalReturn: "Illegal return statement",
  InvalidEscapedReservedWord: "Keyword must not contain escaped characters",
  InvalidHexEscapeSequence: "Invalid hexadecimal escape sequence",
  InvalidLHSInAssignment: "Invalid left-hand side in assignment",
  InvalidLHSInForIn: "Invalid left-hand side in for-in",
  InvalidLHSInForLoop: "Invalid left-hand side in for-loop",
  InvalidModuleSpecifier: "Unexpected token",
  InvalidRegExp: "Invalid regular expression",
  InvalidTaggedTemplateOnOptionalChain: "Invalid tagged template on optional chain",
  InvalidUnicodeEscapeSequence: "Invalid Unicode escape sequence",
  LetInLexicalBinding: "let is disallowed as a lexically bound name",
  MissingFromClause: "Unexpected token",
  MultipleDefaultsInSwitch: "More than one default clause in switch statement",
  NewlineAfterThrow: "Illegal newline after throw",
  NoAsAfterImportNamespace: "Unexpected token",
  NoAsAndFromEscapeSequences: "The `as` and `from` contextual keywords must not contain Unicode escape sequences.",
  NoCatchOrFinally: "Missing catch or finally after try",
  NoSemicolonAfterDecorator: "Decorators must not be followed by a semicolon.",
  NumericSeperatorOneUnderscore: "Numeric separator must be exactly one underscore",
  NumericSeperatorNotAllowedHere: "Numeric separator is not allowed here",
  ParameterAfterRestParameter: "Rest parameter must be last formal parameter",
  PropertyAfterRestProperty: "Unexpected token",
  Redeclaration: "%0 '%1' has already been declared",
  StaticPrototype: "Classes may not have static property named prototype",
  StrictCatchVariable: "Catch variable may not be eval or arguments in strict mode",
  StrictDelete: "Delete of an unqualified identifier in strict mode.",
  StrictFunction: "In strict mode code, functions can only be declared at top level or inside a block",
  StrictFunctionName: "Function name may not be eval or arguments in strict mode",
  StrictLHSAssignment: "Assignment to eval or arguments is not allowed in strict mode",
  StrictLHSPostfix: "Postfix increment/decrement may not have eval or arguments operand in strict mode",
  StrictLHSPrefix: "Prefix increment/decrement may not have eval or arguments operand in strict mode",
  StrictModeWith: "Strict mode code may not include a with statement",
  StrictOctalLiteral: "Octal literals are not allowed in strict mode.",
  StrictParamName: "Parameter name eval or arguments is not allowed in strict mode",
  StrictReservedWord: "Use of future reserved word in strict mode",
  StrictVarName: "Variable name may not be eval or arguments in strict mode",
  TemplateOctalLiteral: "Octal literals are not allowed in template strings.",
  TemplateEscape89: "\\8 and \\9 are not allowed in template strings.",
  UnexpectedEOS: "Unexpected end of input",
  UnexpectedIdentifier: "Unexpected identifier",
  UnexpectedNumber: "Unexpected number",
  UnexpectedReserved: "Unexpected reserved word",
  UnexpectedString: "Unexpected string",
  UnexpectedSuper: "'super' keyword unexpected here",
  UnexpectedTemplate: "Unexpected quasi %0",
  UnexpectedToken: "Unexpected token %0",
  UnexpectedTokenIllegal: "Unexpected token ILLEGAL",
  UnknownLabel: "Undefined label '%0'",
  UnterminatedRegExp: "Invalid regular expression: missing /"
};

// src/token.ts
var TokenName = {};
TokenName[1 /* BooleanLiteral */] = "Boolean";
TokenName[2 /* EOF */] = "<end>";
TokenName[3 /* Identifier */] = "Identifier";
TokenName[4 /* Keyword */] = "Keyword";
TokenName[5 /* NullLiteral */] = "Null";
TokenName[6 /* NumericLiteral */] = "Numeric";
TokenName[7 /* Punctuator */] = "Punctuator";
TokenName[8 /* StringLiteral */] = "String";
TokenName[9 /* RegularExpression */] = "RegularExpression";
TokenName[10 /* Template */] = "Template";

// src/scanner.ts
function hexValue(ch) {
  return "0123456789abcdef".indexOf(ch.toLowerCase());
}
function octalValue(ch) {
  return "01234567".indexOf(ch);
}
var Scanner = class {
  source;
  errorHandler;
  trackComment;
  isModule;
  index;
  lineNumber;
  lineStart;
  curlyStack;
  length;
  constructor(code, handler) {
    this.source = code;
    this.errorHandler = handler;
    this.trackComment = false;
    this.isModule = false;
    this.length = code.length;
    this.index = 0;
    this.lineNumber = code.length > 0 ? 1 : 0;
    this.lineStart = 0;
    this.curlyStack = [];
  }
  saveState() {
    return {
      index: this.index,
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      curlyStack: this.curlyStack.slice()
    };
  }
  restoreState(state) {
    this.index = state.index;
    this.lineNumber = state.lineNumber;
    this.lineStart = state.lineStart;
    this.curlyStack = state.curlyStack;
  }
  eof() {
    return this.index >= this.length;
  }
  throwUnexpectedToken(message = Messages.UnexpectedTokenIllegal) {
    return this.errorHandler.throwError(
      this.index,
      this.lineNumber,
      this.index - this.lineStart + 1,
      message
    );
  }
  tolerateUnexpectedToken(message = Messages.UnexpectedTokenIllegal) {
    this.errorHandler.tolerateError(
      this.index,
      this.lineNumber,
      this.index - this.lineStart + 1,
      message
    );
  }
  // https://tc39.github.io/ecma262/#sec-comments
  skipSingleLineComment(offset) {
    let comments = [];
    let start, loc;
    if (this.trackComment) {
      comments = [];
      start = this.index - offset;
      loc = {
        start: {
          line: this.lineNumber,
          column: this.index - this.lineStart - offset
        },
        end: {}
      };
    }
    while (!this.eof()) {
      const ch = this.source.charCodeAt(this.index);
      ++this.index;
      if (Character.isLineTerminator(ch)) {
        if (this.trackComment) {
          loc.end = {
            line: this.lineNumber,
            column: this.index - this.lineStart - 1
          };
          const entry = {
            multiLine: false,
            slice: [start + offset, this.index - 1],
            range: [start, this.index - 1],
            loc
          };
          comments.push(entry);
        }
        if (ch === 13 && this.source.charCodeAt(this.index) === 10) {
          ++this.index;
        }
        ++this.lineNumber;
        this.lineStart = this.index;
        return comments;
      }
    }
    if (this.trackComment) {
      loc.end = {
        line: this.lineNumber,
        column: this.index - this.lineStart
      };
      const entry = {
        multiLine: false,
        slice: [start + offset, this.index],
        range: [start, this.index],
        loc
      };
      comments.push(entry);
    }
    return comments;
  }
  skipMultiLineComment() {
    let comments = [];
    let start, loc;
    if (this.trackComment) {
      comments = [];
      start = this.index - 2;
      loc = {
        start: {
          line: this.lineNumber,
          column: this.index - this.lineStart - 2
        },
        end: {}
      };
    }
    while (!this.eof()) {
      const ch = this.source.charCodeAt(this.index);
      if (Character.isLineTerminator(ch)) {
        if (ch === 13 && this.source.charCodeAt(this.index + 1) === 10) {
          ++this.index;
        }
        ++this.lineNumber;
        ++this.index;
        this.lineStart = this.index;
      } else if (ch === 42) {
        if (this.source.charCodeAt(this.index + 1) === 47) {
          this.index += 2;
          if (this.trackComment) {
            loc.end = {
              line: this.lineNumber,
              column: this.index - this.lineStart
            };
            const entry = {
              multiLine: true,
              slice: [start + 2, this.index - 2],
              range: [start, this.index],
              loc
            };
            comments.push(entry);
          }
          return comments;
        }
        ++this.index;
      } else {
        ++this.index;
      }
    }
    if (this.trackComment) {
      loc.end = {
        line: this.lineNumber,
        column: this.index - this.lineStart
      };
      const entry = {
        multiLine: true,
        slice: [start + 2, this.index],
        range: [start, this.index],
        loc
      };
      comments.push(entry);
    }
    this.tolerateUnexpectedToken();
    return comments;
  }
  scanComments() {
    let comments;
    if (this.trackComment) {
      comments = [];
    }
    let start = this.index === 0;
    while (!this.eof()) {
      let ch = this.source.charCodeAt(this.index);
      if (Character.isWhiteSpace(ch)) {
        ++this.index;
      } else if (Character.isLineTerminator(ch)) {
        ++this.index;
        if (ch === 13 && this.source.charCodeAt(this.index) === 10) {
          ++this.index;
        }
        ++this.lineNumber;
        this.lineStart = this.index;
        start = true;
      } else if (ch === 47) {
        ch = this.source.charCodeAt(this.index + 1);
        if (ch === 47) {
          this.index += 2;
          const comment = this.skipSingleLineComment(2);
          if (this.trackComment) {
            comments = comments.concat(comment);
          }
          start = true;
        } else if (ch === 42) {
          this.index += 2;
          const comment = this.skipMultiLineComment();
          if (this.trackComment) {
            comments = comments.concat(comment);
          }
        } else {
          break;
        }
      } else if (start && ch === 45) {
        if (this.source.charCodeAt(this.index + 1) === 45 && this.source.charCodeAt(this.index + 2) === 62) {
          this.index += 3;
          const comment = this.skipSingleLineComment(3);
          if (this.trackComment) {
            comments = comments.concat(comment);
          }
        } else {
          break;
        }
      } else if (ch === 60 && !this.isModule) {
        if (this.source.slice(this.index + 1, this.index + 4) === "!--") {
          this.index += 4;
          const comment = this.skipSingleLineComment(4);
          if (this.trackComment) {
            comments = comments.concat(comment);
          }
        } else {
          break;
        }
      } else {
        break;
      }
    }
    return comments;
  }
  // https://tc39.github.io/ecma262/#sec-future-reserved-words
  isFutureReservedWord(id) {
    switch (id) {
      case "enum":
      case "export":
      case "import":
      case "super":
        return true;
      default:
        return false;
    }
  }
  isStrictModeReservedWord(id) {
    switch (id) {
      case "implements":
      case "interface":
      case "package":
      case "private":
      case "protected":
      case "public":
      case "static":
      case "yield":
      case "let":
        return true;
      default:
        return false;
    }
  }
  isRestrictedWord(id) {
    return id === "eval" || id === "arguments";
  }
  // https://tc39.github.io/ecma262/#sec-keywords
  isKeyword(id) {
    switch (id.length) {
      case 2:
        return id === "if" || id === "in" || id === "do";
      case 3:
        return id === "var" || id === "for" || id === "new" || id === "try" || id === "let";
      case 4:
        return id === "this" || id === "else" || id === "case" || id === "void" || id === "with" || id === "enum";
      case 5:
        return id === "while" || id === "break" || id === "catch" || id === "throw" || id === "const" || id === "yield" || id === "class" || id === "super";
      case 6:
        return id === "return" || id === "typeof" || id === "delete" || id === "switch" || id === "export" || id === "import";
      case 7:
        return id === "default" || id === "finally" || id === "extends";
      case 8:
        return id === "function" || id === "continue" || id === "debugger";
      case 10:
        return id === "instanceof";
      default:
        return false;
    }
  }
  codePointAt(i) {
    let cp = this.source.charCodeAt(i);
    if (cp >= 55296 && cp <= 56319) {
      const second = this.source.charCodeAt(i + 1);
      if (second >= 56320 && second <= 57343) {
        const first = cp;
        cp = (first - 55296) * 1024 + second - 56320 + 65536;
      }
    }
    return cp;
  }
  scanHexEscape(prefix) {
    const len = prefix === "u" ? 4 : 2;
    let code = 0;
    for (let i = 0; i < len; ++i) {
      if (!this.eof() && Character.isHexDigit(this.source.charCodeAt(this.index))) {
        code = code * 16 + hexValue(this.source[this.index++]);
      } else {
        return null;
      }
    }
    return String.fromCharCode(code);
  }
  tryToScanUnicodeCodePointEscape() {
    let ch = this.source[this.index];
    let code = 0;
    if (ch === "}") {
      return null;
    }
    while (!this.eof()) {
      ch = this.source[this.index++];
      if (!Character.isHexDigit(ch.charCodeAt(0))) {
        break;
      }
      code = code * 16 + hexValue(ch);
    }
    if (code > 1114111 || ch !== "}") {
      return null;
    }
    return Character.fromCodePoint(code);
  }
  scanUnicodeCodePointEscape() {
    const result = this.tryToScanUnicodeCodePointEscape();
    if (result === null) {
      return this.throwUnexpectedToken();
    }
    return result;
  }
  getIdentifier() {
    const start = this.index++;
    while (!this.eof()) {
      const ch = this.source.charCodeAt(this.index);
      if (ch === 92) {
        this.index = start;
        return this.getComplexIdentifier();
      } else if (ch >= 55296 && ch < 57343) {
        this.index = start;
        return this.getComplexIdentifier();
      }
      if (Character.isIdentifierPart(ch)) {
        ++this.index;
      } else {
        break;
      }
    }
    return this.source.slice(start, this.index);
  }
  getComplexIdentifier() {
    let cp = this.codePointAt(this.index);
    let id = Character.fromCodePoint(cp);
    this.index += id.length;
    let ch;
    if (cp === 92) {
      if (this.source.charCodeAt(this.index) !== 117) {
        this.throwUnexpectedToken();
      }
      ++this.index;
      if (this.source[this.index] === "{") {
        ++this.index;
        ch = this.scanUnicodeCodePointEscape();
      } else {
        ch = this.scanHexEscape("u");
        if (ch === null || ch === "\\" || !Character.isIdentifierStart(ch.charCodeAt(0))) {
          this.throwUnexpectedToken();
        }
      }
      id = ch;
    }
    while (!this.eof()) {
      cp = this.codePointAt(this.index);
      if (!Character.isIdentifierPart(cp)) {
        break;
      }
      ch = Character.fromCodePoint(cp);
      id += ch;
      this.index += ch.length;
      if (cp === 92) {
        id = id.substr(0, id.length - 1);
        if (this.source.charCodeAt(this.index) !== 117) {
          this.throwUnexpectedToken();
        }
        ++this.index;
        if (this.source[this.index] === "{") {
          ++this.index;
          ch = this.scanUnicodeCodePointEscape();
        } else {
          ch = this.scanHexEscape("u");
          if (ch === null || ch === "\\" || !Character.isIdentifierPart(ch.charCodeAt(0))) {
            this.throwUnexpectedToken();
          }
        }
        id += ch;
      }
    }
    return id;
  }
  octalToDecimal(ch) {
    let octal = ch !== "0";
    let code = octalValue(ch);
    if (!this.eof() && Character.isOctalDigit(this.source.charCodeAt(this.index))) {
      octal = true;
      code = code * 8 + octalValue(this.source[this.index++]);
      if ("0123".indexOf(ch) >= 0 && !this.eof() && Character.isOctalDigit(this.source.charCodeAt(this.index))) {
        code = code * 8 + octalValue(this.source[this.index++]);
      }
    }
    return {
      code,
      octal
    };
  }
  // https://tc39.github.io/ecma262/#sec-names-and-keywords
  scanIdentifier() {
    let type;
    const start = this.index;
    const escaped = this.source.charCodeAt(start) === 92;
    const id = escaped ? this.getComplexIdentifier() : this.getIdentifier();
    if (id.length === 1) {
      type = 3 /* Identifier */;
    } else if (this.isKeyword(id)) {
      type = 4 /* Keyword */;
    } else if (id === "null") {
      type = 5 /* NullLiteral */;
    } else if (id === "true" || id === "false") {
      type = 1 /* BooleanLiteral */;
    } else {
      type = 3 /* Identifier */;
    }
    if (type !== 3 /* Identifier */ && start + id.length !== this.index) {
      const restore = this.index;
      this.index = start;
      this.tolerateUnexpectedToken(Messages.InvalidEscapedReservedWord);
      this.index = restore;
    }
    return {
      type,
      value: id,
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index,
      escaped
    };
  }
  // https://tc39.github.io/ecma262/#sec-punctuators
  scanPunctuator() {
    const start = this.index;
    let str = this.source[this.index];
    switch (str) {
      case "(":
      case "{":
        if (str === "{") {
          this.curlyStack.push("{");
        }
        ++this.index;
        break;
      case ".":
        ++this.index;
        if (this.source[this.index] === "." && this.source[this.index + 1] === ".") {
          this.index += 2;
          str = "...";
        }
        break;
      case "}":
        ++this.index;
        this.curlyStack.pop();
        break;
      case "?":
        ++this.index;
        if (this.source[this.index] === "?") {
          ++this.index;
          if (this.source[this.index] === "=") {
            ++this.index;
            str = "??=";
          } else {
            str = "??";
          }
        }
        if (this.source[this.index] === "." && !/^\d$/.test(this.source[this.index + 1])) {
          ++this.index;
          str = "?.";
        }
        break;
      case "#":
      case ")":
      case ";":
      case ",":
      case "[":
      case "]":
      case ":":
      case "~":
      case "@":
        ++this.index;
        break;
      default:
        str = this.source.substr(this.index, 4);
        if (str === ">>>=") {
          this.index += 4;
        } else {
          str = str.substr(0, 3);
          if (str === "===" || str === "!==" || str === ">>>" || str === "<<=" || str === ">>=" || str === "**=" || str === "&&=" || str === "||=") {
            this.index += 3;
          } else {
            str = str.substr(0, 2);
            if (str === "&&" || str === "||" || str === "==" || str === "!=" || str === "+=" || str === "-=" || str === "*=" || str === "/=" || str === "++" || str === "--" || str === "<<" || str === ">>" || str === "&=" || str === "|=" || str === "^=" || str === "%=" || str === "<=" || str === ">=" || str === "=>" || str === "**") {
              this.index += 2;
            } else {
              str = this.source[this.index];
              if ("<>=!+-*%&|^/".indexOf(str) >= 0) {
                ++this.index;
              }
            }
          }
        }
    }
    if (this.index === start) {
      this.throwUnexpectedToken();
    }
    return {
      type: 7 /* Punctuator */,
      value: str,
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  // https://tc39.github.io/ecma262/#sec-literals-numeric-literals
  scanHexLiteral(start) {
    let num = this.scanLiteralPart(Character.isHexDigitChar);
    if (num.length === 0) {
      this.throwUnexpectedToken();
    }
    if (this.source[this.index] === "n") {
      this.index++;
      return {
        type: 6 /* NumericLiteral */,
        value: BigInt("0x" + num),
        lineNumber: this.lineNumber,
        lineStart: this.lineStart,
        start,
        end: this.index
      };
    }
    if (Character.isIdentifierStart(this.source.charCodeAt(this.index))) {
      this.throwUnexpectedToken();
    }
    return {
      type: 6 /* NumericLiteral */,
      value: parseInt("0x" + num, 16),
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  scanBinaryLiteral(start) {
    let ch;
    let num = this.scanLiteralPart((c) => c === "0" || c === "1");
    if (num.length === 0) {
      this.throwUnexpectedToken();
    }
    if (this.source[this.index] === "n") {
      this.index++;
      return {
        type: 6 /* NumericLiteral */,
        value: BigInt("0b" + num),
        lineNumber: this.lineNumber,
        lineStart: this.lineStart,
        start,
        end: this.index
      };
    }
    if (!this.eof()) {
      ch = this.source.charCodeAt(this.index);
      if (Character.isIdentifierStart(ch) || Character.isDecimalDigit(ch)) {
        this.throwUnexpectedToken();
      }
    }
    return {
      type: 6 /* NumericLiteral */,
      value: parseInt(num, 2),
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  scanOctalLiteral(prefix, start) {
    let num = "";
    let octal = false;
    if (Character.isOctalDigit(prefix.charCodeAt(0))) {
      octal = true;
      num = "0" + this.source[this.index++];
    } else {
      ++this.index;
    }
    num += this.scanLiteralPart(Character.isOctalDigitChar);
    if (!octal && num.length === 0) {
      this.throwUnexpectedToken();
    }
    if (this.source[this.index] === "n") {
      this.index++;
      return {
        type: 6 /* NumericLiteral */,
        value: BigInt("0o" + num),
        lineNumber: this.lineNumber,
        lineStart: this.lineStart,
        start,
        end: this.index
      };
    }
    if (Character.isIdentifierStart(this.source.charCodeAt(this.index)) || Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
      this.throwUnexpectedToken();
    }
    return {
      type: 6 /* NumericLiteral */,
      value: parseInt(num, 8),
      octal,
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  isImplicitOctalLiteral() {
    for (let i = this.index + 1; i < this.length; ++i) {
      const ch = this.source[i];
      if (ch === "8" || ch === "9" || ch === "n") {
        return false;
      }
      if (!Character.isOctalDigit(ch.charCodeAt(0))) {
        return true;
      }
    }
    return true;
  }
  scanLiteralPart(check) {
    let num = "";
    if (this.source[this.index] === "_")
      this.throwUnexpectedToken(Messages.NumericSeperatorNotAllowedHere);
    while (this.source[this.index] && (check(this.source[this.index]) || this.source[this.index] === "_")) {
      if (this.source[this.index] !== "_")
        num += this.source[this.index];
      this.index++;
      if (this.source[this.index - 1] === "_" && this.source[this.index] === "_")
        this.throwUnexpectedToken(Messages.NumericSeperatorOneUnderscore);
    }
    if (this.source[this.index - 1] === "_")
      this.throwUnexpectedToken(Messages.NumericSeperatorNotAllowedHere);
    return num;
  }
  scanNumericLiteral() {
    const start = this.index;
    let ch = this.source[start];
    assert(
      Character.isDecimalDigit(ch.charCodeAt(0)) || ch === ".",
      "Numeric literal must start with a decimal digit or a decimal point"
    );
    let num = "";
    if (ch !== ".") {
      num = this.source[this.index++];
      ch = this.source[this.index];
      if (num === "0") {
        if (ch === "x" || ch === "X") {
          ++this.index;
          return this.scanHexLiteral(start);
        }
        if (ch === "b" || ch === "B") {
          ++this.index;
          return this.scanBinaryLiteral(start);
        }
        if (ch === "o" || ch === "O") {
          return this.scanOctalLiteral(ch, start);
        }
        if (ch && Character.isOctalDigit(ch.charCodeAt(0))) {
          if (this.isImplicitOctalLiteral()) {
            return this.scanOctalLiteral(ch, start);
          }
        }
      }
      this.index--;
      num = this.scanLiteralPart(Character.isDecimalDigitChar);
      ch = this.source[this.index];
    }
    if (ch === ".") {
      num += this.source[this.index++];
      num += this.scanLiteralPart(Character.isDecimalDigitChar);
      ch = this.source[this.index];
    }
    if (ch === "e" || ch === "E") {
      num += this.source[this.index++];
      ch = this.source[this.index];
      if (ch === "+" || ch === "-") {
        num += this.source[this.index++];
      }
      if (Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
        num += this.scanLiteralPart(Character.isDecimalDigitChar);
      } else {
        this.throwUnexpectedToken();
      }
    } else if (ch === "n") {
      if (num.length > 1 && num[0] === "0") {
        this.throwUnexpectedToken();
      }
      this.index++;
      return {
        type: 6 /* NumericLiteral */,
        value: BigInt(num),
        lineNumber: this.lineNumber,
        lineStart: this.lineStart,
        start,
        end: this.index
      };
    }
    if (Character.isIdentifierStart(this.source.charCodeAt(this.index))) {
      this.throwUnexpectedToken();
    }
    return {
      type: 6 /* NumericLiteral */,
      value: parseFloat(num),
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  // https://tc39.github.io/ecma262/#sec-literals-string-literals
  scanStringLiteral() {
    const start = this.index;
    let quote = this.source[start];
    assert(
      quote === "'" || quote === '"',
      "String literal must starts with a quote"
    );
    ++this.index;
    let octal = false;
    let str = "";
    while (!this.eof()) {
      let ch = this.source[this.index++];
      if (ch === quote) {
        quote = "";
        break;
      } else if (ch === "\\") {
        ch = this.source[this.index++];
        if (!ch || !Character.isLineTerminator(ch.charCodeAt(0))) {
          switch (ch) {
            case "u":
              if (this.source[this.index] === "{") {
                ++this.index;
                str += this.scanUnicodeCodePointEscape();
              } else {
                const unescapedChar = this.scanHexEscape(ch);
                if (unescapedChar === null) {
                  this.throwUnexpectedToken();
                }
                str += unescapedChar;
              }
              break;
            case "x":
              const unescaped = this.scanHexEscape(ch);
              if (unescaped === null) {
                this.throwUnexpectedToken(Messages.InvalidHexEscapeSequence);
              }
              str += unescaped;
              break;
            case "n":
              str += "\n";
              break;
            case "r":
              str += "\r";
              break;
            case "t":
              str += "	";
              break;
            case "b":
              str += "\b";
              break;
            case "f":
              str += "\f";
              break;
            case "v":
              str += "\v";
              break;
            case "8":
            case "9":
              str += ch;
              this.tolerateUnexpectedToken();
              break;
            default:
              if (ch && Character.isOctalDigit(ch.charCodeAt(0))) {
                const octToDec = this.octalToDecimal(ch);
                octal = octToDec.octal || octal;
                str += String.fromCharCode(octToDec.code);
              } else {
                str += ch;
              }
              break;
          }
        } else {
          ++this.lineNumber;
          if (ch === "\r" && this.source[this.index] === "\n") {
            ++this.index;
          }
          this.lineStart = this.index;
        }
      } else if (Character.isLineTerminator(ch.charCodeAt(0))) {
        break;
      } else {
        str += ch;
      }
    }
    if (quote !== "") {
      this.index = start;
      this.throwUnexpectedToken();
    }
    return {
      type: 8 /* StringLiteral */,
      value: str,
      octal,
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  // https://tc39.github.io/ecma262/#sec-template-literal-lexical-components
  scanTemplate() {
    let cooked = "";
    let terminated = false;
    const start = this.index;
    const head = this.source[start] === "`";
    let tail = false;
    let notEscapeSequenceHead = null;
    let rawOffset = 2;
    ++this.index;
    while (!this.eof()) {
      let ch = this.source[this.index++];
      if (ch === "`") {
        rawOffset = 1;
        tail = true;
        terminated = true;
        break;
      } else if (ch === "$") {
        if (this.source[this.index] === "{") {
          this.curlyStack.push("${");
          ++this.index;
          terminated = true;
          break;
        }
        cooked += ch;
      } else if (notEscapeSequenceHead !== null) {
        continue;
      } else if (ch === "\\") {
        ch = this.source[this.index++];
        if (!Character.isLineTerminator(ch.charCodeAt(0))) {
          switch (ch) {
            case "n":
              cooked += "\n";
              break;
            case "r":
              cooked += "\r";
              break;
            case "t":
              cooked += "	";
              break;
            case "u":
              if (this.source[this.index] === "{") {
                ++this.index;
                const unicodeCodePointEscape = this.tryToScanUnicodeCodePointEscape();
                if (unicodeCodePointEscape === null) {
                  notEscapeSequenceHead = "u";
                } else {
                  cooked += unicodeCodePointEscape;
                }
              } else {
                const unescapedChar = this.scanHexEscape(ch);
                if (unescapedChar === null) {
                  notEscapeSequenceHead = "u";
                } else {
                  cooked += unescapedChar;
                }
              }
              break;
            case "x":
              const unescaped = this.scanHexEscape(ch);
              if (unescaped === null) {
                notEscapeSequenceHead = "x";
              } else {
                cooked += unescaped;
              }
              break;
            case "b":
              cooked += "\b";
              break;
            case "f":
              cooked += "\f";
              break;
            case "v":
              cooked += "\v";
              break;
            default:
              if (ch === "0") {
                if (Character.isDecimalDigit(this.source.charCodeAt(this.index))) {
                  notEscapeSequenceHead = "0";
                } else {
                  cooked += "\0";
                }
              } else if (Character.isDecimalDigitChar(ch)) {
                notEscapeSequenceHead = ch;
              } else {
                cooked += ch;
              }
              break;
          }
        } else {
          ++this.lineNumber;
          if (ch === "\r" && this.source[this.index] === "\n") {
            ++this.index;
          }
          this.lineStart = this.index;
        }
      } else if (Character.isLineTerminator(ch.charCodeAt(0))) {
        ++this.lineNumber;
        if (ch === "\r" && this.source[this.index] === "\n") {
          ++this.index;
        }
        this.lineStart = this.index;
        cooked += "\n";
      } else {
        cooked += ch;
      }
    }
    if (!terminated) {
      this.throwUnexpectedToken();
    }
    if (!head) {
      this.curlyStack.pop();
    }
    return {
      type: 10 /* Template */,
      value: this.source.slice(start + 1, this.index - rawOffset),
      cooked: notEscapeSequenceHead === null ? cooked : null,
      head,
      tail,
      notEscapeSequenceHead,
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  // https://tc39.github.io/ecma262/#sec-literals-regular-expression-literals
  testRegExp(pattern, flags) {
    const astralSubstitute = "\uFFFF";
    let tmp = pattern;
    if (flags.indexOf("u") >= 0) {
      tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, ($0, $1, $2) => {
        const codePoint = parseInt($1 || $2, 16);
        if (codePoint > 1114111) {
          this.throwUnexpectedToken(Messages.InvalidRegExp);
        }
        if (codePoint <= 65535) {
          return String.fromCharCode(codePoint);
        }
        return astralSubstitute;
      }).replace(
        /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
        astralSubstitute
      );
    }
    try {
      RegExp(tmp);
    } catch (e) {
      this.throwUnexpectedToken(Messages.InvalidRegExp);
    }
    try {
      return new RegExp(pattern, flags);
    } catch (exception) {
      return null;
    }
  }
  scanRegExpBody() {
    let ch = this.source[this.index];
    assert(ch === "/", "Regular expression literal must start with a slash");
    let str = this.source[this.index++];
    let classMarker = false;
    let terminated = false;
    while (!this.eof()) {
      ch = this.source[this.index++];
      str += ch;
      if (ch === "\\") {
        ch = this.source[this.index++];
        if (Character.isLineTerminator(ch.charCodeAt(0))) {
          this.throwUnexpectedToken(Messages.UnterminatedRegExp);
        }
        str += ch;
      } else if (Character.isLineTerminator(ch.charCodeAt(0))) {
        this.throwUnexpectedToken(Messages.UnterminatedRegExp);
      } else if (classMarker) {
        if (ch === "]") {
          classMarker = false;
        }
      } else {
        if (ch === "/") {
          terminated = true;
          break;
        } else if (ch === "[") {
          classMarker = true;
        }
      }
    }
    if (!terminated) {
      this.throwUnexpectedToken(Messages.UnterminatedRegExp);
    }
    return str.substr(1, str.length - 2);
  }
  scanRegExpFlags() {
    let str = "";
    let flags = "";
    while (!this.eof()) {
      let ch = this.source[this.index];
      if (!Character.isIdentifierPart(ch.charCodeAt(0))) {
        break;
      }
      ++this.index;
      if (ch === "\\" && !this.eof()) {
        ch = this.source[this.index];
        if (ch === "u") {
          ++this.index;
          let restore = this.index;
          const char = this.scanHexEscape("u");
          if (char !== null) {
            flags += char;
            for (str += "\\u"; restore < this.index; ++restore) {
              str += this.source[restore];
            }
          } else {
            this.index = restore;
            flags += "u";
            str += "\\u";
          }
          this.tolerateUnexpectedToken();
        } else {
          str += "\\";
          this.tolerateUnexpectedToken();
        }
      } else {
        flags += ch;
        str += ch;
      }
    }
    return flags;
  }
  scanRegExp() {
    const start = this.index;
    const pattern = this.scanRegExpBody();
    const flags = this.scanRegExpFlags();
    const value = this.testRegExp(pattern, flags);
    return {
      type: 9 /* RegularExpression */,
      value: "",
      pattern,
      flags,
      regex: value,
      lineNumber: this.lineNumber,
      lineStart: this.lineStart,
      start,
      end: this.index
    };
  }
  lex() {
    if (this.eof()) {
      return {
        type: 2 /* EOF */,
        value: "",
        lineNumber: this.lineNumber,
        lineStart: this.lineStart,
        start: this.index,
        end: this.index
      };
    }
    const cp = this.source.charCodeAt(this.index);
    if (Character.isIdentifierStart(cp)) {
      return this.scanIdentifier();
    }
    if (cp === 40 || cp === 41 || cp === 59) {
      return this.scanPunctuator();
    }
    if (cp === 39 || cp === 34) {
      return this.scanStringLiteral();
    }
    if (cp === 46) {
      if (Character.isDecimalDigit(this.source.charCodeAt(this.index + 1))) {
        return this.scanNumericLiteral();
      }
      return this.scanPunctuator();
    }
    if (Character.isDecimalDigit(cp)) {
      return this.scanNumericLiteral();
    }
    if (cp === 96 || cp === 125 && this.curlyStack[this.curlyStack.length - 1] === "${") {
      return this.scanTemplate();
    }
    if (cp >= 55296 && cp < 57343) {
      if (Character.isIdentifierStart(this.codePointAt(this.index))) {
        return this.scanIdentifier();
      }
    }
    return this.scanPunctuator();
  }
};

// src/parser.ts
var ArrowParameterPlaceHolder = "ArrowParameterPlaceHolder";
var Parser = class {
  config;
  delegate;
  errorHandler;
  scanner;
  operatorPrecedence;
  lookahead;
  hasLineTerminator;
  context;
  tokens;
  startMarker;
  lastMarker;
  constructor(code, options = {}, delegate) {
    this.config = {
      range: typeof options.range === "boolean" && options.range,
      loc: typeof options.loc === "boolean" && options.loc,
      source: null,
      tokens: typeof options.tokens === "boolean" && options.tokens,
      comment: typeof options.comment === "boolean" && options.comment,
      tolerant: typeof options.tolerant === "boolean" && options.tolerant
    };
    if (this.config.loc && options.source && options.source !== null) {
      this.config.source = String(options.source);
    }
    this.delegate = delegate;
    this.errorHandler = new ErrorHandler();
    this.errorHandler.tolerant = this.config.tolerant == true;
    this.scanner = new Scanner(code, this.errorHandler);
    this.scanner.trackComment = this.config.comment == true;
    this.operatorPrecedence = {
      ")": 0,
      ";": 0,
      ",": 0,
      "=": 0,
      "]": 0,
      "??": 5,
      "||": 6,
      "&&": 7,
      "|": 8,
      "^": 9,
      "&": 10,
      "==": 11,
      "!=": 11,
      "===": 11,
      "!==": 11,
      "<": 12,
      ">": 12,
      "<=": 12,
      ">=": 12,
      "<<": 13,
      ">>": 13,
      ">>>": 13,
      "+": 14,
      "-": 14,
      "*": 15,
      "/": 15,
      "%": 15
    };
    this.lookahead = {
      type: 2 /* EOF */,
      value: "",
      lineNumber: this.scanner.lineNumber,
      lineStart: 0,
      start: 0,
      end: 0
    };
    this.hasLineTerminator = false;
    this.context = {
      isModule: false,
      isAsync: false,
      allowIn: true,
      allowStrictDirective: true,
      allowSuper: false,
      allowYield: true,
      firstCoverInitializedNameError: null,
      isAssignmentTarget: false,
      isBindingElement: false,
      inConstructor: false,
      inFunctionBody: false,
      inIteration: false,
      inSwitch: false,
      inClassConstructor: false,
      labelSet: {},
      strict: false,
      decorators: null
    };
    this.tokens = [];
    this.startMarker = {
      index: 0,
      line: this.scanner.lineNumber,
      column: 0
    };
    this.lastMarker = {
      index: 0,
      line: this.scanner.lineNumber,
      column: 0
    };
    this.nextToken();
    this.lastMarker = {
      index: this.scanner.index,
      line: this.scanner.lineNumber,
      column: this.scanner.index - this.scanner.lineStart
    };
  }
  throwError(messageFormat, ...values) {
    const args = values.slice();
    const msg = messageFormat.replace(
      /%(\d)/g,
      (whole, idx) => {
        assert(idx < args.length, "Message reference must be in range");
        return args[idx];
      }
    );
    const index = this.lastMarker.index;
    const line = this.lastMarker.line;
    const column = this.lastMarker.column + 1;
    throw this.errorHandler.createError(index, line, column, msg);
  }
  tolerateError(messageFormat, ...values) {
    const args = values.slice();
    const msg = messageFormat.replace(
      /%(\d)/g,
      (whole, idx) => {
        assert(idx < args.length, "Message reference must be in range");
        return args[idx];
      }
    );
    const index = this.lastMarker.index;
    const line = this.scanner.lineNumber;
    const column = this.lastMarker.column + 1;
    this.errorHandler.tolerateError(index, line, column, msg);
  }
  // Throw an exception because of the token.
  unexpectedTokenError(token, message) {
    let msg = message || Messages.UnexpectedToken;
    let value;
    if (token) {
      if (!message) {
        msg = token.type === 2 /* EOF */ ? Messages.UnexpectedEOS : token.type === 3 /* Identifier */ ? Messages.UnexpectedIdentifier : token.type === 6 /* NumericLiteral */ ? Messages.UnexpectedNumber : token.type === 8 /* StringLiteral */ ? Messages.UnexpectedString : token.type === 10 /* Template */ ? Messages.UnexpectedTemplate : Messages.UnexpectedToken;
        if (token.type === 4 /* Keyword */) {
          if (this.scanner.isFutureReservedWord(token.value)) {
            msg = Messages.UnexpectedReserved;
          } else if (this.context.strict && this.scanner.isStrictModeReservedWord(token.value)) {
            msg = Messages.StrictReservedWord;
          }
        }
      }
      value = token.value;
    } else {
      value = "ILLEGAL";
    }
    msg = msg.replace("%0", value);
    if (token && typeof token.lineNumber === "number") {
      const index = token.start;
      const line = token.lineNumber;
      const lastMarkerLineStart = this.lastMarker.index - this.lastMarker.column;
      const column = token.start - lastMarkerLineStart + 1;
      return this.errorHandler.createError(index, line, column, msg);
    } else {
      const index = this.lastMarker.index;
      const line = this.lastMarker.line;
      const column = this.lastMarker.column + 1;
      return this.errorHandler.createError(index, line, column, msg);
    }
  }
  throwUnexpectedToken(token, message) {
    throw this.unexpectedTokenError(token, message);
  }
  tolerateUnexpectedToken(token, message) {
    this.errorHandler.tolerate(this.unexpectedTokenError(token, message));
  }
  tolerateInvalidLoopStatement() {
    if (this.matchKeyword("class") || this.matchKeyword("function")) {
      this.tolerateError(Messages.UnexpectedToken, this.lookahead);
    }
  }
  collectComments() {
    if (!this.config.comment) {
      this.scanner.scanComments();
    } else {
      const comments = this.scanner.scanComments();
      if (comments.length > 0 && this.delegate) {
        for (let i = 0; i < comments.length; ++i) {
          const e = comments[i];
          const node = {
            type: e.multiLine ? "BlockComment" : "LineComment",
            value: this.scanner.source.slice(e.slice[0], e.slice[1])
          };
          if (this.config.range) {
            node.range = e.range;
          }
          if (this.config.loc) {
            node.loc = e.loc;
          }
          const metadata = {
            start: {
              line: e.loc.start.line,
              column: e.loc.start.column,
              offset: e.range[0]
            },
            end: {
              line: e.loc.end.line,
              column: e.loc.end.column,
              offset: e.range[1]
            }
          };
          this.delegate(node, metadata);
        }
      }
    }
  }
  // From internal representation to an external structure
  getTokenRaw(token) {
    return this.scanner.source.slice(token.start, token.end);
  }
  convertToken(token) {
    const t = {
      type: TokenName[token.type],
      value: this.getTokenRaw(token)
    };
    if (this.config.range) {
      t.range = [token.start, token.end];
    }
    if (this.config.loc) {
      t.loc = {
        start: {
          line: this.startMarker.line,
          column: this.startMarker.column
        },
        end: {
          line: this.scanner.lineNumber,
          column: this.scanner.index - this.scanner.lineStart
        }
      };
    }
    if (token.type === 9 /* RegularExpression */) {
      const pattern = token.pattern;
      const flags = token.flags;
      t.regex = { pattern, flags };
    }
    return t;
  }
  nextToken() {
    const token = this.lookahead;
    this.lastMarker.index = this.scanner.index;
    this.lastMarker.line = this.scanner.lineNumber;
    this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
    this.collectComments();
    if (this.scanner.index !== this.startMarker.index) {
      this.startMarker.index = this.scanner.index;
      this.startMarker.line = this.scanner.lineNumber;
      this.startMarker.column = this.scanner.index - this.scanner.lineStart;
    }
    const next = this.scanner.lex();
    this.hasLineTerminator = token.lineNumber !== next.lineNumber;
    if (next && this.context.strict && next.type === 3 /* Identifier */) {
      if (this.scanner.isStrictModeReservedWord(next.value)) {
        next.type = 4 /* Keyword */;
      }
    }
    this.lookahead = next;
    if (this.config.tokens && next.type !== 2 /* EOF */) {
      this.tokens.push(this.convertToken(next));
    }
    return token;
  }
  nextRegexToken() {
    this.collectComments();
    const token = this.scanner.scanRegExp();
    if (this.config.tokens) {
      this.tokens.pop();
      this.tokens.push(this.convertToken(token));
    }
    this.lookahead = token;
    this.nextToken();
    return token;
  }
  createNode() {
    return {
      index: this.startMarker.index,
      line: this.startMarker.line,
      column: this.startMarker.column
    };
  }
  startNode(token, lastLineStart = 0) {
    let column = token.start - token.lineStart;
    let line = token.lineNumber;
    if (column < 0) {
      column += lastLineStart;
      line--;
    }
    return {
      index: token.start,
      line,
      column
    };
  }
  finalize(marker, node) {
    if (this.config.range) {
      node.range = [marker.index, this.lastMarker.index];
    }
    if (this.config.loc) {
      node.loc = {
        start: {
          line: marker.line,
          column: marker.column
        },
        end: {
          line: this.lastMarker.line,
          column: this.lastMarker.column
        }
      };
      if (this.config.source) {
        node.loc.source = this.config.source;
      }
    }
    if (this.delegate) {
      const metadata = {
        start: {
          line: marker.line,
          column: marker.column,
          offset: marker.index
        },
        end: {
          line: this.lastMarker.line,
          column: this.lastMarker.column,
          offset: this.lastMarker.index
        }
      };
      this.delegate(node, metadata);
    }
    return node;
  }
  // Expect the next token to match the specified punctuator.
  // If not, an exception will be thrown.
  expect(value) {
    const token = this.nextToken();
    if (token.type !== 7 /* Punctuator */ || token.value !== value) {
      this.throwUnexpectedToken(token);
    }
  }
  // Quietly expect a comma when in tolerant mode, otherwise delegates to expect().
  expectCommaSeparator() {
    if (this.config.tolerant) {
      const token = this.lookahead;
      if (token.type === 7 /* Punctuator */ && token.value === ",") {
        this.nextToken();
      } else if (token.type === 7 /* Punctuator */ && token.value === ";") {
        this.nextToken();
        this.tolerateUnexpectedToken(token);
      } else {
        this.tolerateUnexpectedToken(token, Messages.UnexpectedToken);
      }
    } else {
      this.expect(",");
    }
  }
  // Expect the next token to match the specified keyword.
  // If not, an exception will be thrown.
  expectKeyword(keyword) {
    const token = this.nextToken();
    if (token.type !== 4 /* Keyword */ || token.value !== keyword) {
      this.throwUnexpectedToken(token);
    }
  }
  // Return true if the next token matches the specified punctuator.
  match(value) {
    return this.lookahead.type === 7 /* Punctuator */ && this.lookahead.value === value;
  }
  // Return true if the next token matches the specified keyword
  matchKeyword(keyword) {
    return this.lookahead.type === 4 /* Keyword */ && this.lookahead.value === keyword;
  }
  // Return true if the next token matches the specified contextual keyword
  // (where an identifier is sometimes a keyword depending on the context)
  matchContextualKeyword(keyword) {
    return this.lookahead.type === 3 /* Identifier */ && this.lookahead.value === keyword;
  }
  // Return true if the next token is an assignment operator
  matchAssign() {
    if (this.lookahead.type !== 7 /* Punctuator */) {
      return false;
    }
    const op = this.lookahead.value;
    return op === "=" || op === "*=" || op === "**=" || op === "/=" || op === "%=" || op === "+=" || op === "-=" || op === "<<=" || op === ">>=" || op === ">>>=" || op === "&=" || op === "^=" || op === "|=" || op === "&&=" || op === "||=" || op === "??=";
  }
  // Cover grammar support.
  //
  // When an assignment expression position starts with an left parenthesis, the determination of the type
  // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
  // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
  //
  // There are three productions that can be parsed in a parentheses pair that needs to be determined
  // after the outermost pair is closed. They are:
  //
  //   1. AssignmentExpression
  //   2. BindingElements
  //   3. AssignmentTargets
  //
  // In order to avoid exponential backtracking, we use two flags to denote if the production can be
  // binding element or assignment target.
  //
  // The three productions have the relationship:
  //
  //   BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression
  //
  // with a single exception that CoverInitializedName when used directly in an Expression, generates
  // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
  // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
  //
  // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
  // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
  // the CoverInitializedName check is conducted.
  //
  // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
  // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
  // pattern. The CoverInitializedName check is deferred.
  isolateCoverGrammar(parseFunction) {
    const previousIsBindingElement = this.context.isBindingElement;
    const previousIsAssignmentTarget = this.context.isAssignmentTarget;
    const previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError;
    this.context.isBindingElement = true;
    this.context.isAssignmentTarget = true;
    this.context.firstCoverInitializedNameError = null;
    const result = parseFunction.call(this);
    if (this.context.firstCoverInitializedNameError !== null) {
      this.throwUnexpectedToken(this.context.firstCoverInitializedNameError);
    }
    this.context.isBindingElement = previousIsBindingElement;
    this.context.isAssignmentTarget = previousIsAssignmentTarget;
    this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError;
    return result;
  }
  inheritCoverGrammar(parseFunction) {
    const previousIsBindingElement = this.context.isBindingElement;
    const previousIsAssignmentTarget = this.context.isAssignmentTarget;
    const previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError;
    this.context.isBindingElement = true;
    this.context.isAssignmentTarget = true;
    this.context.firstCoverInitializedNameError = null;
    const result = parseFunction.call(this);
    this.context.isBindingElement = this.context.isBindingElement && previousIsBindingElement;
    this.context.isAssignmentTarget = this.context.isAssignmentTarget && previousIsAssignmentTarget;
    this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.context.firstCoverInitializedNameError;
    return result;
  }
  consumeSemicolon() {
    if (this.match(";")) {
      this.nextToken();
    } else if (!this.hasLineTerminator) {
      if (this.lookahead.type !== 2 /* EOF */ && !this.match("}")) {
        this.throwUnexpectedToken(this.lookahead);
      }
      this.lastMarker.index = this.startMarker.index;
      this.lastMarker.line = this.startMarker.line;
      this.lastMarker.column = this.startMarker.column;
    }
  }
  // https://tc39.github.io/ecma262/#sec-primary-expression
  parsePrimaryExpression() {
    const node = this.createNode();
    let expr;
    let token, raw;
    switch (this.lookahead.type) {
      case 3 /* Identifier */:
        if ((this.context.isModule || this.context.isAsync) && this.lookahead.value === "await") {
          this.tolerateUnexpectedToken(this.lookahead);
        }
        expr = this.matchAsyncFunction() ? this.parseFunctionExpression() : this.finalize(node, new Identifier(this.nextToken().value));
        break;
      case 6 /* NumericLiteral */:
      case 8 /* StringLiteral */:
        if (this.context.strict && this.lookahead.octal) {
          this.tolerateUnexpectedToken(this.lookahead, Messages.StrictOctalLiteral);
        }
        this.context.isAssignmentTarget = false;
        this.context.isBindingElement = false;
        token = this.nextToken();
        raw = this.getTokenRaw(token);
        if (typeof token.value === "bigint")
          expr = this.finalize(node, new BigIntLiteral(token.value, raw, token.value.toString()));
        else
          expr = this.finalize(node, new Literal(token.value, raw));
        break;
      case 1 /* BooleanLiteral */:
        this.context.isAssignmentTarget = false;
        this.context.isBindingElement = false;
        token = this.nextToken();
        raw = this.getTokenRaw(token);
        expr = this.finalize(node, new Literal(token.value === "true", raw));
        break;
      case 5 /* NullLiteral */:
        this.context.isAssignmentTarget = false;
        this.context.isBindingElement = false;
        token = this.nextToken();
        raw = this.getTokenRaw(token);
        expr = this.finalize(node, new Literal(null, raw));
        break;
      case 10 /* Template */:
        expr = this.parseTemplateLiteral({ isTagged: false });
        break;
      case 7 /* Punctuator */:
        switch (this.lookahead.value) {
          case "(":
            this.context.isBindingElement = false;
            expr = this.inheritCoverGrammar(this.parseGroupExpression);
            break;
          case "[":
            expr = this.inheritCoverGrammar(this.parseArrayInitializer);
            break;
          case "{":
            expr = this.inheritCoverGrammar(this.parseObjectInitializer);
            break;
          case "/":
          case "/=":
            this.context.isAssignmentTarget = false;
            this.context.isBindingElement = false;
            this.scanner.index = this.startMarker.index;
            token = this.nextRegexToken();
            raw = this.getTokenRaw(token);
            expr = this.finalize(node, new RegexLiteral(token.regex, raw, token.pattern, token.flags));
            break;
          case "#":
            this.nextToken();
            expr = this.finalize(node, new PrivateIdentifier(this.nextToken().value));
            break;
          case "@":
            let decorators = this.parseDecorators();
            this.context.decorators = decorators;
            let expression = this.parsePrimaryExpression();
            this.context.decorators = null;
            expr = this.finalize(node, new PrivateIdentifier(this.nextToken().value));
            break;
          default:
            expr = this.throwUnexpectedToken(this.nextToken());
        }
        break;
      case 4 /* Keyword */:
        if (!this.context.strict && this.context.allowYield && this.matchKeyword("yield")) {
          expr = this.parseIdentifierName();
        } else if (!this.context.strict && this.matchKeyword("let")) {
          expr = this.finalize(node, new Identifier(this.nextToken().value));
        } else {
          this.context.isAssignmentTarget = false;
          this.context.isBindingElement = false;
          if (this.matchKeyword("function")) {
            expr = this.parseFunctionExpression();
          } else if (this.matchKeyword("this")) {
            this.nextToken();
            expr = this.finalize(node, new ThisExpression());
          } else if (this.matchKeyword("class")) {
            expr = this.parseClassExpression();
          } else if (this.matchKeyword("new")) {
            expr = this.parseNewExpression();
          } else if (this.matchImportCall()) {
            expr = this.parseImportCall();
          } else if (this.matchImportMeta()) {
            if (!this.context.isModule) {
              this.tolerateUnexpectedToken(this.lookahead, Messages.CannotUseImportMetaOutsideAModule);
            }
            expr = this.parseImportMeta();
          } else {
            expr = this.throwUnexpectedToken(this.nextToken());
          }
        }
        break;
      default:
        expr = this.throwUnexpectedToken(this.nextToken());
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-array-initializer
  parseSpreadElement() {
    const node = this.createNode();
    this.expect("...");
    const arg = this.inheritCoverGrammar(this.parseAssignmentExpression);
    return this.finalize(node, new SpreadElement(arg));
  }
  parseArrayInitializer() {
    const node = this.createNode();
    const elements = [];
    this.expect("[");
    while (!this.match("]")) {
      if (this.match(",")) {
        this.nextToken();
        elements.push(null);
      } else if (this.match("...")) {
        const element = this.parseSpreadElement();
        if (!this.match("]")) {
          this.context.isAssignmentTarget = false;
          this.context.isBindingElement = false;
          this.expect(",");
        }
        elements.push(element);
      } else {
        elements.push(this.inheritCoverGrammar(this.parseAssignmentExpression));
        if (!this.match("]")) {
          this.expect(",");
        }
      }
    }
    this.expect("]");
    return this.finalize(node, new ArrayExpression(elements));
  }
  // https://tc39.github.io/ecma262/#sec-object-initializer
  parsePropertyMethod(params) {
    this.context.isAssignmentTarget = false;
    this.context.isBindingElement = false;
    const previousStrict = this.context.strict;
    const previousAllowStrictDirective = this.context.allowStrictDirective;
    this.context.allowStrictDirective = params.simple;
    const body = this.isolateCoverGrammar(this.parseFunctionSourceElements);
    if (this.context.strict && params.firstRestricted) {
      this.tolerateUnexpectedToken(params.firstRestricted, params.message);
    }
    if (this.context.strict && params.stricted) {
      this.tolerateUnexpectedToken(params.stricted, params.message);
    }
    this.context.strict = previousStrict;
    this.context.allowStrictDirective = previousAllowStrictDirective;
    return body;
  }
  parsePropertyMethodFunction(isGenerator) {
    const node = this.createNode();
    const previousAllowYield = this.context.allowYield;
    this.context.allowYield = true;
    const params = this.parseFormalParameters();
    const method = this.parsePropertyMethod(params);
    this.context.allowYield = previousAllowYield;
    return this.finalize(node, new FunctionExpression(null, params.params, method, isGenerator, false));
  }
  parsePropertyMethodAsyncFunction(isGenerator) {
    const node = this.createNode();
    const previousAllowYield = this.context.allowYield;
    const previousIsAsync = this.context.isAsync;
    this.context.allowYield = false;
    this.context.isAsync = true;
    const params = this.parseFormalParameters();
    const method = this.parsePropertyMethod(params);
    this.context.allowYield = previousAllowYield;
    this.context.isAsync = previousIsAsync;
    return this.finalize(node, new FunctionExpression(null, params.params, method, isGenerator, true));
  }
  parseObjectPropertyKey(isPrivate = false) {
    const node = this.createNode();
    const token = this.nextToken();
    let key;
    switch (token.type) {
      case 8 /* StringLiteral */:
      case 6 /* NumericLiteral */:
        if (this.context.strict && token.octal) {
          this.tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
        }
        const raw = this.getTokenRaw(token);
        if (typeof token.value === "bigint")
          key = this.finalize(node, new BigIntLiteral(token.value, raw, token.value.toString()));
        else
          key = this.finalize(node, new Literal(token.value, raw));
        break;
      case 3 /* Identifier */:
      case 1 /* BooleanLiteral */:
      case 5 /* NullLiteral */:
      case 4 /* Keyword */:
        key = this.finalize(node, isPrivate ? new PrivateIdentifier(token.value) : new Identifier(token.value));
        break;
      case 7 /* Punctuator */:
        if (token.value === "[") {
          key = this.isolateCoverGrammar(this.parseAssignmentExpression);
          this.expect("]");
        } else {
          key = this.throwUnexpectedToken(token);
        }
        break;
      default:
        key = this.throwUnexpectedToken(token);
    }
    return key;
  }
  isPropertyKey(key, value) {
    return key.type === "Identifier" /* Identifier */ && key.name === value || key.type === "Literal" /* Literal */ && key.value === value;
  }
  parseObjectProperty(hasProto) {
    const node = this.createNode();
    const token = this.lookahead;
    let kind;
    let key = null;
    let value = null;
    let computed = false;
    let method = false;
    let shorthand = false;
    let isAsync = false;
    let isGenerator = false;
    if (token.type === 3 /* Identifier */) {
      const id = token.value;
      this.nextToken();
      computed = this.match("[");
      isAsync = !this.hasLineTerminator && id === "async" && !this.match(":") && !this.match("(") && !this.match(",");
      isGenerator = this.match("*");
      if (isGenerator) {
        this.nextToken();
      }
      key = isAsync ? this.parseObjectPropertyKey() : this.finalize(node, new Identifier(id));
    } else if (this.match("*")) {
      this.nextToken();
    } else {
      computed = this.match("[");
      key = this.parseObjectPropertyKey();
    }
    const lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead);
    if (token.type === 3 /* Identifier */ && !isAsync && token.value === "get" && lookaheadPropertyKey) {
      kind = "get";
      computed = this.match("[");
      key = this.parseObjectPropertyKey();
      this.context.allowYield = false;
      value = this.parseGetterMethod();
    } else if (token.type === 3 /* Identifier */ && !isAsync && token.value === "set" && lookaheadPropertyKey) {
      kind = "set";
      computed = this.match("[");
      key = this.parseObjectPropertyKey();
      value = this.parseSetterMethod();
    } else if (token.type === 7 /* Punctuator */ && token.value === "*" && lookaheadPropertyKey) {
      kind = "init";
      computed = this.match("[");
      key = this.parseObjectPropertyKey();
      value = this.parseGeneratorMethod(false);
      method = true;
    } else {
      if (!key) {
        this.throwUnexpectedToken(this.lookahead);
      }
      kind = "init";
      if (this.match(":") && !isAsync) {
        if (!computed && this.isPropertyKey(key, "__proto__")) {
          if (hasProto.value) {
            this.tolerateError(Messages.DuplicateProtoProperty);
          }
          hasProto.value = true;
        }
        this.nextToken();
        value = this.inheritCoverGrammar(this.parseAssignmentExpression);
      } else if (this.match("(")) {
        value = isAsync ? this.parsePropertyMethodAsyncFunction(isGenerator) : this.parsePropertyMethodFunction(isGenerator);
        method = true;
      } else if (token.type === 3 /* Identifier */) {
        const id = this.finalize(node, new Identifier(token.value));
        if (this.match("=")) {
          this.context.firstCoverInitializedNameError = this.lookahead;
          this.nextToken();
          shorthand = true;
          const init = this.isolateCoverGrammar(this.parseAssignmentExpression);
          value = this.finalize(node, new AssignmentPattern(id, init));
        } else {
          shorthand = true;
          value = id;
        }
      } else {
        this.throwUnexpectedToken(this.nextToken());
      }
    }
    return this.finalize(node, new Property(kind, key, computed, value, method, shorthand));
  }
  parseObjectInitializer() {
    const node = this.createNode();
    this.expect("{");
    const properties = [];
    const hasProto = { value: false };
    while (!this.match("}")) {
      const property = this.match("...") ? this.parseSpreadElement() : this.parseObjectProperty(hasProto);
      properties.push(property);
      if (!this.match("}") && (!property.method || this.match(","))) {
        this.expectCommaSeparator();
      }
    }
    this.expect("}");
    return this.finalize(node, new ObjectExpression(properties));
  }
  // https://tc39.es/proposal-template-literal-revision/#sec-static-semantics-template-early-errors
  throwTemplateLiteralEarlyErrors(token) {
    switch (token.notEscapeSequenceHead) {
      case "u":
        return this.throwUnexpectedToken(token, Messages.InvalidUnicodeEscapeSequence);
      case "x":
        return this.throwUnexpectedToken(token, Messages.InvalidHexEscapeSequence);
      case "8":
      case "9":
        return this.throwUnexpectedToken(token, Messages.TemplateEscape89);
      default:
        return this.throwUnexpectedToken(token, Messages.TemplateOctalLiteral);
    }
  }
  // https://tc39.github.io/ecma262/#sec-template-literals
  parseTemplateHead(options) {
    assert(this.lookahead.head, "Template literal must start with a template head");
    const node = this.createNode();
    const token = this.nextToken();
    if (!options.isTagged && token.notEscapeSequenceHead !== null) {
      this.throwTemplateLiteralEarlyErrors(token);
    }
    const raw = token.value;
    const cooked = token.cooked;
    return this.finalize(node, new TemplateElement({ raw, cooked }, token.tail));
  }
  parseTemplateElement(options) {
    if (this.lookahead.type !== 10 /* Template */) {
      this.throwUnexpectedToken();
    }
    const node = this.createNode();
    const token = this.nextToken();
    if (!options.isTagged && token.notEscapeSequenceHead !== null) {
      this.throwTemplateLiteralEarlyErrors(token);
    }
    const raw = token.value;
    const cooked = token.cooked;
    return this.finalize(node, new TemplateElement({ raw, cooked }, token.tail));
  }
  parseTemplateLiteral(options) {
    const node = this.createNode();
    const expressions = [];
    const quasis = [];
    let quasi = this.parseTemplateHead(options);
    quasis.push(quasi);
    while (!quasi.tail) {
      expressions.push(this.parseExpression());
      quasi = this.parseTemplateElement(options);
      quasis.push(quasi);
    }
    return this.finalize(node, new TemplateLiteral(quasis, expressions));
  }
  // https://tc39.github.io/ecma262/#sec-grouping-operator
  reinterpretExpressionAsPattern(expr) {
    switch (expr.type) {
      case "Identifier" /* Identifier */:
      case "MemberExpression" /* MemberExpression */:
      case "RestElement" /* RestElement */:
      case "AssignmentPattern" /* AssignmentPattern */:
        break;
      case "SpreadElement" /* SpreadElement */:
        expr.type = "RestElement" /* RestElement */;
        this.reinterpretExpressionAsPattern(expr.argument);
        break;
      case "ArrayExpression" /* ArrayExpression */:
        expr.type = "ArrayPattern" /* ArrayPattern */;
        for (let i = 0; i < expr.elements.length; i++) {
          if (expr.elements[i] !== null) {
            this.reinterpretExpressionAsPattern(expr.elements[i]);
          }
        }
        break;
      case "ObjectExpression" /* ObjectExpression */:
        expr.type = "ObjectPattern" /* ObjectPattern */;
        for (let i = 0; i < expr.properties.length; i++) {
          const property = expr.properties[i];
          this.reinterpretExpressionAsPattern(property.type === "SpreadElement" /* SpreadElement */ ? property : property.value);
        }
        break;
      case "AssignmentExpression" /* AssignmentExpression */:
        expr.type = "AssignmentPattern" /* AssignmentPattern */;
        delete expr.operator;
        this.reinterpretExpressionAsPattern(expr.left);
        break;
      default:
        break;
    }
  }
  parseGroupExpression() {
    let expr;
    this.expect("(");
    if (this.match(")")) {
      this.nextToken();
      if (!this.match("=>")) {
        this.expect("=>");
      }
      expr = {
        type: ArrowParameterPlaceHolder,
        params: [],
        async: false
      };
    } else {
      const startToken = this.lookahead;
      const params = [];
      if (this.match("...")) {
        expr = this.parseRestElement(params);
        this.expect(")");
        if (!this.match("=>")) {
          this.expect("=>");
        }
        expr = {
          type: ArrowParameterPlaceHolder,
          params: [expr],
          async: false
        };
      } else {
        let arrow = false;
        this.context.isBindingElement = true;
        expr = this.inheritCoverGrammar(this.parseAssignmentExpression);
        if (this.match(",")) {
          const expressions = [];
          this.context.isAssignmentTarget = false;
          expressions.push(expr);
          while (this.lookahead.type !== 2 /* EOF */) {
            if (!this.match(",")) {
              break;
            }
            this.nextToken();
            if (this.match(")")) {
              this.nextToken();
              for (let i = 0; i < expressions.length; i++) {
                this.reinterpretExpressionAsPattern(expressions[i]);
              }
              arrow = true;
              expr = {
                type: ArrowParameterPlaceHolder,
                params: expressions,
                async: false
              };
            } else if (this.match("...")) {
              if (!this.context.isBindingElement) {
                this.throwUnexpectedToken(this.lookahead);
              }
              expressions.push(this.parseRestElement(params));
              this.expect(")");
              if (!this.match("=>")) {
                this.expect("=>");
              }
              this.context.isBindingElement = false;
              for (let i = 0; i < expressions.length; i++) {
                this.reinterpretExpressionAsPattern(expressions[i]);
              }
              arrow = true;
              expr = {
                type: ArrowParameterPlaceHolder,
                params: expressions,
                async: false
              };
            } else {
              expressions.push(this.inheritCoverGrammar(this.parseAssignmentExpression));
            }
            if (arrow) {
              break;
            }
          }
          if (!arrow) {
            expr = this.finalize(this.startNode(startToken), new SequenceExpression(expressions));
          }
        }
        if (!arrow) {
          this.expect(")");
          if (this.match("=>")) {
            if (expr.type === "Identifier" /* Identifier */ && expr.name === "yield") {
              arrow = true;
              expr = {
                type: ArrowParameterPlaceHolder,
                params: [expr],
                async: false
              };
            }
            if (!arrow) {
              if (!this.context.isBindingElement) {
                this.throwUnexpectedToken(this.lookahead);
              }
              if (expr.type === "SequenceExpression" /* SequenceExpression */) {
                for (let i = 0; i < expr.expressions.length; i++) {
                  this.reinterpretExpressionAsPattern(expr.expressions[i]);
                }
              } else {
                this.reinterpretExpressionAsPattern(expr);
              }
              const parameters = expr.type === "SequenceExpression" /* SequenceExpression */ ? expr.expressions : [expr];
              expr = {
                type: ArrowParameterPlaceHolder,
                params: parameters,
                async: false
              };
            }
          }
          this.context.isBindingElement = false;
        }
      }
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions
  parseArguments() {
    this.expect("(");
    const args = [];
    if (!this.match(")")) {
      while (true) {
        const expr = this.match("...") ? this.parseSpreadElement() : this.isolateCoverGrammar(this.parseAssignmentExpression);
        args.push(expr);
        if (this.match(")")) {
          break;
        }
        this.expectCommaSeparator();
        if (this.match(")")) {
          break;
        }
      }
    }
    this.expect(")");
    return args;
  }
  isIdentifierName(token) {
    return token.type === 3 /* Identifier */ || token.type === 4 /* Keyword */ || token.type === 1 /* BooleanLiteral */ || token.type === 5 /* NullLiteral */;
  }
  parseIdentifierName(allowPrivateField = false) {
    let isPrivateField = false;
    let node = this.createNode();
    let token = this.nextToken();
    if (token.value === "#" && allowPrivateField) {
      token = this.nextToken();
      isPrivateField = true;
    }
    if (!this.isIdentifierName(token)) {
      this.throwUnexpectedToken(token);
    }
    return this.finalize(node, isPrivateField ? new PrivateIdentifier(token.value) : new Identifier(token.value));
  }
  parseNewExpression() {
    const node = this.createNode();
    const id = this.parseIdentifierName();
    assert(id.name === "new", "New expression must start with `new`");
    let expr;
    if (this.match(".")) {
      this.nextToken();
      if (this.lookahead.type === 3 /* Identifier */ && this.context.inFunctionBody && this.lookahead.value === "target") {
        const property = this.parseIdentifierName();
        expr = new MetaProperty(id, property);
      } else {
        this.throwUnexpectedToken(this.lookahead);
      }
    } else if (this.matchKeyword("import")) {
      this.throwUnexpectedToken(this.lookahead);
    } else {
      const callee = this.isolateCoverGrammar(this.parseLeftHandSideExpression);
      const args = this.match("(") ? this.parseArguments() : [];
      expr = new NewExpression(callee, args);
      this.context.isAssignmentTarget = false;
      this.context.isBindingElement = false;
    }
    return this.finalize(node, expr);
  }
  parseAsyncArgument() {
    const arg = this.parseAssignmentExpression();
    this.context.firstCoverInitializedNameError = null;
    return arg;
  }
  parseAsyncArguments() {
    this.expect("(");
    const args = [];
    if (!this.match(")")) {
      while (true) {
        const expr = this.match("...") ? this.parseSpreadElement() : this.isolateCoverGrammar(this.parseAsyncArgument);
        args.push(expr);
        if (this.match(")")) {
          break;
        }
        this.expectCommaSeparator();
        if (this.match(")")) {
          break;
        }
      }
    }
    this.expect(")");
    return args;
  }
  matchImportCall() {
    let match = this.matchKeyword("import");
    if (match) {
      const state = this.scanner.saveState();
      this.scanner.scanComments();
      const next = this.scanner.lex();
      this.scanner.restoreState(state);
      match = next.type === 7 /* Punctuator */ && next.value === "(";
    }
    return match;
  }
  parseImportCall() {
    const node = this.createNode();
    this.expectKeyword("import");
    this.expect("(");
    var previousIsAssignmentTarget = this.context.isAssignmentTarget;
    this.context.isAssignmentTarget = true;
    const source = this.parseAssignmentExpression();
    let attributes = null;
    if (this.match(",")) {
      this.nextToken();
      if (!this.match(")"))
        attributes = this.parseAssignmentExpression();
    }
    this.context.isAssignmentTarget = previousIsAssignmentTarget;
    if (!this.match(")")) {
      if (this.match(",")) {
        this.nextToken();
      }
      this.expect(")");
    } else {
      this.nextToken();
    }
    return this.finalize(node, new ImportExpression(source, attributes));
  }
  matchImportMeta() {
    let match = this.matchKeyword("import");
    if (match) {
      const state = this.scanner.saveState();
      this.scanner.scanComments();
      const dot = this.scanner.lex();
      if (dot.type === 7 /* Punctuator */ && dot.value === ".") {
        this.scanner.scanComments();
        const meta = this.scanner.lex();
        match = meta.type === 3 /* Identifier */ && meta.value === "meta";
        if (match) {
          if (meta.end - meta.start !== "meta".length) {
            this.tolerateUnexpectedToken(meta, Messages.InvalidEscapedReservedWord);
          }
        }
      } else {
        match = false;
      }
      this.scanner.restoreState(state);
    }
    return match;
  }
  parseImportMeta() {
    const node = this.createNode();
    const id = this.parseIdentifierName();
    this.expect(".");
    const property = this.parseIdentifierName();
    this.context.isAssignmentTarget = false;
    return this.finalize(node, new MetaProperty(id, property));
  }
  parseLeftHandSideExpressionAllowCall() {
    const startToken = this.lookahead;
    const maybeAsync = this.matchContextualKeyword("async");
    const previousAllowIn = this.context.allowIn;
    this.context.allowIn = true;
    let expr;
    const isSuper = this.matchKeyword("super");
    if (isSuper && this.context.inFunctionBody) {
      expr = this.createNode();
      this.nextToken();
      expr = this.finalize(expr, new Super());
      if (!this.match("(") && !this.match(".") && !this.match("[")) {
        this.throwUnexpectedToken(this.lookahead);
      }
    } else {
      expr = this.inheritCoverGrammar(this.matchKeyword("new") ? this.parseNewExpression : this.parsePrimaryExpression);
    }
    if (isSuper && this.match("(") && (!this.context.inClassConstructor || !this.context.allowSuper)) {
      this.tolerateError(Messages.UnexpectedSuper);
    }
    let hasOptional = false;
    while (true) {
      let optional = false;
      if (this.match("?.")) {
        optional = true;
        hasOptional = true;
        this.expect("?.");
      }
      if (this.match("(")) {
        const asyncArrow = maybeAsync && startToken.lineNumber === this.lookahead.lineNumber;
        this.context.isBindingElement = false;
        this.context.isAssignmentTarget = false;
        const args = asyncArrow ? this.parseAsyncArguments() : this.parseArguments();
        if (expr.type === "ImportExpression" /* ImportExpression */ && args.length !== 1) {
          this.tolerateError(Messages.BadImportCallArity);
        }
        expr = this.finalize(this.startNode(startToken), new CallExpression(expr, args, optional));
        if (asyncArrow && this.match("=>")) {
          for (let i = 0; i < args.length; ++i) {
            this.reinterpretExpressionAsPattern(args[i]);
          }
          expr = {
            type: ArrowParameterPlaceHolder,
            params: args,
            async: true
          };
        }
      } else if (this.match("[")) {
        this.context.isBindingElement = false;
        this.context.isAssignmentTarget = !optional;
        this.expect("[");
        const property = this.isolateCoverGrammar(this.parseExpression);
        this.expect("]");
        expr = this.finalize(this.startNode(startToken), new MemberExpression(true, expr, property, optional));
      } else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) {
        if (optional) {
          this.throwUnexpectedToken(this.lookahead);
        }
        if (hasOptional) {
          this.throwError(Messages.InvalidTaggedTemplateOnOptionalChain);
        }
        const quasi = this.parseTemplateLiteral({ isTagged: true });
        expr = this.finalize(this.startNode(startToken), new TaggedTemplateExpression(expr, quasi));
      } else if (this.match(".") || optional) {
        this.context.isBindingElement = false;
        this.context.isAssignmentTarget = !optional;
        if (!optional) {
          this.expect(".");
        }
        const property = this.parseIdentifierName(true);
        expr = this.finalize(this.startNode(startToken), new MemberExpression(false, expr, property, optional));
      } else {
        break;
      }
    }
    this.context.allowIn = previousAllowIn;
    if (hasOptional) {
      expr = this.finalize(this.startNode(startToken), new ChainExpression(expr));
    }
    return expr;
  }
  parseSuper() {
    const node = this.createNode();
    this.expectKeyword("super");
    if (!this.match("[") && !this.match(".")) {
      this.throwUnexpectedToken(this.lookahead);
    }
    return this.finalize(node, new Super());
  }
  parseLeftHandSideExpression() {
    assert(this.context.allowIn, "callee of new expression always allow in keyword.");
    const node = this.startNode(this.lookahead);
    let expr = this.matchKeyword("super") && this.context.inFunctionBody ? this.parseSuper() : this.inheritCoverGrammar(this.matchKeyword("new") ? this.parseNewExpression : this.parsePrimaryExpression);
    let hasOptional = false;
    while (true) {
      let optional = false;
      if (this.match("?.")) {
        optional = true;
        hasOptional = true;
        this.expect("?.");
      }
      if (this.match("[")) {
        this.context.isBindingElement = false;
        this.context.isAssignmentTarget = !optional;
        this.expect("[");
        const property = this.isolateCoverGrammar(this.parseExpression);
        this.expect("]");
        expr = this.finalize(node, new MemberExpression(true, expr, property, optional));
      } else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) {
        if (optional) {
          this.throwUnexpectedToken(this.lookahead);
        }
        if (hasOptional) {
          this.throwError(Messages.InvalidTaggedTemplateOnOptionalChain);
        }
        const quasi = this.parseTemplateLiteral({ isTagged: true });
        expr = this.finalize(node, new TaggedTemplateExpression(expr, quasi));
      } else if (this.match(".") || optional) {
        this.context.isBindingElement = false;
        this.context.isAssignmentTarget = !optional;
        if (!optional) {
          this.expect(".");
        }
        const property = this.parseIdentifierName();
        expr = this.finalize(node, new MemberExpression(false, expr, property, optional));
      } else {
        break;
      }
    }
    if (hasOptional) {
      expr = this.finalize(node, new ChainExpression(expr));
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-update-expressions
  parseUpdateExpression() {
    let expr;
    const startToken = this.lookahead;
    if (this.match("++") || this.match("--")) {
      const node = this.startNode(startToken);
      const token = this.nextToken();
      expr = this.inheritCoverGrammar(this.parseUnaryExpression);
      if (this.context.strict && expr.type === "Identifier" /* Identifier */ && this.scanner.isRestrictedWord(expr.name)) {
        this.tolerateError(Messages.StrictLHSPrefix);
      }
      if (!this.context.isAssignmentTarget) {
        this.tolerateError(Messages.InvalidLHSInAssignment);
      }
      const prefix = true;
      expr = this.finalize(node, new UpdateExpression(token.value, expr, prefix));
      this.context.isAssignmentTarget = false;
      this.context.isBindingElement = false;
    } else {
      expr = this.inheritCoverGrammar(this.parseLeftHandSideExpressionAllowCall);
      if (!this.hasLineTerminator && this.lookahead.type === 7 /* Punctuator */) {
        if (this.match("++") || this.match("--")) {
          if (this.context.strict && expr.type === "Identifier" /* Identifier */ && this.scanner.isRestrictedWord(expr.name)) {
            this.tolerateError(Messages.StrictLHSPostfix);
          }
          if (!this.context.isAssignmentTarget) {
            this.tolerateError(Messages.InvalidLHSInAssignment);
          }
          this.context.isAssignmentTarget = false;
          this.context.isBindingElement = false;
          const operator = this.nextToken().value;
          const prefix = false;
          expr = this.finalize(this.startNode(startToken), new UpdateExpression(operator, expr, prefix));
        }
      }
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-unary-operators
  parseAwaitExpression() {
    const node = this.createNode();
    this.nextToken();
    const argument = this.parseUnaryExpression();
    return this.finalize(node, new AwaitExpression(argument));
  }
  parseUnaryExpression() {
    let expr;
    if (this.match("+") || this.match("-") || this.match("~") || this.match("!") || this.matchKeyword("delete") || this.matchKeyword("void") || this.matchKeyword("typeof")) {
      const node = this.startNode(this.lookahead);
      const token = this.nextToken();
      expr = this.inheritCoverGrammar(this.parseUnaryExpression);
      expr = this.finalize(node, new UnaryExpression(token.value, expr));
      if (this.context.strict && expr.operator === "delete" && expr.argument.type === "Identifier" /* Identifier */) {
        this.tolerateError(Messages.StrictDelete);
      }
      this.context.isAssignmentTarget = false;
      this.context.isBindingElement = false;
    } else if ((this.context.isModule && !this.context.inFunctionBody || this.context.isAsync) && this.matchContextualKeyword("await")) {
      expr = this.parseAwaitExpression();
    } else {
      expr = this.parseUpdateExpression();
    }
    return expr;
  }
  parseExponentiationExpression() {
    const startToken = this.lookahead;
    const isLeftParenthesized = this.match("(");
    let expr = this.inheritCoverGrammar(this.parseUnaryExpression);
    const exponentAllowed = expr.type !== "UnaryExpression" /* UnaryExpression */ || isLeftParenthesized;
    if (exponentAllowed && this.match("**")) {
      this.nextToken();
      this.context.isAssignmentTarget = false;
      this.context.isBindingElement = false;
      const left = expr;
      const right = this.isolateCoverGrammar(this.parseExponentiationExpression);
      expr = this.finalize(this.startNode(startToken), new BinaryExpression("**", left, right));
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-exp-operator
  // https://tc39.github.io/ecma262/#sec-multiplicative-operators
  // https://tc39.github.io/ecma262/#sec-additive-operators
  // https://tc39.github.io/ecma262/#sec-bitwise-shift-operators
  // https://tc39.github.io/ecma262/#sec-relational-operators
  // https://tc39.github.io/ecma262/#sec-equality-operators
  // https://tc39.github.io/ecma262/#sec-binary-bitwise-operators
  // https://tc39.github.io/ecma262/#sec-binary-logical-operators
  binaryPrecedence(token) {
    const op = token.value;
    let precedence;
    if (token.type === 7 /* Punctuator */) {
      precedence = this.operatorPrecedence[op] || 0;
    } else if (token.type === 4 /* Keyword */) {
      precedence = op === "instanceof" || this.context.allowIn && op === "in" ? 12 : 0;
    } else {
      precedence = 0;
    }
    return precedence;
  }
  parseBinaryExpression() {
    const startToken = this.lookahead;
    let expr = this.inheritCoverGrammar(this.parseExponentiationExpression);
    let allowAndOr = true;
    let allowNullishCoalescing = true;
    const updateNullishCoalescingRestrictions = (token2) => {
      if (token2.value === "&&" || token2.value === "||") {
        allowNullishCoalescing = false;
      }
      if (token2.value === "??") {
        allowAndOr = false;
      }
    };
    const token = this.lookahead;
    let prec = this.binaryPrecedence(token);
    if (prec > 0) {
      updateNullishCoalescingRestrictions(token);
      this.nextToken();
      this.context.isAssignmentTarget = false;
      this.context.isBindingElement = false;
      const markers = [startToken, this.lookahead];
      let left = expr;
      let right = this.isolateCoverGrammar(this.parseExponentiationExpression);
      const stack = [left, token.value, right];
      const precedences = [prec];
      while (true) {
        prec = this.binaryPrecedence(this.lookahead);
        if (prec <= 0) {
          break;
        }
        if (!allowAndOr && (this.lookahead.value === "&&" || this.lookahead.value === "||") || !allowNullishCoalescing && this.lookahead.value === "??") {
          this.throwUnexpectedToken(this.lookahead);
        }
        updateNullishCoalescingRestrictions(this.lookahead);
        while (stack.length > 2 && prec <= precedences[precedences.length - 1]) {
          right = stack.pop();
          const operator = stack.pop();
          precedences.pop();
          left = stack.pop();
          markers.pop();
          const marker = markers[markers.length - 1];
          const node = this.startNode(marker, marker.lineStart);
          const logical = operator === "||" || operator === "&&" || operator === "??";
          stack.push(this.finalize(node, logical ? new LogicalExpression(operator, left, right) : new BinaryExpression(operator, left, right)));
        }
        stack.push(this.nextToken().value);
        precedences.push(prec);
        markers.push(this.lookahead);
        stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression));
      }
      let i = stack.length - 1;
      expr = stack[i];
      let lastMarker = markers.pop();
      while (i > 1) {
        const marker = markers.pop();
        const lastLineStart = lastMarker && lastMarker.lineStart;
        const node = this.startNode(marker, lastLineStart);
        const operator = stack[i - 1];
        const logical = operator === "||" || operator === "&&" || operator === "??";
        expr = this.finalize(node, logical ? new LogicalExpression(operator, stack[i - 2], expr) : new BinaryExpression(operator, stack[i - 2], expr));
        i -= 2;
        lastMarker = marker;
      }
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-conditional-operator
  parseConditionalExpression() {
    const startToken = this.lookahead;
    let expr = this.inheritCoverGrammar(this.parseBinaryExpression);
    if (this.match("?")) {
      this.nextToken();
      const previousAllowIn = this.context.allowIn;
      this.context.allowIn = true;
      const consequent = this.isolateCoverGrammar(this.parseAssignmentExpression);
      this.context.allowIn = previousAllowIn;
      this.expect(":");
      const alternate = this.isolateCoverGrammar(this.parseAssignmentExpression);
      expr = this.finalize(this.startNode(startToken), new ConditionalExpression(expr, consequent, alternate));
      this.context.isAssignmentTarget = false;
      this.context.isBindingElement = false;
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-assignment-operators
  checkPatternParam(options, param) {
    switch (param.type) {
      case "Identifier" /* Identifier */:
        this.validateParam(options, param, param.name);
        break;
      case "RestElement" /* RestElement */:
        this.checkPatternParam(options, param.argument);
        break;
      case "AssignmentPattern" /* AssignmentPattern */:
        this.checkPatternParam(options, param.left);
        break;
      case "ArrayPattern" /* ArrayPattern */:
        for (let i = 0; i < param.elements.length; i++) {
          if (param.elements[i] !== null) {
            this.checkPatternParam(options, param.elements[i]);
          }
        }
        break;
      case "ObjectPattern" /* ObjectPattern */:
        for (let i = 0; i < param.properties.length; i++) {
          const property = param.properties[i];
          this.checkPatternParam(options, property.type === "RestElement" /* RestElement */ ? property : property.value);
        }
        break;
      default:
        break;
    }
    options.simple = options.simple && param instanceof Identifier;
  }
  reinterpretAsCoverFormalsList(expr) {
    let params = [expr];
    const options = {
      simple: true,
      paramSet: {}
    };
    let asyncArrow = false;
    switch (expr.type) {
      case "Identifier" /* Identifier */:
        break;
      case ArrowParameterPlaceHolder:
        params = expr.params;
        asyncArrow = expr.async;
        break;
      default:
        return null;
    }
    for (let i = 0; i < params.length; ++i) {
      const param = params[i];
      if (param.type === "AssignmentPattern" /* AssignmentPattern */) {
        if (param.right.type === "YieldExpression" /* YieldExpression */) {
          if (param.right.argument) {
            this.throwUnexpectedToken(this.lookahead);
          }
          param.right.type = "Identifier" /* Identifier */;
          param.right.name = "yield";
          delete param.right.argument;
          delete param.right.delegate;
        }
      } else if (asyncArrow && param.type === "Identifier" /* Identifier */ && param.name === "await") {
        this.throwUnexpectedToken(this.lookahead);
      }
      this.checkPatternParam(options, param);
      params[i] = param;
    }
    if (this.context.strict || !this.context.allowYield) {
      for (let i = 0; i < params.length; ++i) {
        const param = params[i];
        if (param.type === "YieldExpression" /* YieldExpression */) {
          this.throwUnexpectedToken(this.lookahead);
        }
      }
    }
    if (options.hasDuplicateParameterNames) {
      const token = this.context.strict ? options.stricted : options.firstRestricted;
      this.throwUnexpectedToken(token, Messages.DuplicateParameter);
    }
    return {
      simple: options.simple,
      params,
      stricted: options.stricted,
      firstRestricted: options.firstRestricted,
      message: options.message
    };
  }
  parseAssignmentExpression() {
    let expr;
    if (!this.context.allowYield && this.matchKeyword("yield")) {
      expr = this.parseYieldExpression();
    } else {
      const startToken = this.lookahead;
      let token = startToken;
      expr = this.parseConditionalExpression();
      if (token.type === 3 /* Identifier */ && token.lineNumber === this.lookahead.lineNumber && token.value === "async") {
        if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword("yield")) {
          const arg = this.parsePrimaryExpression();
          this.reinterpretExpressionAsPattern(arg);
          expr = {
            type: ArrowParameterPlaceHolder,
            params: [arg],
            async: true
          };
        }
      }
      if (expr.type === ArrowParameterPlaceHolder || this.match("=>")) {
        this.context.isAssignmentTarget = false;
        this.context.isBindingElement = false;
        const isAsync = expr.async;
        const list = this.reinterpretAsCoverFormalsList(expr);
        if (list) {
          if (this.hasLineTerminator) {
            this.tolerateUnexpectedToken(this.lookahead);
          }
          this.context.firstCoverInitializedNameError = null;
          const previousStrict = this.context.strict;
          const previousAllowStrictDirective = this.context.allowStrictDirective;
          this.context.allowStrictDirective = list.simple;
          const previousAllowYield = this.context.allowYield;
          const previousIsAsync = this.context.isAsync;
          this.context.allowYield = true;
          this.context.isAsync = isAsync;
          const node = this.startNode(startToken);
          this.expect("=>");
          let body;
          if (this.match("{")) {
            const previousAllowIn = this.context.allowIn;
            this.context.allowIn = true;
            body = this.parseFunctionSourceElements();
            this.context.allowIn = previousAllowIn;
          } else {
            body = this.isolateCoverGrammar(this.parseAssignmentExpression);
          }
          const expression = body.type !== "BlockStatement" /* BlockStatement */;
          if (this.context.strict && list.firstRestricted) {
            this.throwUnexpectedToken(list.firstRestricted, list.message);
          }
          if (this.context.strict && list.stricted) {
            this.tolerateUnexpectedToken(list.stricted, list.message);
          }
          expr = this.finalize(node, new ArrowFunctionExpression(list.params, body, expression, isAsync));
          this.context.strict = previousStrict;
          this.context.allowStrictDirective = previousAllowStrictDirective;
          this.context.allowYield = previousAllowYield;
          this.context.isAsync = previousIsAsync;
        }
      } else {
        if (this.matchAssign()) {
          if (!this.context.isAssignmentTarget) {
            this.tolerateError(Messages.InvalidLHSInAssignment);
          }
          if (this.context.strict && expr.type === "Identifier" /* Identifier */) {
            const id = expr;
            if (this.scanner.isRestrictedWord(id.name)) {
              this.tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
            }
            if (this.scanner.isStrictModeReservedWord(id.name)) {
              this.tolerateUnexpectedToken(token, Messages.StrictReservedWord);
            }
          }
          if (!this.match("=")) {
            this.context.isAssignmentTarget = false;
            this.context.isBindingElement = false;
          } else {
            this.reinterpretExpressionAsPattern(expr);
          }
          token = this.nextToken();
          const operator = token.value;
          const right = this.isolateCoverGrammar(this.parseAssignmentExpression);
          expr = this.finalize(this.startNode(startToken), new AssignmentExpression(operator, expr, right));
          this.context.firstCoverInitializedNameError = null;
        }
      }
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-comma-operator
  parseExpression() {
    const startToken = this.lookahead;
    let expr = this.isolateCoverGrammar(this.parseAssignmentExpression);
    if (this.match(",")) {
      const expressions = [];
      expressions.push(expr);
      while (this.lookahead.type !== 2 /* EOF */) {
        if (!this.match(",")) {
          break;
        }
        this.nextToken();
        expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression));
      }
      expr = this.finalize(this.startNode(startToken), new SequenceExpression(expressions));
    }
    return expr;
  }
  // https://tc39.github.io/ecma262/#sec-block
  parseStatementListItem() {
    let statement;
    this.context.isAssignmentTarget = true;
    this.context.isBindingElement = true;
    if (this.lookahead.type === 4 /* Keyword */) {
      switch (this.lookahead.value) {
        case "export":
          if (!this.context.isModule) {
            this.tolerateUnexpectedToken(this.lookahead, Messages.IllegalExportDeclaration);
          }
          statement = this.parseExportDeclaration();
          break;
        case "import":
          if (this.matchImportCall()) {
            statement = this.parseExpressionStatement();
          } else if (this.matchImportMeta()) {
            statement = this.parseStatement();
          } else {
            if (!this.context.isModule) {
              this.tolerateUnexpectedToken(this.lookahead, Messages.IllegalImportDeclaration);
            }
            statement = this.parseImportDeclaration();
          }
          break;
        case "const":
          statement = this.parseLexicalDeclaration({ inFor: false });
          break;
        case "function":
          statement = this.parseFunctionDeclaration();
          break;
        case "class":
          statement = this.parseClassDeclaration();
          break;
        case "let":
          statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement();
          break;
        default:
          statement = this.parseStatement();
          break;
      }
    } else {
      statement = this.parseStatement();
    }
    return statement;
  }
  parseBlock() {
    const node = this.createNode();
    this.expect("{");
    const block = [];
    while (true) {
      if (this.match("}")) {
        break;
      }
      block.push(this.parseStatementListItem());
    }
    this.expect("}");
    return this.finalize(node, new BlockStatement(block));
  }
  // https://tc39.github.io/ecma262/#sec-let-and-const-declarations
  parseLexicalBinding(kind, options) {
    const node = this.createNode();
    const params = [];
    const id = this.parsePattern(params, kind);
    if (this.context.strict && id.type === "Identifier" /* Identifier */) {
      if (this.scanner.isRestrictedWord(id.name)) {
        this.tolerateError(Messages.StrictVarName);
      }
    }
    let init = null;
    if (kind === "const") {
      if (!this.matchKeyword("in") && !this.matchContextualKeyword("of")) {
        if (this.match("=")) {
          this.nextToken();
          init = this.isolateCoverGrammar(this.parseAssignmentExpression);
        } else {
          this.throwError(Messages.DeclarationMissingInitializer, "const");
        }
      }
    } else if (!options.inFor && id.type !== "Identifier" /* Identifier */ || this.match("=")) {
      this.expect("=");
      init = this.isolateCoverGrammar(this.parseAssignmentExpression);
    }
    return this.finalize(node, new VariableDeclarator(id, init));
  }
  parseBindingList(kind, options) {
    const list = [this.parseLexicalBinding(kind, options)];
    while (this.match(",")) {
      this.nextToken();
      list.push(this.parseLexicalBinding(kind, options));
    }
    return list;
  }
  isLexicalDeclaration() {
    const state = this.scanner.saveState();
    this.scanner.scanComments();
    const next = this.scanner.lex();
    this.scanner.restoreState(state);
    return next.type === 3 /* Identifier */ || next.type === 7 /* Punctuator */ && next.value === "[" || next.type === 7 /* Punctuator */ && next.value === "{" || next.type === 4 /* Keyword */ && next.value === "let" || next.type === 4 /* Keyword */ && next.value === "yield";
  }
  parseLexicalDeclaration(options) {
    const node = this.createNode();
    const kind = this.nextToken().value;
    assert(kind === "let" || kind === "const", "Lexical declaration must be either let or const");
    const declarations = this.parseBindingList(kind, options);
    this.consumeSemicolon();
    return this.finalize(node, new VariableDeclaration(declarations, kind));
  }
  /**
   * This function checks to see if a property is initialized in a Class
   * e.g.
   * publicProp = 123;
   * @returns {Boolean}
   */
  isInitializedProperty() {
    let state = this.scanner.saveState();
    this.scanner.scanComments();
    let next = this.scanner.lex();
    this.scanner.restoreState(state);
    return this.lookahead.type === 3 && next.value === "=";
  }
  /**
   * This function checks to see if a property is declared in a Class
   * e.g.
   * publicProp;
   * @returns {Boolean}
   */
  isDeclaredProperty() {
    let state = this.scanner.saveState();
    this.scanner.scanComments();
    let next = this.scanner.lex();
    this.scanner.restoreState(state);
    return this.lookahead.type === 3 && next.value === ";" || this.lookahead.type === 3 && next.lineNumber !== this.startMarker.line;
  }
  // https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns
  parseBindingRestElement(params, kind) {
    const node = this.createNode();
    this.expect("...");
    const arg = this.parsePattern(params, kind);
    return this.finalize(node, new RestElement(arg));
  }
  parseArrayPattern(params, kind) {
    const node = this.createNode();
    this.expect("[");
    const elements = [];
    while (!this.match("]")) {
      if (this.match(",")) {
        this.nextToken();
        elements.push(null);
      } else {
        if (this.match("...")) {
          elements.push(this.parseBindingRestElement(params, kind));
          break;
        } else {
          elements.push(this.parsePatternWithDefault(params, kind));
        }
        if (!this.match("]")) {
          this.expect(",");
        }
      }
    }
    this.expect("]");
    return this.finalize(node, new ArrayPattern(elements));
  }
  parsePropertyPattern(params, kind) {
    const node = this.createNode();
    let computed = false;
    let shorthand = false;
    const method = false;
    let key;
    let value;
    if (this.lookahead.type === 3 /* Identifier */) {
      const keyToken = this.lookahead;
      key = this.parseVariableIdentifier();
      const init = this.finalize(node, new Identifier(keyToken.value));
      if (this.match("=")) {
        params.push(keyToken);
        shorthand = true;
        this.nextToken();
        const expr = this.parseAssignmentExpression();
        value = this.finalize(this.startNode(keyToken), new AssignmentPattern(init, expr));
      } else if (!this.match(":")) {
        params.push(keyToken);
        shorthand = true;
        value = init;
      } else {
        this.expect(":");
        value = this.parsePatternWithDefault(params, kind);
      }
    } else {
      computed = this.match("[");
      key = this.parseObjectPropertyKey();
      this.expect(":");
      value = this.parsePatternWithDefault(params, kind);
    }
    return this.finalize(node, new Property("init", key, computed, value, method, shorthand));
  }
  parseRestProperty(params) {
    const node = this.createNode();
    this.expect("...");
    const arg = this.parsePattern(params);
    if (this.match("=")) {
      this.throwError(Messages.DefaultRestProperty);
    }
    if (!this.match("}")) {
      this.throwError(Messages.PropertyAfterRestProperty);
    }
    return this.finalize(node, new RestElement(arg));
  }
  parseObjectPattern(params, kind) {
    const node = this.createNode();
    const properties = [];
    this.expect("{");
    while (!this.match("}")) {
      properties.push(this.match("...") ? this.parseRestProperty(params) : this.parsePropertyPattern(params, kind));
      if (!this.match("}")) {
        this.expect(",");
      }
    }
    this.expect("}");
    return this.finalize(node, new ObjectPattern(properties));
  }
  parsePattern(params, kind) {
    let pattern;
    if (this.match("[")) {
      pattern = this.parseArrayPattern(params, kind);
    } else if (this.match("{")) {
      pattern = this.parseObjectPattern(params, kind);
    } else {
      if (this.matchKeyword("let") && (kind === "const" || kind === "let")) {
        this.tolerateUnexpectedToken(this.lookahead, Messages.LetInLexicalBinding);
      }
      params.push(this.lookahead);
      pattern = this.parseVariableIdentifier(kind);
    }
    return pattern;
  }
  parsePatternWithDefault(params, kind) {
    const startToken = this.lookahead;
    let pattern = this.parsePattern(params, kind);
    if (this.match("=")) {
      this.nextToken();
      const previousAllowYield = this.context.allowYield;
      this.context.allowYield = true;
      const right = this.isolateCoverGrammar(this.parseAssignmentExpression);
      this.context.allowYield = previousAllowYield;
      pattern = this.finalize(this.startNode(startToken), new AssignmentPattern(pattern, right));
    }
    return pattern;
  }
  // https://tc39.github.io/ecma262/#sec-variable-statement
  parseVariableIdentifier(kind) {
    const node = this.createNode();
    const token = this.nextToken();
    if (token.type === 4 /* Keyword */ && token.value === "yield") {
      if (this.context.strict) {
        this.tolerateUnexpectedToken(token, Messages.StrictReservedWord);
      } else if (!this.context.allowYield) {
        this.throwUnexpectedToken(token);
      }
    } else if (token.type !== 3 /* Identifier */) {
      if (this.context.strict && token.type === 4 /* Keyword */ && this.scanner.isStrictModeReservedWord(token.value)) {
        this.tolerateUnexpectedToken(token, Messages.StrictReservedWord);
      } else {
        if (this.context.strict || token.value !== "let" || kind !== "var") {
          this.throwUnexpectedToken(token);
        }
      }
    } else if ((this.context.isModule || this.context.isAsync) && token.type === 3 /* Identifier */ && token.value === "await") {
      this.tolerateUnexpectedToken(token);
    }
    return this.finalize(node, new Identifier(token.value));
  }
  parseVariableDeclaration(options) {
    const node = this.createNode();
    const params = [];
    const id = this.parsePattern(params, "var");
    if (this.context.strict && id.type === "Identifier" /* Identifier */) {
      if (this.scanner.isRestrictedWord(id.name)) {
        this.tolerateError(Messages.StrictVarName);
      }
    }
    let init = null;
    if (this.match("=")) {
      this.nextToken();
      init = this.isolateCoverGrammar(this.parseAssignmentExpression);
    } else if (id.type !== "Identifier" /* Identifier */ && !options.inFor) {
      this.expect("=");
    }
    return this.finalize(node, new VariableDeclarator(id, init));
  }
  parseVariableDeclarationList(options) {
    const opt = { inFor: options.inFor };
    const list = [];
    list.push(this.parseVariableDeclaration(opt));
    while (this.match(",")) {
      this.nextToken();
      list.push(this.parseVariableDeclaration(opt));
    }
    return list;
  }
  parseVariableStatement() {
    const node = this.createNode();
    this.expectKeyword("var");
    const declarations = this.parseVariableDeclarationList({ inFor: false });
    this.consumeSemicolon();
    return this.finalize(node, new VariableDeclaration(declarations, "var"));
  }
  // https://tc39.github.io/ecma262/#sec-empty-statement
  parseEmptyStatement() {
    const node = this.createNode();
    this.expect(";");
    return this.finalize(node, new EmptyStatement());
  }
  // https://tc39.github.io/ecma262/#sec-expression-statement
  parseExpressionStatement() {
    const node = this.createNode();
    const expr = this.parseExpression();
    this.consumeSemicolon();
    return this.finalize(node, new ExpressionStatement(expr));
  }
  // https://tc39.github.io/ecma262/#sec-if-statement
  parseIfClause() {
    if (this.context.strict && this.matchKeyword("function")) {
      this.tolerateError(Messages.StrictFunction);
    }
    return this.parseStatement();
  }
  parseIfStatement() {
    const node = this.createNode();
    let consequent;
    let alternate = null;
    this.expectKeyword("if");
    this.expect("(");
    const test = this.parseExpression();
    if (!this.match(")") && this.config.tolerant) {
      this.tolerateUnexpectedToken(this.nextToken());
      consequent = this.finalize(this.createNode(), new EmptyStatement());
    } else {
      this.expect(")");
      consequent = this.parseIfClause();
      if (this.matchKeyword("else")) {
        this.nextToken();
        alternate = this.parseIfClause();
      }
    }
    return this.finalize(node, new IfStatement(test, consequent, alternate));
  }
  // https://tc39.github.io/ecma262/#sec-do-while-statement
  parseDoWhileStatement() {
    const node = this.createNode();
    this.expectKeyword("do");
    this.tolerateInvalidLoopStatement();
    const previousInIteration = this.context.inIteration;
    this.context.inIteration = true;
    const body = this.parseStatement();
    this.context.inIteration = previousInIteration;
    this.expectKeyword("while");
    this.expect("(");
    const test = this.parseExpression();
    if (!this.match(")") && this.config.tolerant) {
      this.tolerateUnexpectedToken(this.nextToken());
    } else {
      this.expect(")");
      if (this.match(";")) {
        this.nextToken();
      }
    }
    return this.finalize(node, new DoWhileStatement(body, test));
  }
  // https://tc39.github.io/ecma262/#sec-while-statement
  parseWhileStatement() {
    const node = this.createNode();
    let body;
    this.expectKeyword("while");
    this.expect("(");
    const test = this.parseExpression();
    if (!this.match(")") && this.config.tolerant) {
      this.tolerateUnexpectedToken(this.nextToken());
      body = this.finalize(this.createNode(), new EmptyStatement());
    } else {
      this.expect(")");
      const previousInIteration = this.context.inIteration;
      this.context.inIteration = true;
      body = this.parseStatement();
      this.context.inIteration = previousInIteration;
    }
    return this.finalize(node, new WhileStatement(test, body));
  }
  // https://tc39.github.io/ecma262/#sec-for-statement
  // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements
  parseForStatement() {
    let init = null;
    let test = null;
    let update = null;
    let forIn = true;
    let left, right;
    let _await = false;
    const node = this.createNode();
    this.expectKeyword("for");
    if (this.matchContextualKeyword("await")) {
      if (!this.context.isAsync) {
        this.tolerateUnexpectedToken(this.lookahead);
      }
      _await = true;
      this.nextToken();
    }
    this.expect("(");
    if (this.match(";")) {
      this.nextToken();
    } else {
      if (this.matchKeyword("var")) {
        init = this.createNode();
        this.nextToken();
        const previousAllowIn = this.context.allowIn;
        this.context.allowIn = false;
        const declarations = this.parseVariableDeclarationList({ inFor: true });
        this.context.allowIn = previousAllowIn;
        if (!_await && declarations.length === 1 && this.matchKeyword("in")) {
          const decl = declarations[0];
          if (decl.init && (decl.id.type === "ArrayPattern" /* ArrayPattern */ || decl.id.type === "ObjectPattern" /* ObjectPattern */ || this.context.strict)) {
            this.tolerateError(Messages.ForInOfLoopInitializer, "for-in");
          }
          init = this.finalize(init, new VariableDeclaration(declarations, "var"));
          this.nextToken();
          left = init;
          right = this.parseExpression();
          init = null;
        } else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword("of")) {
          init = this.finalize(init, new VariableDeclaration(declarations, "var"));
          this.nextToken();
          left = init;
          right = this.parseAssignmentExpression();
          init = null;
          forIn = false;
        } else {
          init = this.finalize(init, new VariableDeclaration(declarations, "var"));
          this.expect(";");
        }
      } else if (this.matchKeyword("const") || this.matchKeyword("let")) {
        init = this.createNode();
        const kind = this.nextToken().value;
        if (!this.context.strict && this.lookahead.value === "in") {
          init = this.finalize(init, new Identifier(kind));
          this.nextToken();
          left = init;
          right = this.parseExpression();
          init = null;
        } else {
          const previousAllowIn = this.context.allowIn;
          this.context.allowIn = false;
          const declarations = this.parseBindingList(kind, { inFor: true });
          this.context.allowIn = previousAllowIn;
          if (declarations.length === 1 && declarations[0].init === null && this.matchKeyword("in")) {
            init = this.finalize(init, new VariableDeclaration(declarations, kind));
            this.nextToken();
            left = init;
            right = this.parseExpression();
            init = null;
          } else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword("of")) {
            init = this.finalize(init, new VariableDeclaration(declarations, kind));
            this.nextToken();
            left = init;
            right = this.parseAssignmentExpression();
            init = null;
            forIn = false;
          } else {
            this.consumeSemicolon();
            init = this.finalize(init, new VariableDeclaration(declarations, kind));
          }
        }
      } else {
        const initStartToken = this.lookahead;
        const previousIsBindingElement = this.context.isBindingElement;
        const previousIsAssignmentTarget = this.context.isAssignmentTarget;
        const previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError;
        const previousAllowIn = this.context.allowIn;
        this.context.allowIn = false;
        init = this.inheritCoverGrammar(this.parseAssignmentExpression);
        this.context.allowIn = previousAllowIn;
        if (this.matchKeyword("in")) {
          if (!this.context.isAssignmentTarget || init.type === "AssignmentExpression" /* AssignmentExpression */) {
            this.tolerateError(Messages.InvalidLHSInForIn);
          }
          this.nextToken();
          this.reinterpretExpressionAsPattern(init);
          left = init;
          right = this.parseExpression();
          init = null;
        } else if (this.matchContextualKeyword("of")) {
          if (!this.context.isAssignmentTarget || init.type === "AssignmentExpression" /* AssignmentExpression */) {
            this.tolerateError(Messages.InvalidLHSInForLoop);
          }
          this.nextToken();
          this.reinterpretExpressionAsPattern(init);
          left = init;
          right = this.parseAssignmentExpression();
          init = null;
          forIn = false;
        } else {
          this.context.isBindingElement = previousIsBindingElement;
          this.context.isAssignmentTarget = previousIsAssignmentTarget;
          this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError;
          if (this.match(",")) {
            const initSeq = [init];
            while (this.match(",")) {
              this.nextToken();
              initSeq.push(this.isolateCoverGrammar(this.parseAssignmentExpression));
            }
            init = this.finalize(this.startNode(initStartToken), new SequenceExpression(initSeq));
          }
          this.expect(";");
        }
      }
    }
    if (typeof left === "undefined") {
      if (!this.match(";")) {
        test = this.isolateCoverGrammar(this.parseExpression);
      }
      this.expect(";");
      if (!this.match(")")) {
        update = this.isolateCoverGrammar(this.parseExpression);
      }
    }
    let body;
    if (!this.match(")") && this.config.tolerant) {
      this.tolerateUnexpectedToken(this.nextToken());
      body = this.finalize(this.createNode(), new EmptyStatement());
    } else {
      this.expect(")");
      this.tolerateInvalidLoopStatement();
      const previousInIteration = this.context.inIteration;
      this.context.inIteration = true;
      body = this.isolateCoverGrammar(this.parseStatement);
      this.context.inIteration = previousInIteration;
    }
    return typeof left === "undefined" ? this.finalize(node, new ForStatement(init, test, update, body)) : forIn ? this.finalize(node, new ForInStatement(left, right, body)) : this.finalize(node, new ForOfStatement(left, right, body, _await));
  }
  // https://tc39.github.io/ecma262/#sec-continue-statement
  parseContinueStatement() {
    const node = this.createNode();
    this.expectKeyword("continue");
    let label = null;
    if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) {
      const id = this.parseVariableIdentifier();
      label = id;
      const key = "$" + id.name;
      if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) {
        this.throwError(Messages.UnknownLabel, id.name);
      }
    }
    this.consumeSemicolon();
    if (label === null && !this.context.inIteration) {
      this.throwError(Messages.IllegalContinue);
    }
    return this.finalize(node, new ContinueStatement(label));
  }
  // https://tc39.github.io/ecma262/#sec-break-statement
  parseBreakStatement() {
    const node = this.createNode();
    this.expectKeyword("break");
    let label = null;
    if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) {
      const id = this.parseVariableIdentifier();
      const key = "$" + id.name;
      if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) {
        this.throwError(Messages.UnknownLabel, id.name);
      }
      label = id;
    }
    this.consumeSemicolon();
    if (label === null && !this.context.inIteration && !this.context.inSwitch) {
      this.throwError(Messages.IllegalBreak);
    }
    return this.finalize(node, new BreakStatement(label));
  }
  // https://tc39.github.io/ecma262/#sec-return-statement
  parseReturnStatement() {
    if (!this.context.inFunctionBody) {
      this.tolerateError(Messages.IllegalReturn);
    }
    const node = this.createNode();
    this.expectKeyword("return");
    const hasArgument = !this.match(";") && !this.match("}") && !this.hasLineTerminator && this.lookahead.type !== 2 /* EOF */ || this.lookahead.type === 8 /* StringLiteral */ || this.lookahead.type === 10 /* Template */;
    const argument = hasArgument ? this.parseExpression() : null;
    this.consumeSemicolon();
    return this.finalize(node, new ReturnStatement(argument));
  }
  // https://tc39.github.io/ecma262/#sec-with-statement
  parseWithStatement() {
    if (this.context.strict) {
      this.tolerateError(Messages.StrictModeWith);
    }
    const node = this.createNode();
    let body;
    this.expectKeyword("with");
    this.expect("(");
    const object = this.parseExpression();
    if (!this.match(")") && this.config.tolerant) {
      this.tolerateUnexpectedToken(this.nextToken());
      body = this.finalize(this.createNode(), new EmptyStatement());
    } else {
      this.expect(")");
      body = this.parseStatement();
    }
    return this.finalize(node, new WithStatement(object, body));
  }
  // https://tc39.github.io/ecma262/#sec-switch-statement
  parseSwitchCase() {
    const node = this.createNode();
    let test;
    if (this.matchKeyword("default")) {
      this.nextToken();
      test = null;
    } else {
      this.expectKeyword("case");
      test = this.parseExpression();
    }
    this.expect(":");
    const consequent = [];
    while (true) {
      if (this.match("}") || this.matchKeyword("default") || this.matchKeyword("case")) {
        break;
      }
      consequent.push(this.parseStatementListItem());
    }
    return this.finalize(node, new SwitchCase(test, consequent));
  }
  parseSwitchStatement() {
    const node = this.createNode();
    this.expectKeyword("switch");
    this.expect("(");
    const discriminant = this.parseExpression();
    this.expect(")");
    const previousInSwitch = this.context.inSwitch;
    this.context.inSwitch = true;
    const cases = [];
    let defaultFound = false;
    this.expect("{");
    while (true) {
      if (this.match("}")) {
        break;
      }
      const clause = this.parseSwitchCase();
      if (clause.test === null) {
        if (defaultFound) {
          this.throwError(Messages.MultipleDefaultsInSwitch);
        }
        defaultFound = true;
      }
      cases.push(clause);
    }
    this.expect("}");
    this.context.inSwitch = previousInSwitch;
    return this.finalize(node, new SwitchStatement(discriminant, cases));
  }
  // https://tc39.github.io/ecma262/#sec-labelled-statements
  parseLabelledStatement() {
    const node = this.createNode();
    const expr = this.parseExpression();
    let statement;
    if (expr.type === "Identifier" /* Identifier */ && this.match(":")) {
      this.nextToken();
      const id = expr;
      const key = "$" + id.name;
      if (Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) {
        this.throwError(Messages.Redeclaration, "Label", id.name);
      }
      this.context.labelSet[key] = true;
      let body;
      if (this.matchKeyword("class")) {
        this.tolerateUnexpectedToken(this.lookahead);
        body = this.parseClassDeclaration();
      } else if (this.matchKeyword("function")) {
        const token = this.lookahead;
        const declaration = this.parseFunctionDeclaration();
        if (this.context.strict) {
          this.tolerateUnexpectedToken(token, Messages.StrictFunction);
        } else if (declaration.generator) {
          this.tolerateUnexpectedToken(token, Messages.GeneratorInLegacyContext);
        }
        body = declaration;
      } else {
        body = this.parseStatement();
      }
      delete this.context.labelSet[key];
      statement = new LabeledStatement(id, body);
    } else {
      this.consumeSemicolon();
      statement = new ExpressionStatement(expr);
    }
    return this.finalize(node, statement);
  }
  // https://tc39.github.io/ecma262/#sec-throw-statement
  parseThrowStatement() {
    const node = this.createNode();
    this.expectKeyword("throw");
    if (this.hasLineTerminator) {
      this.throwError(Messages.NewlineAfterThrow);
    }
    const argument = this.parseExpression();
    this.consumeSemicolon();
    return this.finalize(node, new ThrowStatement(argument));
  }
  // https://tc39.github.io/ecma262/#sec-try-statement
  parseCatchClause() {
    const node = this.createNode();
    this.expectKeyword("catch");
    let param = null;
    if (this.match("(")) {
      this.expect("(");
      if (this.match(")")) {
        this.throwUnexpectedToken(this.lookahead);
      }
      const params = [];
      param = this.parsePattern(params);
      const paramMap = {};
      for (let i = 0; i < params.length; i++) {
        const key = "$" + params[i].value;
        if (Object.prototype.hasOwnProperty.call(paramMap, key)) {
          this.tolerateError(Messages.DuplicateBinding, params[i].value);
        }
        paramMap[key] = true;
      }
      if (this.context.strict && param.type === "Identifier" /* Identifier */) {
        if (this.scanner.isRestrictedWord(param.name)) {
          this.tolerateError(Messages.StrictCatchVariable);
        }
      }
      this.expect(")");
    }
    const body = this.parseBlock();
    return this.finalize(node, new CatchClause(param, body));
  }
  parseFinallyClause() {
    this.expectKeyword("finally");
    return this.parseBlock();
  }
  parseTryStatement() {
    const node = this.createNode();
    this.expectKeyword("try");
    const block = this.parseBlock();
    const handler = this.matchKeyword("catch") ? this.parseCatchClause() : null;
    const finalizer = this.matchKeyword("finally") ? this.parseFinallyClause() : null;
    if (!handler && !finalizer) {
      this.throwError(Messages.NoCatchOrFinally);
    }
    return this.finalize(node, new TryStatement(block, handler, finalizer));
  }
  // https://tc39.github.io/ecma262/#sec-debugger-statement
  parseDebuggerStatement() {
    const node = this.createNode();
    this.expectKeyword("debugger");
    this.consumeSemicolon();
    return this.finalize(node, new DebuggerStatement());
  }
  // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations
  parseStatement() {
    let statement;
    switch (this.lookahead.type) {
      case 1 /* BooleanLiteral */:
      case 5 /* NullLiteral */:
      case 6 /* NumericLiteral */:
      case 8 /* StringLiteral */:
      case 10 /* Template */:
      case 9 /* RegularExpression */:
        statement = this.parseExpressionStatement();
        break;
      case 7 /* Punctuator */:
        const value = this.lookahead.value;
        if (value === "{") {
          statement = this.parseBlock();
        } else if (value === "(") {
          statement = this.parseExpressionStatement();
        } else if (value === ";") {
          statement = this.parseEmptyStatement();
        } else {
          statement = this.parseExpressionStatement();
        }
        break;
      case 3 /* Identifier */:
        statement = this.matchAsyncFunction() ? this.parseFunctionDeclaration() : this.parseLabelledStatement();
        break;
      case 4 /* Keyword */:
        switch (this.lookahead.value) {
          case "break":
            statement = this.parseBreakStatement();
            break;
          case "continue":
            statement = this.parseContinueStatement();
            break;
          case "debugger":
            statement = this.parseDebuggerStatement();
            break;
          case "do":
            statement = this.parseDoWhileStatement();
            break;
          case "for":
            statement = this.parseForStatement();
            break;
          case "function":
            statement = this.parseFunctionDeclaration();
            break;
          case "if":
            statement = this.parseIfStatement();
            break;
          case "return":
            statement = this.parseReturnStatement();
            break;
          case "switch":
            statement = this.parseSwitchStatement();
            break;
          case "throw":
            statement = this.parseThrowStatement();
            break;
          case "try":
            statement = this.parseTryStatement();
            break;
          case "var":
            statement = this.parseVariableStatement();
            break;
          case "while":
            statement = this.parseWhileStatement();
            break;
          case "with":
            statement = this.parseWithStatement();
            break;
          default:
            statement = this.parseExpressionStatement();
            break;
        }
        break;
      default:
        statement = this.throwUnexpectedToken(this.lookahead);
    }
    return statement;
  }
  // https://tc39.github.io/ecma262/#sec-function-definitions
  parseFunctionSourceElements() {
    const node = this.createNode();
    this.expect("{");
    const body = this.parseDirectivePrologues();
    const previousLabelSet = this.context.labelSet;
    const previousInIteration = this.context.inIteration;
    const previousInSwitch = this.context.inSwitch;
    const previousInFunctionBody = this.context.inFunctionBody;
    this.context.labelSet = {};
    this.context.inIteration = false;
    this.context.inSwitch = false;
    this.context.inFunctionBody = true;
    while (this.lookahead.type !== 2 /* EOF */) {
      if (this.match("}")) {
        break;
      }
      body.push(this.parseStatementListItem());
    }
    this.expect("}");
    this.context.labelSet = previousLabelSet;
    this.context.inIteration = previousInIteration;
    this.context.inSwitch = previousInSwitch;
    this.context.inFunctionBody = previousInFunctionBody;
    return this.finalize(node, new BlockStatement(body));
  }
  validateParam(options, param, name) {
    const key = "$" + name;
    if (this.context.strict) {
      if (this.scanner.isRestrictedWord(name)) {
        options.stricted = param;
        options.message = Messages.StrictParamName;
      }
      if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
        options.stricted = param;
        options.hasDuplicateParameterNames = true;
      }
    } else if (!options.firstRestricted) {
      if (this.scanner.isRestrictedWord(name)) {
        options.firstRestricted = param;
        options.message = Messages.StrictParamName;
      } else if (this.scanner.isStrictModeReservedWord(name)) {
        options.firstRestricted = param;
        options.message = Messages.StrictReservedWord;
      } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
        options.stricted = param;
        options.hasDuplicateParameterNames = true;
      }
    }
    if (typeof Object.defineProperty === "function") {
      Object.defineProperty(options.paramSet, key, { value: true, enumerable: true, writable: true, configurable: true });
    } else {
      options.paramSet[key] = true;
    }
  }
  parseRestElement(params) {
    const node = this.createNode();
    this.expect("...");
    const arg = this.parsePattern(params);
    if (this.match("=")) {
      this.throwError(Messages.DefaultRestParameter);
    }
    if (!this.match(")")) {
      this.throwError(Messages.ParameterAfterRestParameter);
    }
    return this.finalize(node, new RestElement(arg));
  }
  parseFormalParameter(options) {
    const params = [];
    const param = this.match("...") ? this.parseRestElement(params) : this.parsePatternWithDefault(params);
    for (let i = 0; i < params.length; i++) {
      this.validateParam(options, params[i], params[i].value);
    }
    options.simple = options.simple && param instanceof Identifier;
    options.params.push(param);
  }
  parseFormalParameters(firstRestricted) {
    const options = {
      simple: true,
      hasDuplicateParameterNames: false,
      params: [],
      firstRestricted
    };
    this.expect("(");
    if (!this.match(")")) {
      options.paramSet = {};
      while (this.lookahead.type !== 2 /* EOF */) {
        this.parseFormalParameter(options);
        if (this.match(")")) {
          break;
        }
        this.expect(",");
        if (this.match(")")) {
          break;
        }
      }
    }
    this.expect(")");
    if (options.hasDuplicateParameterNames) {
      if (this.context.strict || this.context.isAsync || !options.simple) {
        this.throwError(Messages.DuplicateParameter);
      }
    }
    return {
      simple: options.simple,
      params: options.params,
      stricted: options.stricted,
      firstRestricted: options.firstRestricted,
      message: options.message
    };
  }
  matchAsyncFunction() {
    let match = this.matchContextualKeyword("async");
    if (match) {
      const state = this.scanner.saveState();
      this.scanner.scanComments();
      const next = this.scanner.lex();
      this.scanner.restoreState(state);
      match = state.lineNumber === next.lineNumber && next.type === 4 /* Keyword */ && next.value === "function";
    }
    return match;
  }
  parseFunctionDeclaration(identifierIsOptional) {
    const node = this.createNode();
    const isAsync = this.matchContextualKeyword("async");
    if (isAsync) {
      if (this.context.inIteration) {
        this.tolerateError(Messages.AsyncFunctionInSingleStatementContext);
      }
      this.nextToken();
    }
    this.expectKeyword("function");
    const isGenerator = this.match("*");
    if (isGenerator) {
      this.nextToken();
    }
    let message;
    let id = null;
    let firstRestricted = null;
    if (!identifierIsOptional || !this.match("(")) {
      const token = this.lookahead;
      id = this.parseVariableIdentifier();
      if (this.context.strict) {
        if (this.scanner.isRestrictedWord(token.value)) {
          this.tolerateUnexpectedToken(token, Messages.StrictFunctionName);
        }
      } else {
        if (this.scanner.isRestrictedWord(token.value)) {
          firstRestricted = token;
          message = Messages.StrictFunctionName;
        } else if (this.scanner.isStrictModeReservedWord(token.value)) {
          firstRestricted = token;
          message = Messages.StrictReservedWord;
        }
      }
    }
    const previousIsAsync = this.context.isAsync;
    const previousAllowYield = this.context.allowYield;
    this.context.isAsync = isAsync;
    this.context.allowYield = !isGenerator;
    const formalParameters = this.parseFormalParameters(firstRestricted);
    const params = formalParameters.params;
    const stricted = formalParameters.stricted;
    firstRestricted = formalParameters.firstRestricted;
    if (formalParameters.message) {
      message = formalParameters.message;
    }
    const previousStrict = this.context.strict;
    const previousAllowStrictDirective = this.context.allowStrictDirective;
    this.context.allowStrictDirective = formalParameters.simple;
    const body = this.parseFunctionSourceElements();
    if (this.context.strict && firstRestricted) {
      this.throwUnexpectedToken(firstRestricted, message);
    }
    if (this.context.strict && stricted) {
      this.tolerateUnexpectedToken(stricted, message);
    }
    this.context.strict = previousStrict;
    this.context.allowStrictDirective = previousAllowStrictDirective;
    this.context.isAsync = previousIsAsync;
    this.context.allowYield = previousAllowYield;
    return isAsync ? this.finalize(node, new AsyncFunctionDeclaration(id, params, body, isGenerator)) : this.finalize(node, new FunctionDeclaration(id, params, body, isGenerator));
  }
  parseFunctionExpression() {
    const node = this.createNode();
    const isAsync = this.matchContextualKeyword("async");
    if (isAsync) {
      this.nextToken();
    }
    this.expectKeyword("function");
    const isGenerator = this.match("*");
    if (isGenerator) {
      this.nextToken();
    }
    let message;
    let id = null;
    let firstRestricted;
    const previousIsAsync = this.context.isAsync;
    const previousAllowYield = this.context.allowYield;
    this.context.isAsync = isAsync;
    this.context.allowYield = !isGenerator;
    if (!this.match("(")) {
      const token = this.lookahead;
      id = !this.context.strict && !isGenerator && this.matchKeyword("yield") ? this.parseIdentifierName() : this.parseVariableIdentifier();
      if (this.context.strict) {
        if (this.scanner.isRestrictedWord(token.value)) {
          this.tolerateUnexpectedToken(token, Messages.StrictFunctionName);
        }
      } else {
        if (this.scanner.isRestrictedWord(token.value)) {
          firstRestricted = token;
          message = Messages.StrictFunctionName;
        } else if (this.scanner.isStrictModeReservedWord(token.value)) {
          firstRestricted = token;
          message = Messages.StrictReservedWord;
        }
      }
    }
    const formalParameters = this.parseFormalParameters(firstRestricted);
    const params = formalParameters.params;
    const stricted = formalParameters.stricted;
    firstRestricted = formalParameters.firstRestricted;
    if (formalParameters.message) {
      message = formalParameters.message;
    }
    const previousStrict = this.context.strict;
    const previousAllowStrictDirective = this.context.allowStrictDirective;
    this.context.allowStrictDirective = formalParameters.simple;
    const body = this.parseFunctionSourceElements();
    if (this.context.strict && firstRestricted) {
      this.throwUnexpectedToken(firstRestricted, message);
    }
    if (this.context.strict && stricted) {
      this.tolerateUnexpectedToken(stricted, message);
    }
    this.context.strict = previousStrict;
    this.context.allowStrictDirective = previousAllowStrictDirective;
    this.context.isAsync = previousIsAsync;
    this.context.allowYield = previousAllowYield;
    return this.finalize(node, new FunctionExpression(id, params, body, isGenerator, isAsync));
  }
  // https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive
  parseDirective() {
    const token = this.lookahead;
    const node = this.createNode();
    const expr = this.parseExpression();
    const directive = expr.type === "Literal" /* Literal */ ? this.getTokenRaw(token).slice(1, -1) : null;
    this.consumeSemicolon();
    return this.finalize(node, directive ? new Directive(expr, directive) : new ExpressionStatement(expr));
  }
  parseDirectivePrologues() {
    let firstRestricted = null;
    const body = [];
    while (true) {
      const token = this.lookahead;
      if (token.type !== 8 /* StringLiteral */) {
        break;
      }
      const statement = this.parseDirective();
      body.push(statement);
      const directive = statement.directive;
      if (typeof directive !== "string") {
        break;
      }
      if (directive === "use strict") {
        this.context.strict = true;
        if (firstRestricted) {
          this.tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
        }
        if (!this.context.allowStrictDirective) {
          this.tolerateUnexpectedToken(token, Messages.IllegalLanguageModeDirective);
        }
      } else {
        if (!firstRestricted && token.octal) {
          firstRestricted = token;
        }
      }
    }
    return body;
  }
  // https://tc39.github.io/ecma262/#sec-method-definitions
  qualifiedPropertyName(token) {
    switch (token.type) {
      case 3 /* Identifier */:
      case 8 /* StringLiteral */:
      case 1 /* BooleanLiteral */:
      case 5 /* NullLiteral */:
      case 6 /* NumericLiteral */:
      case 4 /* Keyword */:
        return true;
      case 7 /* Punctuator */:
        return token.value === "[" || token.value === "#";
      default:
        break;
    }
    return false;
  }
  parseGetterMethod() {
    const node = this.createNode();
    const isGenerator = false;
    const previousAllowYield = this.context.allowYield;
    this.context.allowYield = !isGenerator;
    const formalParameters = this.parseFormalParameters();
    if (formalParameters.params.length > 0) {
      this.tolerateError(Messages.BadGetterArity);
    }
    const method = this.parsePropertyMethod(formalParameters);
    this.context.allowYield = previousAllowYield;
    return this.finalize(node, new FunctionExpression(null, formalParameters.params, method, isGenerator, false));
  }
  parseSetterMethod() {
    const node = this.createNode();
    const isGenerator = false;
    const previousAllowYield = this.context.allowYield;
    this.context.allowYield = !isGenerator;
    const formalParameters = this.parseFormalParameters();
    if (formalParameters.params.length !== 1) {
      this.tolerateError(Messages.BadSetterArity);
    } else if (formalParameters.params[0] instanceof RestElement) {
      this.tolerateError(Messages.BadSetterRestParameter);
    }
    const method = this.parsePropertyMethod(formalParameters);
    this.context.allowYield = previousAllowYield;
    return this.finalize(node, new FunctionExpression(null, formalParameters.params, method, isGenerator, false));
  }
  parseGeneratorMethod(isAsync) {
    const node = this.createNode();
    const isGenerator = true;
    const previousAllowYield = this.context.allowYield;
    this.context.allowYield = true;
    const params = this.parseFormalParameters();
    this.context.allowYield = false;
    const method = this.parsePropertyMethod(params);
    this.context.allowYield = previousAllowYield;
    return this.finalize(node, new FunctionExpression(null, params.params, method, isGenerator, isAsync));
  }
  // https://tc39.github.io/ecma262/#sec-generator-function-definitions
  isStartOfExpression() {
    let start = true;
    const value = this.lookahead.value;
    switch (this.lookahead.type) {
      case 7 /* Punctuator */:
        start = value === "[" || value === "(" || value === "{" || value === "+" || value === "-" || value === "!" || value === "~" || value === "++" || value === "--" || value === "/" || value === "/=";
        break;
      case 4 /* Keyword */:
        start = value === "class" || value === "delete" || value === "function" || value === "let" || value === "new" || value === "super" || value === "this" || value === "typeof" || value === "void" || value === "yield";
        break;
      default:
        break;
    }
    return start;
  }
  parseYieldExpression() {
    const node = this.createNode();
    this.expectKeyword("yield");
    let argument = null;
    let delegate = false;
    if (!this.hasLineTerminator) {
      const previousAllowYield = this.context.allowYield;
      this.context.allowYield = false;
      delegate = this.match("*");
      if (delegate) {
        this.nextToken();
        argument = this.parseAssignmentExpression();
      } else if (this.isStartOfExpression()) {
        argument = this.parseAssignmentExpression();
      }
      this.context.allowYield = previousAllowYield;
    }
    return this.finalize(node, new YieldExpression(argument, delegate));
  }
  // https://tc39.github.io/ecma262/#sec-class-definitions
  parseStaticBlock() {
    const node = this.createNode();
    this.expect("{");
    const block = [];
    while (true) {
      if (this.match("}")) {
        break;
      }
      block.push(this.parseStatementListItem());
    }
    this.expect("}");
    return this.finalize(node, new StaticBlock(block));
  }
  parseDecorator() {
    const node = this.createNode();
    this.expect("@");
    const previousStrict = this.context.strict;
    const previousAllowYield = this.context.allowYield;
    const previousIsAsync = this.context.isAsync;
    this.context.strict = false;
    this.context.allowYield = true;
    this.context.isAsync = false;
    const expression = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall);
    this.context.strict = previousStrict;
    this.context.allowYield = previousAllowYield;
    this.context.isAsync = previousIsAsync;
    if (this.match(";")) {
      this.throwError(Messages.NoSemicolonAfterDecorator);
    }
    return this.finalize(node, new Decorator(expression));
  }
  parseDecorators() {
    let decorators = null;
    while (this.match("@")) {
      if (decorators == null)
        decorators = [];
      decorators.push(this.parseDecorator());
    }
    return decorators;
  }
  parseClassElement(hasConstructor) {
    let token = this.lookahead;
    const node = this.createNode();
    const previousInConstructor = this.context.inConstructor;
    let kind = "";
    let key = null;
    let value = null;
    let computed = false;
    let method = false;
    let isStatic = false;
    let isAsync = false;
    let isGenerator = false;
    let isPrivate = false;
    const decorators = this.parseDecorators();
    if (decorators) {
      token = this.lookahead;
    }
    if (this.match("*")) {
      this.nextToken();
    } else {
      computed = this.match("[");
      if (this.match("#")) {
        isPrivate = true;
        this.nextToken();
        token = this.lookahead;
      }
      key = this.parseObjectPropertyKey(isPrivate);
      const id = key;
      this.context.inConstructor = token.type === 3 /* Identifier */ && token.value === "constructor";
      if (id.name === "static" && (this.qualifiedPropertyName(this.lookahead) || this.match("*"))) {
        token = this.lookahead;
        isStatic = true;
        computed = this.match("[");
        if (this.match("*")) {
          this.nextToken();
          if (this.match("#")) {
            isPrivate = true;
            this.nextToken();
            token = this.lookahead;
          }
        } else {
          if (this.match("#")) {
            isPrivate = true;
            this.nextToken();
            token = this.lookahead;
          }
          key = this.parseObjectPropertyKey(isPrivate);
        }
      }
      if (id.name === "static" && this.match("{")) {
        return this.parseStaticBlock();
      }
      if (token.type === 3 /* Identifier */ && !this.hasLineTerminator && token.value === "async") {
        const punctuator = this.lookahead.value;
        if (punctuator !== ":" && punctuator !== "(") {
          isAsync = true;
          isGenerator = this.match("*");
          if (isGenerator) {
            this.nextToken();
          }
          token = this.lookahead;
          computed = this.match("[");
          if (this.match("*")) {
            this.nextToken();
            if (this.match("#")) {
              isPrivate = true;
              this.nextToken();
            }
          } else {
            if (this.match("#")) {
              isPrivate = true;
              this.nextToken();
              token = this.lookahead;
            }
            key = this.parseObjectPropertyKey(isPrivate);
          }
          if (token.type === 3 /* Identifier */ && token.value === "constructor" && !isStatic) {
            this.tolerateUnexpectedToken(token, Messages.ConstructorIsAsync);
          }
        }
      }
    }
    if (token.type === 3 /* Identifier */ && token.value === "constructor" && isPrivate) {
      this.tolerateUnexpectedToken(token, Messages.ConstructorIsPrivate);
    }
    const lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead);
    if (token.type === 3 /* Identifier */ || token.type === 8 /* StringLiteral */) {
      if (token.value === "get" && lookaheadPropertyKey) {
        kind = "get";
        if (this.match("#")) {
          isPrivate = true;
          this.nextToken();
          token = this.lookahead;
        }
        computed = this.match("[");
        key = this.parseObjectPropertyKey(isPrivate);
        this.context.allowYield = false;
        value = this.parseGetterMethod();
      } else if (token.value === "set" && lookaheadPropertyKey) {
        kind = "set";
        if (this.match("#")) {
          isPrivate = true;
          this.nextToken();
          token = this.lookahead;
        }
        computed = this.match("[");
        key = this.parseObjectPropertyKey(isPrivate);
        value = this.parseSetterMethod();
      } else if (!this.match("(")) {
        kind = "property";
        computed = false;
        if (this.match("=")) {
          this.nextToken();
          value = this.isolateCoverGrammar(this.parseAssignmentExpression);
        }
      }
    } else if (token.type === 7 /* Punctuator */ && token.value === "*" && lookaheadPropertyKey) {
      kind = "init";
      computed = this.match("[");
      key = this.parseObjectPropertyKey(isPrivate);
      value = this.parseGeneratorMethod(isAsync);
      method = true;
    } else if (token.type === 7 /* Punctuator */ && token.value === "[" && !this.match("(")) {
      kind = "property";
      computed = true;
      if (this.match("=")) {
        this.nextToken();
        value = this.isolateCoverGrammar(this.parseAssignmentExpression);
      }
    }
    if (!kind && key && this.match("(")) {
      const previousInClassConstructor = this.context.inClassConstructor;
      this.context.inClassConstructor = token.value === "constructor";
      kind = "init";
      value = isAsync ? this.parsePropertyMethodAsyncFunction(isGenerator) : this.parsePropertyMethodFunction(isGenerator);
      this.context.inClassConstructor = previousInClassConstructor;
      method = true;
    }
    if (!kind) {
      this.throwUnexpectedToken(this.lookahead);
    }
    if (kind === "init") {
      kind = "method";
    }
    if (!computed) {
      if (isStatic && this.isPropertyKey(key, "prototype")) {
        this.throwUnexpectedToken(token, Messages.StaticPrototype);
      }
      if (!isStatic && this.isPropertyKey(key, "constructor")) {
        if (kind !== "method" || !method || value && value.generator) {
          this.throwUnexpectedToken(token, Messages.ConstructorSpecialMethod);
        }
        if (hasConstructor.value) {
          this.throwUnexpectedToken(token, Messages.DuplicateConstructor);
        } else {
          hasConstructor.value = true;
        }
        kind = "constructor";
      }
    }
    this.context.inConstructor = previousInConstructor;
    if (kind === "property") {
      this.consumeSemicolon();
      return this.finalize(node, new PropertyDefinition(key, computed, value, isStatic, decorators));
    } else
      return this.finalize(node, new MethodDefinition(key, computed, value, kind, isStatic, decorators));
  }
  parseClassElementList() {
    const body = [];
    const hasConstructor = { value: false };
    this.expect("{");
    while (!this.match("}")) {
      if (this.match(";")) {
        this.nextToken();
      } else {
        body.push(this.parseClassElement(hasConstructor));
      }
    }
    this.expect("}");
    return body;
  }
  parseClassBody() {
    const node = this.createNode();
    const elementList = this.parseClassElementList();
    return this.finalize(node, new ClassBody(elementList));
  }
  parseClassDeclaration(identifierIsOptional) {
    const node = this.createNode();
    const previousStrict = this.context.strict;
    const previousAllowSuper = this.context.allowSuper;
    this.context.strict = true;
    this.expectKeyword("class");
    const id = identifierIsOptional && this.lookahead.type !== 3 /* Identifier */ ? null : this.parseVariableIdentifier();
    let superClass = null;
    if (this.matchKeyword("extends")) {
      this.nextToken();
      superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall);
      this.context.allowSuper = true;
    }
    const classBody = this.parseClassBody();
    this.context.allowSuper = previousAllowSuper;
    this.context.strict = previousStrict;
    return this.finalize(node, new ClassDeclaration(id, superClass, classBody, this.context.decorators));
  }
  parseClassExpression() {
    const node = this.createNode();
    const previousStrict = this.context.strict;
    this.context.strict = true;
    this.expectKeyword("class");
    const id = this.lookahead.type === 3 /* Identifier */ ? this.parseVariableIdentifier() : null;
    let superClass = null;
    if (this.matchKeyword("extends")) {
      this.nextToken();
      superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall);
      this.context.allowSuper = true;
    }
    const classBody = this.parseClassBody();
    this.context.strict = previousStrict;
    return this.finalize(node, new ClassExpression(id, superClass, classBody, this.context.decorators));
  }
  // https://tc39.github.io/ecma262/#sec-scripts
  // https://tc39.github.io/ecma262/#sec-modules
  parseModule() {
    this.context.strict = true;
    this.context.isModule = true;
    this.scanner.isModule = true;
    const node = this.createNode();
    const body = this.parseDirectivePrologues();
    while (this.lookahead.type !== 2 /* EOF */) {
      body.push(this.parseStatementListItem());
    }
    return this.finalize(node, new Module(body));
  }
  parseScript() {
    const node = this.createNode();
    const body = this.parseDirectivePrologues();
    while (this.lookahead.type !== 2 /* EOF */) {
      body.push(this.parseStatementListItem());
    }
    return this.finalize(node, new Script(body));
  }
  // https://tc39.github.io/ecma262/#sec-imports
  parseImportAttributes() {
    if (this.lookahead.value === "assert") {
      this.nextToken();
      this.expect("{");
      const attributes = [];
      while (!this.match("}")) {
        attributes.push(this.parseImportAttribute());
        if (!this.match("}")) {
          this.expectCommaSeparator();
        }
      }
      this.expect("}");
      return attributes;
    }
    return null;
  }
  parseImportAttribute() {
    const node = this.createNode();
    if (this.lookahead.type !== 3 /* Identifier */) {
      this.throwUnexpectedToken(this.nextToken());
    }
    const key = this.parseIdentifierName();
    if (!this.match(":")) {
      this.throwUnexpectedToken(this.nextToken());
    }
    this.nextToken();
    const literalToken = this.nextToken();
    const raw = this.getTokenRaw(literalToken);
    const value = this.finalize(node, new Literal(literalToken.value, raw));
    return this.finalize(node, new ImportAttribute(key, value));
  }
  parseModuleSpecifier() {
    const node = this.createNode();
    if (this.lookahead.type !== 8 /* StringLiteral */) {
      this.throwError(Messages.InvalidModuleSpecifier);
    }
    const token = this.nextToken();
    const raw = this.getTokenRaw(token);
    if (!Character.isStringWellFormedUnicode(token.value)) {
      this.throwError(Messages.InvalidModuleSpecifier);
    }
    return this.finalize(node, new Literal(token.value, raw));
  }
  // import {<foo as bar>} ...;
  parseImportSpecifier() {
    const node = this.createNode();
    let imported;
    let local;
    if (this.lookahead.type === 3 /* Identifier */) {
      imported = this.parseVariableIdentifier();
      local = imported;
      if (this.matchContextualKeyword("as")) {
        this.nextToken();
        local = this.parseVariableIdentifier();
      }
    } else {
      imported = this.lookahead.type == 8 /* StringLiteral */ ? this.parseModuleSpecifier() : this.parseIdentifierName();
      local = imported;
      if (this.matchContextualKeyword("as")) {
        this.nextToken();
        local = this.parseVariableIdentifier();
      } else {
        this.throwUnexpectedToken(this.nextToken());
      }
    }
    return this.finalize(node, new ImportSpecifier(local, imported));
  }
  // {foo, bar as bas}
  parseNamedImports() {
    this.expect("{");
    const specifiers = [];
    while (!this.match("}")) {
      specifiers.push(this.parseImportSpecifier());
      if (!this.match("}")) {
        this.expect(",");
      }
    }
    this.expect("}");
    return specifiers;
  }
  // import <foo> ...;
  parseImportDefaultSpecifier() {
    const node = this.createNode();
    const local = this.parseIdentifierName();
    return this.finalize(node, new ImportDefaultSpecifier(local));
  }
  // import <* as foo> ...;
  parseImportNamespaceSpecifier() {
    const node = this.createNode();
    this.expect("*");
    if (!this.matchContextualKeyword("as")) {
      this.throwError(Messages.NoAsAfterImportNamespace);
    }
    if (this.lookahead.escaped) {
      this.throwError(Messages.NoAsAndFromEscapeSequences);
    }
    this.nextToken();
    const local = this.parseIdentifierName();
    return this.finalize(node, new ImportNamespaceSpecifier(local));
  }
  parseImportDeclaration() {
    if (this.context.inFunctionBody) {
      this.throwError(Messages.IllegalImportDeclaration);
    }
    const node = this.createNode();
    this.expectKeyword("import");
    let src;
    let specifiers = [];
    if (this.lookahead.type === 8 /* StringLiteral */) {
      src = this.parseModuleSpecifier();
    } else {
      if (this.match("{")) {
        specifiers = specifiers.concat(this.parseNamedImports());
      } else if (this.match("*")) {
        specifiers.push(this.parseImportNamespaceSpecifier());
      } else if (this.isIdentifierName(this.lookahead) && !this.matchKeyword("default")) {
        specifiers.push(this.parseImportDefaultSpecifier());
        if (this.match(",")) {
          this.nextToken();
          if (this.match("*")) {
            specifiers.push(this.parseImportNamespaceSpecifier());
          } else if (this.match("{")) {
            specifiers = specifiers.concat(this.parseNamedImports());
          } else {
            this.throwUnexpectedToken(this.lookahead);
          }
        }
      } else {
        this.throwUnexpectedToken(this.nextToken());
      }
      if (!this.matchContextualKeyword("from")) {
        const message = this.lookahead.value ? Messages.UnexpectedToken : Messages.MissingFromClause;
        this.throwError(message, this.lookahead.value);
      }
      this.nextToken();
      src = this.parseModuleSpecifier();
    }
    const attributes = this.parseImportAttributes();
    this.consumeSemicolon();
    return this.finalize(node, new ImportDeclaration(specifiers, src, attributes));
  }
  // https://tc39.github.io/ecma262/#sec-exports
  parseExportSpecifier() {
    const node = this.createNode();
    const local = this.lookahead.type == 8 /* StringLiteral */ ? this.parseModuleSpecifier() : this.parseIdentifierName();
    let exported = local;
    if (this.matchContextualKeyword("as")) {
      if (this.lookahead.escaped) {
        this.throwError(Messages.NoAsAndFromEscapeSequences);
      }
      this.nextToken();
      exported = this.lookahead.type == 8 /* StringLiteral */ ? this.parseModuleSpecifier() : this.parseIdentifierName();
    }
    return this.finalize(node, new ExportSpecifier(local, exported));
  }
  parseExportDeclaration() {
    if (this.context.inFunctionBody) {
      this.throwError(Messages.IllegalExportDeclaration);
    }
    const node = this.createNode();
    this.expectKeyword("export");
    let exportDeclaration;
    if (this.matchKeyword("default")) {
      this.nextToken();
      if (this.matchKeyword("function")) {
        const declaration = this.parseFunctionDeclaration(true);
        exportDeclaration = this.finalize(node, new ExportDefaultDeclaration(declaration));
      } else if (this.matchKeyword("class")) {
        const declaration = this.parseClassDeclaration(true);
        exportDeclaration = this.finalize(node, new ExportDefaultDeclaration(declaration));
      } else if (this.matchContextualKeyword("async")) {
        const declaration = this.matchAsyncFunction() ? this.parseFunctionDeclaration(true) : this.parseAssignmentExpression();
        exportDeclaration = this.finalize(node, new ExportDefaultDeclaration(declaration));
      } else {
        if (this.matchContextualKeyword("from")) {
          this.throwError(Messages.UnexpectedToken, this.lookahead.value);
        }
        const declaration = this.match("{") ? this.parseObjectInitializer() : this.match("[") ? this.parseArrayInitializer() : this.parseAssignmentExpression();
        this.consumeSemicolon();
        exportDeclaration = this.finalize(node, new ExportDefaultDeclaration(declaration));
      }
    } else if (this.match("*")) {
      this.nextToken();
      let exported = null;
      if (this.matchContextualKeyword("as")) {
        if (this.lookahead.escaped) {
          this.throwError(Messages.NoAsAndFromEscapeSequences);
        }
        this.nextToken();
        exported = this.lookahead.type == 8 /* StringLiteral */ ? this.parseModuleSpecifier() : this.parseIdentifierName();
      }
      if (!this.matchContextualKeyword("from")) {
        const message = this.lookahead.value ? Messages.UnexpectedToken : Messages.MissingFromClause;
        this.throwError(message, this.lookahead.value);
      }
      if (this.lookahead.escaped) {
        this.throwError(Messages.NoAsAndFromEscapeSequences);
      }
      this.nextToken();
      const src = this.parseModuleSpecifier();
      const attributes = this.parseImportAttributes();
      this.consumeSemicolon();
      exportDeclaration = this.finalize(node, new ExportAllDeclaration(src, exported, attributes));
    } else if (this.lookahead.type === 4 /* Keyword */) {
      let declaration;
      switch (this.lookahead.value) {
        case "let":
        case "const":
          declaration = this.parseLexicalDeclaration({ inFor: false });
          break;
        case "var":
        case "class":
        case "function":
          declaration = this.parseStatementListItem();
          break;
        default:
          this.throwUnexpectedToken(this.lookahead);
      }
      exportDeclaration = this.finalize(node, new ExportNamedDeclaration(declaration, [], null, null));
    } else if (this.matchAsyncFunction()) {
      const declaration = this.parseFunctionDeclaration();
      exportDeclaration = this.finalize(node, new ExportNamedDeclaration(declaration, [], null, null));
    } else {
      const specifiers = [];
      let source = null;
      let isExportFromIdentifier = false;
      let attributes = null;
      this.expect("{");
      while (!this.match("}")) {
        isExportFromIdentifier = isExportFromIdentifier || this.matchKeyword("default");
        specifiers.push(this.parseExportSpecifier());
        if (!this.match("}")) {
          this.expect(",");
        }
      }
      this.expect("}");
      if (this.matchContextualKeyword("from")) {
        if (this.lookahead.escaped) {
          this.throwError(Messages.NoAsAndFromEscapeSequences);
        }
        this.nextToken();
        source = this.parseModuleSpecifier();
        attributes = this.parseImportAttributes();
        this.consumeSemicolon();
      } else if (isExportFromIdentifier) {
        const message = this.lookahead.value ? Messages.UnexpectedToken : Messages.MissingFromClause;
        this.throwError(message, this.lookahead.value);
      } else {
        attributes = this.parseImportAttributes();
        this.consumeSemicolon();
      }
      exportDeclaration = this.finalize(node, new ExportNamedDeclaration(null, specifiers, source, attributes));
    }
    return exportDeclaration;
  }
};

// src/xhtml-entities.ts
var XHTMLEntities = {
  quot: '"',
  amp: "&",
  apos: "'",
  gt: ">",
  nbsp: "\xA0",
  iexcl: "\xA1",
  cent: "\xA2",
  pound: "\xA3",
  curren: "\xA4",
  yen: "\xA5",
  brvbar: "\xA6",
  sect: "\xA7",
  uml: "\xA8",
  copy: "\xA9",
  ordf: "\xAA",
  laquo: "\xAB",
  not: "\xAC",
  shy: "\xAD",
  reg: "\xAE",
  macr: "\xAF",
  deg: "\xB0",
  plusmn: "\xB1",
  sup2: "\xB2",
  sup3: "\xB3",
  acute: "\xB4",
  micro: "\xB5",
  para: "\xB6",
  middot: "\xB7",
  cedil: "\xB8",
  sup1: "\xB9",
  ordm: "\xBA",
  raquo: "\xBB",
  frac14: "\xBC",
  frac12: "\xBD",
  frac34: "\xBE",
  iquest: "\xBF",
  Agrave: "\xC0",
  Aacute: "\xC1",
  Acirc: "\xC2",
  Atilde: "\xC3",
  Auml: "\xC4",
  Aring: "\xC5",
  AElig: "\xC6",
  Ccedil: "\xC7",
  Egrave: "\xC8",
  Eacute: "\xC9",
  Ecirc: "\xCA",
  Euml: "\xCB",
  Igrave: "\xCC",
  Iacute: "\xCD",
  Icirc: "\xCE",
  Iuml: "\xCF",
  ETH: "\xD0",
  Ntilde: "\xD1",
  Ograve: "\xD2",
  Oacute: "\xD3",
  Ocirc: "\xD4",
  Otilde: "\xD5",
  Ouml: "\xD6",
  times: "\xD7",
  Oslash: "\xD8",
  Ugrave: "\xD9",
  Uacute: "\xDA",
  Ucirc: "\xDB",
  Uuml: "\xDC",
  Yacute: "\xDD",
  THORN: "\xDE",
  szlig: "\xDF",
  agrave: "\xE0",
  aacute: "\xE1",
  acirc: "\xE2",
  atilde: "\xE3",
  auml: "\xE4",
  aring: "\xE5",
  aelig: "\xE6",
  ccedil: "\xE7",
  egrave: "\xE8",
  eacute: "\xE9",
  ecirc: "\xEA",
  euml: "\xEB",
  igrave: "\xEC",
  iacute: "\xED",
  icirc: "\xEE",
  iuml: "\xEF",
  eth: "\xF0",
  ntilde: "\xF1",
  ograve: "\xF2",
  oacute: "\xF3",
  ocirc: "\xF4",
  otilde: "\xF5",
  ouml: "\xF6",
  divide: "\xF7",
  oslash: "\xF8",
  ugrave: "\xF9",
  uacute: "\xFA",
  ucirc: "\xFB",
  uuml: "\xFC",
  yacute: "\xFD",
  thorn: "\xFE",
  yuml: "\xFF",
  OElig: "\u0152",
  oelig: "\u0153",
  Scaron: "\u0160",
  scaron: "\u0161",
  Yuml: "\u0178",
  fnof: "\u0192",
  circ: "\u02C6",
  tilde: "\u02DC",
  Alpha: "\u0391",
  Beta: "\u0392",
  Gamma: "\u0393",
  Delta: "\u0394",
  Epsilon: "\u0395",
  Zeta: "\u0396",
  Eta: "\u0397",
  Theta: "\u0398",
  Iota: "\u0399",
  Kappa: "\u039A",
  Lambda: "\u039B",
  Mu: "\u039C",
  Nu: "\u039D",
  Xi: "\u039E",
  Omicron: "\u039F",
  Pi: "\u03A0",
  Rho: "\u03A1",
  Sigma: "\u03A3",
  Tau: "\u03A4",
  Upsilon: "\u03A5",
  Phi: "\u03A6",
  Chi: "\u03A7",
  Psi: "\u03A8",
  Omega: "\u03A9",
  alpha: "\u03B1",
  beta: "\u03B2",
  gamma: "\u03B3",
  delta: "\u03B4",
  epsilon: "\u03B5",
  zeta: "\u03B6",
  eta: "\u03B7",
  theta: "\u03B8",
  iota: "\u03B9",
  kappa: "\u03BA",
  lambda: "\u03BB",
  mu: "\u03BC",
  nu: "\u03BD",
  xi: "\u03BE",
  omicron: "\u03BF",
  pi: "\u03C0",
  rho: "\u03C1",
  sigmaf: "\u03C2",
  sigma: "\u03C3",
  tau: "\u03C4",
  upsilon: "\u03C5",
  phi: "\u03C6",
  chi: "\u03C7",
  psi: "\u03C8",
  omega: "\u03C9",
  thetasym: "\u03D1",
  upsih: "\u03D2",
  piv: "\u03D6",
  ensp: "\u2002",
  emsp: "\u2003",
  thinsp: "\u2009",
  zwnj: "\u200C",
  zwj: "\u200D",
  lrm: "\u200E",
  rlm: "\u200F",
  ndash: "\u2013",
  mdash: "\u2014",
  lsquo: "\u2018",
  rsquo: "\u2019",
  sbquo: "\u201A",
  ldquo: "\u201C",
  rdquo: "\u201D",
  bdquo: "\u201E",
  dagger: "\u2020",
  Dagger: "\u2021",
  bull: "\u2022",
  hellip: "\u2026",
  permil: "\u2030",
  prime: "\u2032",
  Prime: "\u2033",
  lsaquo: "\u2039",
  rsaquo: "\u203A",
  oline: "\u203E",
  frasl: "\u2044",
  euro: "\u20AC",
  image: "\u2111",
  weierp: "\u2118",
  real: "\u211C",
  trade: "\u2122",
  alefsym: "\u2135",
  larr: "\u2190",
  uarr: "\u2191",
  rarr: "\u2192",
  darr: "\u2193",
  harr: "\u2194",
  crarr: "\u21B5",
  lArr: "\u21D0",
  uArr: "\u21D1",
  rArr: "\u21D2",
  dArr: "\u21D3",
  hArr: "\u21D4",
  forall: "\u2200",
  part: "\u2202",
  exist: "\u2203",
  empty: "\u2205",
  nabla: "\u2207",
  isin: "\u2208",
  notin: "\u2209",
  ni: "\u220B",
  prod: "\u220F",
  sum: "\u2211",
  minus: "\u2212",
  lowast: "\u2217",
  radic: "\u221A",
  prop: "\u221D",
  infin: "\u221E",
  ang: "\u2220",
  and: "\u2227",
  or: "\u2228",
  cap: "\u2229",
  cup: "\u222A",
  int: "\u222B",
  there4: "\u2234",
  sim: "\u223C",
  cong: "\u2245",
  asymp: "\u2248",
  ne: "\u2260",
  equiv: "\u2261",
  le: "\u2264",
  ge: "\u2265",
  sub: "\u2282",
  sup: "\u2283",
  nsub: "\u2284",
  sube: "\u2286",
  supe: "\u2287",
  oplus: "\u2295",
  otimes: "\u2297",
  perp: "\u22A5",
  sdot: "\u22C5",
  lceil: "\u2308",
  rceil: "\u2309",
  lfloor: "\u230A",
  rfloor: "\u230B",
  loz: "\u25CA",
  spades: "\u2660",
  clubs: "\u2663",
  hearts: "\u2665",
  diams: "\u2666",
  lang: "\u27E8",
  rang: "\u27E9"
};

// src/jsx-parser.ts
TokenName[100 /* Identifier */] = "JSXIdentifier";
TokenName[101 /* Text */] = "JSXText";
function getQualifiedElementName(elementName) {
  let qualifiedName;
  switch (elementName.type) {
    case "JSXIdentifier" /* JSXIdentifier */:
      const id = elementName;
      qualifiedName = id.name;
      break;
    case "JSXNamespacedName" /* JSXNamespacedName */:
      const ns = elementName;
      qualifiedName = getQualifiedElementName(ns.namespace) + ":" + getQualifiedElementName(ns.name);
      break;
    case "JSXMemberExpression" /* JSXMemberExpression */:
      const expr = elementName;
      qualifiedName = getQualifiedElementName(expr.object) + "." + getQualifiedElementName(expr.property);
      break;
    default:
      break;
  }
  return qualifiedName;
}
var JSXParser = class extends Parser {
  constructor(code, options, delegate) {
    super(code, options, delegate);
  }
  //@ts-ignore
  parsePrimaryExpression() {
    return this.match("<") ? this.parseJSXRoot() : super.parsePrimaryExpression();
  }
  startJSX() {
    this.scanner.index = this.startMarker.index;
    this.scanner.lineNumber = this.startMarker.line;
    this.scanner.lineStart = this.startMarker.index - this.startMarker.column;
  }
  finishJSX() {
    this.nextToken();
  }
  reenterJSX() {
    this.startJSX();
    this.expectJSX("}");
    if (this.config.tokens) {
      this.tokens.pop();
    }
  }
  createJSXNode() {
    this.collectComments();
    return {
      index: this.scanner.index,
      line: this.scanner.lineNumber,
      column: this.scanner.index - this.scanner.lineStart
    };
  }
  createJSXChildNode() {
    return {
      index: this.scanner.index,
      line: this.scanner.lineNumber,
      column: this.scanner.index - this.scanner.lineStart
    };
  }
  scanXHTMLEntity(quote) {
    let result = "&";
    let valid = true;
    let terminated = false;
    let numeric = false;
    let hex = false;
    while (!this.scanner.eof() && valid && !terminated) {
      const ch = this.scanner.source[this.scanner.index];
      if (ch === quote) {
        break;
      }
      terminated = ch === ";";
      result += ch;
      ++this.scanner.index;
      if (!terminated) {
        switch (result.length) {
          case 2:
            numeric = ch === "#";
            break;
          case 3:
            if (numeric) {
              hex = ch === "x";
              valid = hex || Character.isDecimalDigit(ch.charCodeAt(0));
              numeric = numeric && !hex;
            }
            break;
          default:
            valid = valid && !(numeric && !Character.isDecimalDigit(ch.charCodeAt(0)));
            valid = valid && !(hex && !Character.isHexDigit(ch.charCodeAt(0)));
            break;
        }
      }
    }
    if (valid && terminated && result.length > 2) {
      const str = result.substr(1, result.length - 2);
      if (numeric && str.length > 1) {
        result = String.fromCharCode(parseInt(str.substr(1), 10));
      } else if (hex && str.length > 2) {
        result = String.fromCharCode(parseInt("0" + str.substr(1), 16));
      } else if (!numeric && !hex && XHTMLEntities[str]) {
        result = XHTMLEntities[str];
      }
    }
    return result;
  }
  // Scan the next JSX token. This replaces Scanner#lex when in JSX mode.
  lexJSX() {
    const cp = this.scanner.source.charCodeAt(this.scanner.index);
    if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) {
      const value = this.scanner.source[this.scanner.index++];
      return {
        type: 7 /* Punctuator */,
        value,
        lineNumber: this.scanner.lineNumber,
        lineStart: this.scanner.lineStart,
        start: this.scanner.index - 1,
        end: this.scanner.index
      };
    }
    if (cp === 34 || cp === 39) {
      const start = this.scanner.index;
      const quote = this.scanner.source[this.scanner.index++];
      let str = "";
      while (!this.scanner.eof()) {
        const ch = this.scanner.source[this.scanner.index++];
        if (ch === quote) {
          break;
        } else if (ch === "&") {
          str += this.scanXHTMLEntity(quote);
        } else {
          str += ch;
        }
      }
      return {
        type: 8 /* StringLiteral */,
        value: str,
        lineNumber: this.scanner.lineNumber,
        lineStart: this.scanner.lineStart,
        start,
        end: this.scanner.index
      };
    }
    if (cp === 46) {
      const n1 = this.scanner.source.charCodeAt(this.scanner.index + 1);
      const n2 = this.scanner.source.charCodeAt(this.scanner.index + 2);
      const value = n1 === 46 && n2 === 46 ? "..." : ".";
      const start = this.scanner.index;
      this.scanner.index += value.length;
      return {
        type: 7 /* Punctuator */,
        value,
        lineNumber: this.scanner.lineNumber,
        lineStart: this.scanner.lineStart,
        start,
        end: this.scanner.index
      };
    }
    if (cp === 96) {
      return {
        type: 10 /* Template */,
        value: "",
        lineNumber: this.scanner.lineNumber,
        lineStart: this.scanner.lineStart,
        start: this.scanner.index,
        end: this.scanner.index
      };
    }
    if (Character.isIdentifierStart(cp) && cp !== 92) {
      const start = this.scanner.index;
      ++this.scanner.index;
      while (!this.scanner.eof()) {
        const ch = this.scanner.source.charCodeAt(this.scanner.index);
        if (Character.isIdentifierPart(ch) && ch !== 92) {
          ++this.scanner.index;
        } else if (ch === 45) {
          ++this.scanner.index;
        } else {
          break;
        }
      }
      const id = this.scanner.source.slice(start, this.scanner.index);
      return {
        type: 100 /* Identifier */,
        value: id,
        lineNumber: this.scanner.lineNumber,
        lineStart: this.scanner.lineStart,
        start,
        end: this.scanner.index
      };
    }
    return this.scanner.lex();
  }
  nextJSXToken() {
    this.collectComments();
    this.startMarker.index = this.scanner.index;
    this.startMarker.line = this.scanner.lineNumber;
    this.startMarker.column = this.scanner.index - this.scanner.lineStart;
    const token = this.lexJSX();
    this.lastMarker.index = this.scanner.index;
    this.lastMarker.line = this.scanner.lineNumber;
    this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
    if (this.config.tokens) {
      this.tokens.push(this.convertToken(token));
    }
    return token;
  }
  nextJSXText() {
    this.startMarker.index = this.scanner.index;
    this.startMarker.line = this.scanner.lineNumber;
    this.startMarker.column = this.scanner.index - this.scanner.lineStart;
    const start = this.scanner.index;
    let text = "";
    while (!this.scanner.eof()) {
      const ch = this.scanner.source[this.scanner.index];
      if (ch === "{" || ch === "<") {
        break;
      }
      ++this.scanner.index;
      text += ch;
      if (Character.isLineTerminator(ch.charCodeAt(0))) {
        ++this.scanner.lineNumber;
        if (ch === "\r" && this.scanner.source[this.scanner.index] === "\n") {
          ++this.scanner.index;
        }
        this.scanner.lineStart = this.scanner.index;
      }
    }
    this.lastMarker.index = this.scanner.index;
    this.lastMarker.line = this.scanner.lineNumber;
    this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
    const token = {
      type: 101 /* Text */,
      value: text,
      lineNumber: this.scanner.lineNumber,
      lineStart: this.scanner.lineStart,
      start,
      end: this.scanner.index
    };
    if (text.length > 0 && this.config.tokens) {
      this.tokens.push(this.convertToken(token));
    }
    return token;
  }
  peekJSXToken() {
    const state = this.scanner.saveState();
    this.scanner.scanComments();
    const next = this.lexJSX();
    this.scanner.restoreState(state);
    return next;
  }
  // Expect the next JSX token to match the specified punctuator.
  // If not, an exception will be thrown.
  expectJSX(value) {
    const token = this.nextJSXToken();
    if (token.type !== 7 /* Punctuator */ || token.value !== value) {
      this.throwUnexpectedToken(token);
    }
  }
  // Return true if the next JSX token matches the specified punctuator.
  matchJSX(value) {
    const next = this.peekJSXToken();
    return next.type === 7 /* Punctuator */ && next.value === value;
  }
  parseJSXIdentifier() {
    const node = this.createJSXNode();
    const token = this.nextJSXToken();
    if (token.type !== 100 /* Identifier */) {
      this.throwUnexpectedToken(token);
    }
    return this.finalize(node, new JSXIdentifier(token.value));
  }
  parseJSXElementName() {
    const node = this.createJSXNode();
    let elementName = this.parseJSXIdentifier();
    if (this.matchJSX(":")) {
      const namespace = elementName;
      this.expectJSX(":");
      const name = this.parseJSXIdentifier();
      elementName = this.finalize(node, new JSXNamespacedName(namespace, name));
    } else if (this.matchJSX(".")) {
      while (this.matchJSX(".")) {
        const object = elementName;
        this.expectJSX(".");
        const property = this.parseJSXIdentifier();
        elementName = this.finalize(node, new JSXMemberExpression(object, property));
      }
    }
    return elementName;
  }
  parseJSXAttributeName() {
    const node = this.createJSXNode();
    let attributeName;
    const identifier = this.parseJSXIdentifier();
    if (this.matchJSX(":")) {
      const namespace = identifier;
      this.expectJSX(":");
      const name = this.parseJSXIdentifier();
      attributeName = this.finalize(node, new JSXNamespacedName(namespace, name));
    } else {
      attributeName = identifier;
    }
    return attributeName;
  }
  parseJSXStringLiteralAttribute() {
    const node = this.createJSXNode();
    const token = this.nextJSXToken();
    if (token.type !== 8 /* StringLiteral */) {
      this.throwUnexpectedToken(token);
    }
    const raw = this.getTokenRaw(token);
    return this.finalize(node, new Literal(token.value, raw));
  }
  parseJSXExpressionAttribute() {
    const node = this.createJSXNode();
    this.expectJSX("{");
    this.finishJSX();
    if (this.match("}")) {
      this.tolerateError("JSX attributes must only be assigned a non-empty expression");
    }
    const expression = this.parseAssignmentExpression();
    this.reenterJSX();
    return this.finalize(node, new JSXExpressionContainer(expression));
  }
  parseJSXAttributeValue() {
    return this.matchJSX("{") ? this.parseJSXExpressionAttribute() : this.matchJSX("<") ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute();
  }
  parseJSXNameValueAttribute() {
    const node = this.createJSXNode();
    const name = this.parseJSXAttributeName();
    let value = null;
    if (this.matchJSX("=")) {
      this.expectJSX("=");
      value = this.parseJSXAttributeValue();
    }
    return this.finalize(node, new JSXAttribute(name, value));
  }
  parseJSXSpreadAttribute() {
    const node = this.createJSXNode();
    this.expectJSX("{");
    this.expectJSX("...");
    this.finishJSX();
    const argument = this.parseAssignmentExpression();
    this.reenterJSX();
    return this.finalize(node, new JSXSpreadAttribute(argument));
  }
  parseJSXAttributes() {
    const attributes = [];
    while (!this.matchJSX("/") && !this.matchJSX(">")) {
      const attribute = this.matchJSX("{") ? this.parseJSXSpreadAttribute() : this.parseJSXNameValueAttribute();
      attributes.push(attribute);
    }
    return attributes;
  }
  parseJSXOpeningElement() {
    const node = this.createJSXNode();
    this.expectJSX("<");
    if (this.matchJSX(">")) {
      this.expectJSX(">");
      return this.finalize(node, new JSXOpeningFragment(false));
    }
    const name = this.parseJSXElementName();
    const attributes = this.parseJSXAttributes();
    const selfClosing = this.matchJSX("/");
    if (selfClosing) {
      this.expectJSX("/");
    }
    this.expectJSX(">");
    return this.finalize(node, new JSXOpeningElement(name, selfClosing, attributes));
  }
  parseJSXBoundaryElement() {
    const node = this.createJSXNode();
    this.expectJSX("<");
    if (this.matchJSX("/")) {
      this.expectJSX("/");
      if (this.matchJSX(">")) {
        this.expectJSX(">");
        return this.finalize(node, new JSXClosingFragment());
      }
      const elementName = this.parseJSXElementName();
      this.expectJSX(">");
      return this.finalize(node, new JSXClosingElement(elementName));
    }
    const name = this.parseJSXElementName();
    const attributes = this.parseJSXAttributes();
    const selfClosing = this.matchJSX("/");
    if (selfClosing) {
      this.expectJSX("/");
    }
    this.expectJSX(">");
    return this.finalize(node, new JSXOpeningElement(name, selfClosing, attributes));
  }
  parseJSXEmptyExpression() {
    const node = this.createJSXChildNode();
    this.collectComments();
    this.lastMarker.index = this.scanner.index;
    this.lastMarker.line = this.scanner.lineNumber;
    this.lastMarker.column = this.scanner.index - this.scanner.lineStart;
    return this.finalize(node, new JSXEmptyExpression());
  }
  parseJSXExpressionContainer() {
    const node = this.createJSXNode();
    this.expectJSX("{");
    let expression;
    if (this.matchJSX("}")) {
      expression = this.parseJSXEmptyExpression();
      this.expectJSX("}");
    } else {
      this.finishJSX();
      expression = this.parseAssignmentExpression();
      this.reenterJSX();
    }
    return this.finalize(node, new JSXExpressionContainer(expression));
  }
  parseJSXChildren() {
    const children = [];
    while (!this.scanner.eof()) {
      const node = this.createJSXChildNode();
      const token = this.nextJSXText();
      if (token.start < token.end) {
        const raw = this.getTokenRaw(token);
        const child = this.finalize(node, new JSXText(token.value, raw));
        children.push(child);
      }
      if (this.scanner.source[this.scanner.index] === "{") {
        const container = this.parseJSXExpressionContainer();
        children.push(container);
      } else {
        break;
      }
    }
    return children;
  }
  parseComplexJSXElement(el) {
    const stack = [];
    while (!this.scanner.eof()) {
      el.children = el.children.concat(this.parseJSXChildren());
      const node = this.createJSXChildNode();
      const element = this.parseJSXBoundaryElement();
      if (element.type === "JSXOpeningElement" /* JSXOpeningElement */) {
        const opening = element;
        if (opening.selfClosing) {
          const child = this.finalize(node, new JSXElement(opening, [], null));
          el.children.push(child);
        } else {
          stack.push(el);
          el = { node, opening, closing: null, children: [] };
        }
      }
      if (element.type === "JSXClosingElement" /* JSXClosingElement */) {
        el.closing = element;
        const open = getQualifiedElementName(el.opening.name);
        const close = getQualifiedElementName(el.closing.name);
        if (open !== close) {
          this.tolerateError("Expected corresponding JSX closing tag for %0", open);
        }
        if (stack.length > 0) {
          const child = this.finalize(el.node, new JSXElement(el.opening, el.children, el.closing));
          el = stack[stack.length - 1];
          el.children.push(child);
          stack.pop();
        } else {
          break;
        }
      }
      if (element.type === "JSXClosingFragment" /* JSXClosingFragment */) {
        el.closing = element;
        if (el.opening.type !== "JSXOpeningFragment" /* JSXOpeningFragment */) {
          this.tolerateError("Expected corresponding JSX closing tag for jsx fragment");
        } else {
          break;
        }
      }
    }
    return el;
  }
  parseJSXElement() {
    const node = this.createJSXNode();
    const opening = this.parseJSXOpeningElement();
    let children = [];
    let closing = null;
    if (!opening.selfClosing) {
      const el = this.parseComplexJSXElement({ node, opening, closing, children });
      children = el.children;
      closing = el.closing;
    }
    return this.finalize(node, new JSXElement(opening, children, closing));
  }
  parseJSXRoot() {
    if (this.config.tokens) {
      this.tokens.pop();
    }
    this.startJSX();
    const element = this.parseJSXElement();
    this.finishJSX();
    return element;
  }
  isStartOfExpression() {
    return super.isStartOfExpression() || this.match("<");
  }
};

// src/tokenizer.ts
var beforeFunctionExpressionTokens = [
  "(",
  "{",
  "[",
  "in",
  "typeof",
  "instanceof",
  "new",
  "return",
  "case",
  "delete",
  "throw",
  "void",
  // assignment operators
  "=",
  "+=",
  "-=",
  "*=",
  "**=",
  "/=",
  "%=",
  "<<=",
  ">>=",
  ">>>=",
  "&=",
  "|=",
  "^=",
  ",",
  // binary/unary operators
  "+",
  "-",
  "*",
  "**",
  "/",
  "%",
  "++",
  "--",
  "<<",
  ">>",
  ">>>",
  "&",
  "|",
  "^",
  "!",
  "~",
  "&&",
  "||",
  "??",
  "?",
  ":",
  "===",
  "==",
  ">=",
  "<=",
  "<",
  ">",
  "!=",
  "!=="
];
var Reader = class {
  values;
  curly;
  paren;
  constructor() {
    this.values = [];
    this.curly = this.paren = -1;
  }
  // A function following one of those tokens is an expression.
  beforeFunctionExpression(t) {
    return beforeFunctionExpressionTokens.includes(t);
  }
  // Determine if forward slash (/) is an operator or part of a regular expression
  // https://github.com/mozilla/sweet.js/wiki/design
  isRegexStart() {
    const previous = this.values[this.values.length - 1];
    let regex = previous !== null;
    switch (previous) {
      case "this":
      case "]":
        regex = false;
        break;
      case ")":
        const keyword = this.values[this.paren - 1];
        regex = keyword === "if" || keyword === "while" || keyword === "for" || keyword === "with";
        break;
      case "}":
        regex = true;
        if (this.values[this.curly - 3] === "function") {
          const check = this.values[this.curly - 4];
          regex = check ? !this.beforeFunctionExpression(check) : false;
        } else if (this.values[this.curly - 4] === "function") {
          const check = this.values[this.curly - 5];
          regex = check ? !this.beforeFunctionExpression(check) : true;
        }
        break;
      default:
        break;
    }
    return regex;
  }
  push(token) {
    if (token.type === 7 /* Punctuator */ || token.type === 4 /* Keyword */) {
      if (token.value === "{") {
        this.curly = this.values.length;
      } else if (token.value === "(") {
        this.paren = this.values.length;
      }
      this.values.push(token.value);
    } else {
      this.values.push(null);
    }
  }
};
var Tokenizer = class {
  errorHandler;
  scanner;
  trackRange;
  trackLoc;
  buffer;
  reader;
  constructor(code, config) {
    this.errorHandler = new ErrorHandler();
    this.errorHandler.tolerant = config ? typeof config.tolerant === "boolean" && config.tolerant : false;
    this.scanner = new Scanner(code, this.errorHandler);
    this.scanner.trackComment = config ? typeof config.comment === "boolean" && config.comment : false;
    this.trackRange = config ? typeof config.range === "boolean" && config.range : false;
    this.trackLoc = config ? typeof config.loc === "boolean" && config.loc : false;
    this.buffer = [];
    this.reader = new Reader();
  }
  errors() {
    return this.errorHandler.errors;
  }
  getNextToken() {
    if (this.buffer.length === 0) {
      const comments = this.scanner.scanComments();
      if (this.scanner.trackComment) {
        for (let i = 0; i < comments.length; ++i) {
          const e = comments[i];
          const value = this.scanner.source.slice(e.slice[0], e.slice[1]);
          const comment = {
            type: e.multiLine ? "BlockComment" : "LineComment",
            value
          };
          if (this.trackRange) {
            comment.range = e.range;
          }
          if (this.trackLoc) {
            comment.loc = e.loc;
          }
          this.buffer.push(comment);
        }
      }
      if (!this.scanner.eof()) {
        let loc;
        if (this.trackLoc) {
          loc = {
            start: {
              line: this.scanner.lineNumber,
              column: this.scanner.index - this.scanner.lineStart
            },
            end: {}
          };
        }
        const maybeRegex = this.scanner.source[this.scanner.index] === "/" && this.reader.isRegexStart();
        let token;
        if (maybeRegex) {
          const state = this.scanner.saveState();
          try {
            token = this.scanner.scanRegExp();
          } catch (e) {
            this.scanner.restoreState(state);
            token = this.scanner.lex();
          }
        } else {
          token = this.scanner.lex();
        }
        this.reader.push(token);
        const entry = {
          type: TokenName[token.type],
          value: this.scanner.source.slice(token.start, token.end)
        };
        if (this.trackRange) {
          entry.range = [token.start, token.end];
        }
        if (this.trackLoc) {
          loc.end = {
            line: this.scanner.lineNumber,
            column: this.scanner.index - this.scanner.lineStart
          };
          entry.loc = loc;
        }
        if (token.type === 9 /* RegularExpression */) {
          const pattern = token.pattern;
          const flags = token.flags;
          entry.regex = { pattern, flags };
        }
        this.buffer.push(entry);
      }
    }
    return this.buffer.shift();
  }
};

// src/visitor.ts
var Visitor = class {
  visit(node) {
    if (node == null)
      return node;
    switch (node.type) {
      case "AssignmentExpression" /* AssignmentExpression */:
        return this.visitAssignmentExpression(node);
      case "AssignmentPattern" /* AssignmentPattern */:
        return this.visitAssignmentPattern(node);
      case "ArrayExpression" /* ArrayExpression */:
        return this.visitArrayExpression(node);
      case "ArrayPattern" /* ArrayPattern */:
        return this.visitArrayPattern(node);
      case "ArrowFunctionExpression" /* ArrowFunctionExpression */:
        return this.visitArrowFunctionExpression(node);
      case "AwaitExpression" /* AwaitExpression */:
        return this.visitAwaitExpression(node);
      case "BlockStatement" /* BlockStatement */:
        return this.visitBlockStatement(node);
      case "BinaryExpression" /* BinaryExpression */:
        return this.visitBinaryExpression(node);
      case "BreakStatement" /* BreakStatement */:
        return this.visitBreakStatement(node);
      case "CallExpression" /* CallExpression */:
        return this.visitCallExpression(node);
      case "CatchClause" /* CatchClause */:
        return this.visitCatchClause(node);
      case "ChainExpression" /* ChainExpression */:
        return this.visitChainExpression(node);
      case "ClassBody" /* ClassBody */:
        return this.visitClassBody(node);
      case "ClassDeclaration" /* ClassDeclaration */:
        return this.visitClassDeclaration(node);
      case "ClassExpression" /* ClassExpression */:
        return this.visitClassExpression(node);
      case "ConditionalExpression" /* ConditionalExpression */:
        return this.visitConditionalExpression(node);
      case "ContinueStatement" /* ContinueStatement */:
        return this.visitContinueStatement(node);
      case "Decorator" /* Decorator */:
        return this.visitDecorator(node);
      case "DoWhileStatement" /* DoWhileStatement */:
        return this.visitDoWhileStatement(node);
      case "DebuggerStatement" /* DebuggerStatement */:
        return this.visitDebuggerStatement(node);
      case "EmptyStatement" /* EmptyStatement */:
        return this.visitEmptyStatement(node);
      case "ExportAllDeclaration" /* ExportAllDeclaration */:
        return this.visitExportAllDeclaration(node);
      case "ExportDefaultDeclaration" /* ExportDefaultDeclaration */:
        return this.visitExportDefaultDeclaration(node);
      case "ExportNamedDeclaration" /* ExportNamedDeclaration */:
        return this.visitExportNamedDeclaration(node);
      case "ExportSpecifier" /* ExportSpecifier */:
        return this.visitExportSpecifier(node);
      case "ExpressionStatement" /* ExpressionStatement */:
        return this.visitExpressionStatement(node);
      case "ForStatement" /* ForStatement */:
        return this.visitForStatement(node);
      case "ForOfStatement" /* ForOfStatement */:
        return this.visitForOfStatement(node);
      case "ForInStatement" /* ForInStatement */:
        return this.visitForInStatement(node);
      case "FunctionDeclaration" /* FunctionDeclaration */:
        return this.visitFunctionDeclaration(node);
      case "FunctionExpression" /* FunctionExpression */:
        return this.visitFunctionExpression(node);
      case "Identifier" /* Identifier */:
        return this.visitIdentifier(node);
      case "IfStatement" /* IfStatement */:
        return this.visitIfStatement(node);
      case "ImportAttribute" /* ImportAttribute */:
        return this.visitImportAttribute(node);
      case "ImportExpression" /* ImportExpression */:
        return this.visitImportExpression(node);
      case "ImportDeclaration" /* ImportDeclaration */:
        return this.visitImportDeclaration(node);
      case "ImportDefaultSpecifier" /* ImportDefaultSpecifier */:
        return this.visitImportDefaultSpecifier(node);
      case "ImportNamespaceSpecifier" /* ImportNamespaceSpecifier */:
        return this.visitImportNamespaceSpecifier(node);
      case "ImportSpecifier" /* ImportSpecifier */:
        return this.visitImportSpecifier(node);
      case "Literal" /* Literal */:
        return this.visitLiteral(node);
      case "LabeledStatement" /* LabeledStatement */:
        return this.visitLabeledStatement(node);
      case "LogicalExpression" /* LogicalExpression */:
        return this.visitLogicalExpression(node);
      case "MemberExpression" /* MemberExpression */:
        return this.visitMemberExpression(node);
      case "MetaProperty" /* MetaProperty */:
        return this.visitMetaProperty(node);
      case "MethodDefinition" /* MethodDefinition */:
        return this.visitMethodDefinition(node);
      case "NewExpression" /* NewExpression */:
        return this.visitNewExpression(node);
      case "ObjectExpression" /* ObjectExpression */:
        return this.visitObjectExpression(node);
      case "ObjectPattern" /* ObjectPattern */:
        return this.visitObjectPattern(node);
      case "Program" /* Program */:
        return this.visitProgram(node);
      case "Property" /* Property */:
        return this.visitProperty(node);
      case "PrivateIdentifier" /* PrivateIdentifier */:
        return this.visitPrivateIdentifier(node);
      case "RestElement" /* RestElement */:
        return this.visitRestElement(node);
      case "ReturnStatement" /* ReturnStatement */:
        return this.visitReturnStatement(node);
      case "SequenceExpression" /* SequenceExpression */:
        return this.visitSequenceExpression(node);
      case "SpreadElement" /* SpreadElement */:
        return this.visitSpreadElement(node);
      case "StaticBlock" /* StaticBlock */:
        return this.visitStaticBlock(node);
      case "Super" /* Super */:
        return this.visitSuper(node);
      case "SwitchCase" /* SwitchCase */:
        return this.visitSwitchCase(node);
      case "SwitchStatement" /* SwitchStatement */:
        return this.visitSwitchStatement(node);
      case "TaggedTemplateExpression" /* TaggedTemplateExpression */:
        return this.visitTaggedTemplateExpression(node);
      case "TemplateElement" /* TemplateElement */:
        return this.visitTemplateElement(node);
      case "TemplateLiteral" /* TemplateLiteral */:
        return this.visitTemplateLiteral(node);
      case "ThisExpression" /* ThisExpression */:
        return this.visitThisExpression(node);
      case "ThrowStatement" /* ThrowStatement */:
        return this.visitThrowStatement(node);
      case "TryStatement" /* TryStatement */:
        return this.visitTryStatement(node);
      case "UnaryExpression" /* UnaryExpression */:
        return this.visitUnaryExpression(node);
      case "UpdateExpression" /* UpdateExpression */:
        return this.visitUpdateExpression(node);
      case "VariableDeclaration" /* VariableDeclaration */:
        return this.visitVariableDeclaration(node);
      case "VariableDeclarator" /* VariableDeclarator */:
        return this.visitVariableDeclarator(node);
      case "WhileStatement" /* WhileStatement */:
        return this.visitWhileStatement(node);
      case "WithStatement" /* WithStatement */:
        return this.visitWithStatement(node);
      case "YieldExpression" /* YieldExpression */:
        return this.visitYieldExpression(node);
    }
  }
  visitNodeList(original) {
    if (original == null)
      return original;
    let list = null;
    for (let i = 0, n = original.length; i < n; i++) {
      let p = this.visit(original[i]);
      if (list != null) {
        list.push(p);
      } else if (p != original[i]) {
        list = [];
        for (let j = 0; j < i; j++) {
          list.push(original[j]);
        }
        list.push(p);
      }
    }
    if (list != null)
      return list;
    return original;
  }
  visitAssignmentExpression(node) {
    const left = this.visit(node.left);
    const right = this.visit(node.right);
    if (left !== node.left || right !== node.right)
      return new AssignmentExpression(node.operator, left, right);
    return node;
  }
  visitAssignmentPattern(node) {
    const left = this.visit(node.left);
    const right = this.visit(node.right);
    if (left !== node.left || right !== node.right)
      return new AssignmentPattern(left, right);
    return node;
  }
  visitArrayExpression(node) {
    const elements = this.visitNodeList(node.elements);
    if (elements !== node.elements)
      return new ArrayExpression(elements);
    return node;
  }
  visitArrayPattern(node) {
    const elements = this.visitNodeList(node.elements);
    if (elements !== node.elements)
      return new ArrayPattern(elements);
    return node;
  }
  visitArrowFunctionExpression(node) {
    const id = this.visit(node.id);
    const params = this.visitNodeList(node.params);
    const body = this.visit(node.body);
    if (id !== node.id || params !== node.params || body !== node.body) {
      const ret = new ArrowFunctionExpression(params, body, node.expression, node.async);
      ret.id = id;
      return ret;
    }
    return node;
  }
  visitAwaitExpression(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new AwaitExpression(argument);
    return node;
  }
  visitBlockStatement(node) {
    const body = this.visitNodeList(node.body);
    if (body !== node.body)
      return new BlockStatement(body);
    return node;
  }
  visitBinaryExpression(node) {
    const left = this.visit(node.left);
    const right = this.visit(node.right);
    if (left !== node.left || right !== node.right)
      return new BinaryExpression(node.operator, left, right);
    return node;
  }
  visitBreakStatement(node) {
    const label = this.visit(node.label);
    if (label !== node.label)
      return new BreakStatement(label);
    return node;
  }
  visitCallExpression(node) {
    const callee = this.visit(node.callee);
    const args = this.visitNodeList(node.arguments);
    if (callee !== node.callee || args !== node.arguments)
      return new CallExpression(callee, args, node.optional);
    return node;
  }
  visitCatchClause(node) {
    const param = this.visit(node.param);
    const body = this.visit(node.body);
    if (param !== node.param || body !== node.body)
      return new CatchClause(param, body);
    return node;
  }
  visitChainExpression(node) {
    const expression = this.visit(node.expression);
    if (expression !== node.expression)
      return new ChainExpression(expression);
    return node;
  }
  visitClassBody(node) {
    const body = this.visitNodeList(node.body);
    if (body !== node.body)
      return new ClassBody(body);
    return node;
  }
  visitClassDeclaration(node) {
    const id = this.visit(node.id);
    const superClass = this.visit(node.superClass);
    const body = this.visit(node.body);
    const decorators = this.visitNodeList(node.decorators);
    if (id !== node.id || superClass !== node.superClass || body !== node.body || decorators !== node.decorators)
      return new ClassDeclaration(id, superClass, body, decorators);
    return node;
  }
  visitClassExpression(node) {
    const id = this.visit(node.id);
    const superClass = this.visit(node.superClass);
    const body = this.visit(node.body);
    const decorators = this.visitNodeList(node.decorators);
    if (id !== node.id || superClass !== node.superClass || body !== node.body || decorators !== node.decorators)
      return new ClassExpression(id, superClass, body, decorators);
    return node;
  }
  visitConditionalExpression(node) {
    const test = this.visit(node.test);
    const consequent = this.visit(node.consequent);
    const alternate = this.visit(node.alternate);
    if (test !== node.test || consequent !== node.consequent || alternate !== node.alternate)
      return new ConditionalExpression(test, consequent, alternate);
    return node;
  }
  visitContinueStatement(node) {
    const label = this.visit(node.label);
    if (label !== node.label)
      return new ContinueStatement(label);
    return node;
  }
  visitDecorator(node) {
    const expression = this.visit(node.expression);
    if (expression !== node.expression)
      return new Decorator(expression);
    return node;
  }
  visitDoWhileStatement(node) {
    const body = this.visit(node.body);
    const test = this.visit(node.test);
    if (body !== node.body || test !== node.test)
      return new DoWhileStatement(body, test);
    return node;
  }
  visitDebuggerStatement(node) {
    return node;
  }
  visitEmptyStatement(node) {
    return node;
  }
  visitExportAllDeclaration(node) {
    const source = this.visit(node.source);
    const exported = this.visit(node.exported);
    const assertions = this.visitNodeList(node.assertions);
    if (source !== node.source || exported !== node.exported || assertions !== node.assertions)
      return new ExportAllDeclaration(source, exported, assertions);
    return node;
  }
  visitExportDefaultDeclaration(node) {
    const declaration = this.visit(node.declaration);
    if (declaration !== node.declaration)
      return new ExportDefaultDeclaration(declaration);
    return node;
  }
  visitExportNamedDeclaration(node) {
    const declaration = this.visit(node.declaration);
    const specifiers = this.visitNodeList(node.specifiers);
    const source = this.visit(node.source);
    const assertions = this.visitNodeList(node.assertions);
    if (declaration !== node.declaration || specifiers !== node.specifiers || source !== node.source || assertions !== node.assertions)
      return new ExportNamedDeclaration(declaration, specifiers, source, assertions);
    return node;
  }
  visitExportSpecifier(node) {
    const exported = this.visit(node.exported);
    const local = this.visit(node.local);
    if (exported !== node.exported || local !== node.local)
      return new ExportSpecifier(exported, local);
    return node;
  }
  visitExpressionStatement(node) {
    const expression = this.visit(node.expression);
    if (expression !== node.expression)
      return new ExpressionStatement(expression);
    return node;
  }
  visitForStatement(node) {
    const init = this.visit(node.init);
    const test = this.visit(node.test);
    const update = this.visit(node.update);
    const body = this.visit(node.body);
    if (init !== node.init || test !== node.test || update !== node.update || body !== node.body)
      return new ForStatement(init, test, update, body);
    return node;
  }
  visitForOfStatement(node) {
    const left = this.visit(node.left);
    const right = this.visit(node.right);
    const body = this.visit(node.body);
    if (left !== node.left || right !== node.right || body !== node.body)
      return new ForOfStatement(left, right, body, node.await);
    return node;
  }
  visitForInStatement(node) {
    const left = this.visit(node.left);
    const right = this.visit(node.right);
    const body = this.visit(node.body);
    if (left !== node.left || right !== node.right || body !== node.body)
      return new ForInStatement(left, right, body);
    return node;
  }
  visitFunctionDeclaration(node) {
    const id = this.visit(node.id);
    const params = this.visitNodeList(node.params);
    const body = this.visit(node.body);
    if (id !== node.id || params !== node.params || body !== node.body)
      return new FunctionDeclaration(id, params, body, node.generator);
    return node;
  }
  visitFunctionExpression(node) {
    const id = this.visit(node.id);
    const params = this.visitNodeList(node.params);
    const body = this.visit(node.body);
    if (id !== node.id || params !== node.params || body !== node.body)
      return new FunctionExpression(id, params, body, node.generator, node.async);
    return node;
  }
  visitIdentifier(node) {
    return node;
  }
  visitIfStatement(node) {
    const test = this.visit(node.test);
    const consequent = this.visit(node.consequent);
    const alternate = this.visit(node.alternate);
    if (test !== node.test || consequent !== node.consequent || alternate !== node.alternate)
      return new IfStatement(test, consequent, alternate);
    return node;
  }
  visitImportAttribute(node) {
    const key = this.visit(node.key);
    const value = this.visit(node.value);
    if (key !== node.key || value !== node.value)
      return new ImportAttribute(key, value);
    return node;
  }
  visitImportExpression(node) {
    const source = this.visit(node.source);
    const attributes = this.visit(node.attributes);
    if (source !== node.source || attributes !== node.attributes)
      return new ImportExpression(source, attributes);
    return node;
  }
  visitImportDeclaration(node) {
    const specifiers = this.visitNodeList(node.specifiers);
    const source = this.visit(node.source);
    const assertions = this.visitNodeList(node.assertions);
    if (specifiers !== node.specifiers || source !== node.source || assertions !== node.assertions)
      return new ImportDeclaration(specifiers, source, assertions);
    return node;
  }
  visitImportDefaultSpecifier(node) {
    const local = this.visit(node.local);
    if (local !== node.local)
      return new ImportDefaultSpecifier(local);
    return node;
  }
  visitImportNamespaceSpecifier(node) {
    const local = this.visit(node.local);
    if (local !== node.local)
      return new ImportNamespaceSpecifier(local);
    return node;
  }
  visitImportSpecifier(node) {
    const local = this.visit(node.local);
    const imported = this.visit(node.imported);
    if (local !== node.local || imported !== node.imported)
      return new ImportSpecifier(local, imported);
    return node;
  }
  visitLiteral(node) {
    return node;
  }
  visitLabeledStatement(node) {
    const label = this.visit(node.label);
    const body = this.visit(node.body);
    if (label !== node.label || body !== node.body)
      return new LabeledStatement(label, body);
    return node;
  }
  visitLogicalExpression(node) {
    const left = this.visit(node.left);
    const right = this.visit(node.right);
    if (left !== node.left || right !== node.right)
      return new LogicalExpression(node.operator, left, right);
    return node;
  }
  visitMemberExpression(node) {
    const _object = this.visit(node.object);
    const property = this.visit(node.property);
    if (_object !== node.object || property !== node.property)
      return new MemberExpression(node.computed, _object, property, node.optional);
    return node;
  }
  visitMetaProperty(node) {
    const meta = this.visit(node.meta);
    const property = this.visit(node.property);
    if (meta !== node.meta || property !== node.property)
      return new MetaProperty(meta, property);
    return node;
  }
  visitMethodDefinition(node) {
    const key = this.visit(node.key);
    const value = this.visit(node.value);
    const decorators = this.visitNodeList(node.decorators);
    if (key !== node.key || value !== node.value || decorators !== node.decorators)
      return new MethodDefinition(key, node.computed, value, node.kind, node.static, decorators);
    return node;
  }
  visitNewExpression(node) {
    const callee = this.visit(node.callee);
    const args = this.visitNodeList(node.arguments);
    if (callee !== node.callee || args !== node.arguments)
      return new NewExpression(callee, args);
    return node;
  }
  visitObjectExpression(node) {
    const properties = this.visitNodeList(node.properties);
    if (properties !== node.properties)
      return new ObjectExpression(properties);
    return node;
  }
  visitObjectPattern(node) {
    const properties = this.visitNodeList(node.properties);
    if (properties !== node.properties)
      return new ObjectPattern(properties);
    return node;
  }
  visitProgram(node) {
    const body = this.visitNodeList(node.body);
    if (body !== node.body)
      return new Program(node.sourceType, body);
    return node;
  }
  visitProperty(node) {
    const key = this.visit(node.key);
    const value = this.visit(node.value);
    const decorators = this.visitNodeList(node.decorators);
    if (key !== node.key || value !== node.value || decorators !== decorators) {
      if ("kind" in node)
        return new Property(node.kind, key, node.computed, value, node.method, node.shorthand);
      else
        return new PropertyDefinition(key, node.computed, value, node.static, decorators);
    }
    return node;
  }
  visitPrivateIdentifier(node) {
    return node;
  }
  visitRestElement(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new RestElement(argument);
    return node;
  }
  visitReturnStatement(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new ReturnStatement(argument);
    return node;
  }
  visitSequenceExpression(node) {
    const expressions = this.visitNodeList(node.expressions);
    if (expressions !== node.expressions)
      return new SequenceExpression(expressions);
    return node;
  }
  visitSpreadElement(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new SpreadElement(argument);
    return node;
  }
  visitStaticBlock(node) {
    const body = this.visitNodeList(node.body);
    if (body !== node.body)
      return new StaticBlock(body);
    return node;
  }
  visitSuper(node) {
    return node;
  }
  visitSwitchCase(node) {
    const test = this.visit(node.test);
    const consequent = this.visitNodeList(node.consequent);
    if (test !== node.test || consequent !== node.consequent)
      return new SwitchCase(test, consequent);
    return node;
  }
  visitSwitchStatement(node) {
    const discriminant = this.visit(node.discriminant);
    const cases = this.visitNodeList(node.cases);
    if (discriminant !== node.discriminant || cases !== node.cases)
      return new SwitchStatement(discriminant, cases);
    return node;
  }
  visitTaggedTemplateExpression(node) {
    const tag = this.visit(node.tag);
    const quasi = this.visit(node.quasi);
    if (tag !== node.tag || quasi !== node.quasi)
      return new TaggedTemplateExpression(tag, quasi);
    return node;
  }
  visitTemplateElement(node) {
    return node;
  }
  visitTemplateLiteral(node) {
    const quasis = this.visitNodeList(node.quasis);
    const expressions = this.visitNodeList(node.expressions);
    if (quasis !== node.quasis || expressions !== node.expressions)
      return new TemplateLiteral(quasis, expressions);
    return node;
  }
  visitThisExpression(node) {
    return node;
  }
  visitThrowStatement(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new ThrowStatement(argument);
    return node;
  }
  visitTryStatement(node) {
    const block = this.visit(node.block);
    const handler = this.visit(node.handler);
    const finalizer = this.visit(node.finalizer);
    if (block !== node.block || handler !== node.handler || finalizer !== node.finalizer)
      return new TryStatement(block, handler, finalizer);
    return node;
  }
  visitUnaryExpression(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new UnaryExpression(node.operator, argument);
    return node;
  }
  visitUpdateExpression(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new UpdateExpression(node.operator, argument, node.prefix);
    return node;
  }
  visitVariableDeclaration(node) {
    const declarations = this.visitNodeList(node.declarations);
    if (declarations !== node.declarations)
      return new VariableDeclaration(declarations, node.kind);
    return node;
  }
  visitVariableDeclarator(node) {
    const id = this.visit(node.id);
    const init = this.visit(node.init);
    if (id !== node.id || init !== node.init)
      return new VariableDeclarator(id, init);
    return node;
  }
  visitWhileStatement(node) {
    const test = this.visit(node.test);
    const body = this.visit(node.body);
    if (test !== node.test || body !== node.body)
      return new WhileStatement(test, body);
    return node;
  }
  visitWithStatement(node) {
    const _object = this.visit(node.object);
    const body = this.visit(node.body);
    if (_object !== node.object || body !== node.body)
      return new WithStatement(_object, body);
    return node;
  }
  visitYieldExpression(node) {
    const argument = this.visit(node.argument);
    if (argument !== node.argument)
      return new YieldExpression(argument, node.delegate);
    return node;
  }
};

// src/esprima.ts
function parse(code, options, delegate) {
  let commentHandler = null;
  const proxyDelegate = (node, metadata) => {
    if (delegate) {
      delegate(node, metadata);
    }
    if (commentHandler) {
      commentHandler.visit(node, metadata);
    }
  };
  let parserDelegate = typeof delegate === "function" ? proxyDelegate : null;
  let collectComment = false;
  if (options) {
    collectComment = typeof options.comment === "boolean" && options.comment;
    const attachComment = typeof options.attachComment === "boolean" && options.attachComment;
    if (collectComment || attachComment) {
      commentHandler = new CommentHandler();
      commentHandler.attach = attachComment;
      options.comment = true;
      parserDelegate = proxyDelegate;
    }
  }
  let isModule = false;
  if (options && typeof options.sourceType === "string") {
    isModule = options.sourceType === "module";
  }
  let parser;
  if (options && typeof options.jsx === "boolean" && options.jsx) {
    parser = new JSXParser(code, options, parserDelegate);
  } else {
    parser = new Parser(code, options, parserDelegate);
  }
  const program = isModule ? parser.parseModule() : parser.parseScript();
  const ast = program;
  if (collectComment && commentHandler) {
    ast.comments = commentHandler.comments;
  }
  if (parser.config.tokens) {
    ast.tokens = parser.tokens;
  }
  if (parser.config.tolerant) {
    ast.errors = parser.errorHandler.errors;
  }
  return ast;
}
function parseModule(code, options, delegate) {
  const parsingOptions = options || {};
  parsingOptions.sourceType = "module";
  return parse(code, parsingOptions, delegate);
}
function parseScript(code, options, delegate) {
  const parsingOptions = options || {};
  parsingOptions.sourceType = "script";
  return parse(code, parsingOptions, delegate);
}
function tokenize(code, options, delegate) {
  const tokenizer = new Tokenizer(code, options);
  const tokens = [];
  try {
    while (true) {
      let token = tokenizer.getNextToken();
      if (!token) {
        break;
      }
      if (delegate) {
        token = delegate(token);
      }
      tokens.push(token);
    }
  } catch (e) {
    tokenizer.errorHandler.tolerate(e);
  }
  if (tokenizer.errorHandler.tolerant) {
    tokens.errors = tokenizer.errors();
  }
  return tokens;
}
var version = "6.0.3";
var esprima_default = {
  parse,
  parseModule,
  parseScript,
  tokenize,
  Syntax,
  version
};



/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
(() => {
/*!******************************!*\
  !*** ./src/esprima-next.mjs ***!
  \******************************/
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   runTest: () => (/* binding */ runTest)
/* harmony export */ });
/* harmony import */ var esprima_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! esprima-next */ "./node_modules/esprima-next/dist/esprima.js");
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.



const payloads = [
  "backbone-1.6.1.js",
  "jquery-3.7.1.js",
  "mootools-core-1.6.0.js",
  "underscore-1.13.7.js",
];

function runTest(fileData) {
  const testData = payloads.map((name) => fileData[name]);

  return testData.map((payload) => {
    let count = 0;
    count += esprima_next__WEBPACK_IMPORTED_MODULE_0__.tokenize(payload, { loc: true, range: true }).length;
    count += esprima_next__WEBPACK_IMPORTED_MODULE_0__.parse(payload, { loc: true, range: true }).body.length;
    return count;
  });
}

})();

self.WTBenchmark = __webpack_exports__;
/******/ })()
;