import {
  addRange,
  addRelatedInfo,
  append,
  AssertionLevel,
  attachFileToDiagnostics,
  canHaveJSDoc,
  canHaveModifiers,
  CharacterCodes,
  commentPragmas,
  concatenate,
  containsParseError,
  convertToJson,
  createDetachedDiagnostic,
  createNodeFactory,
  createScanner,
  createTextChangeRange,
  createTextSpanFromBounds,
  Debug,
  Diagnostics,
  emptyArray,
  emptyMap,
  ensureScriptKind,
  Extension,
  fileExtensionIs,
  fileExtensionIsOneOf,
  findIndex,
  firstOrUndefined,
  forEach,
  getBaseFileName,
  getBinaryOperatorPrecedence,
  getFullWidth,
  getJSDocCommentRanges,
  getLanguageVariant,
  getLastChild,
  getLeadingCommentRanges,
  getSpellingSuggestion,
  getTextOfNodeFromSourceText,
  hasJSDocNodes,
  idText,
  isArray,
  isAssignmentOperator,
  isAsyncModifier,
  isClassMemberModifier,
  isExportAssignment,
  isExportDeclaration,
  isExportModifier,
  isExpressionWithTypeArguments,
  isExternalModuleReference,
  isFunctionTypeNode,
  isIdentifier as isIdentifierNode,
  isIdentifierText,
  isImportDeclaration,
  isImportEqualsDeclaration,
  isJSDocFunctionType,
  isJSDocNullableType,
  isJSDocReturnTag,
  isJSDocTypeTag,
  isJsxNamespacedName,
  isJsxOpeningElement,
  isJsxOpeningFragment,
  isKeyword,
  isKeywordOrPunctuation,
  isLeftHandSideExpression,
  isLiteralKind,
  isMetaProperty,
  isModifierKind,
  isNonNullExpression,
  isPrivateIdentifier,
  isSetAccessorDeclaration,
  isStringOrNumericLiteralLike,
  isTaggedTemplateExpression,
  isTemplateLiteralKind,
  isTypeReferenceNode,
  JSDocParsingMode,
  LanguageVariant,
  lastOrUndefined,
  map,
  mapDefined,
  ModifierFlags,
  modifiersToFlags,
  ModuleKind,
  NodeFactoryFlags,
  NodeFlags,
  nodeIsMissing,
  nodeIsPresent,
  noop,
  normalizePath,
  objectAllocator,
  OperatorPrecedence,
  perfLogger,
  PragmaKindFlags,
  ScriptKind,
  ScriptTarget,
  setParent,
  setParentRecursive,
  setTextRange,
  setTextRangePos,
  setTextRangePosEnd,
  setTextRangePosWidth,
  skipTrivia,
  some,
  startsWith,
  supportedDeclarationExtensions,
  SyntaxKind,
  textChangeRangeIsUnchanged,
  textChangeRangeNewSpan,
  textSpanEnd,
  textToKeywordObj,
  toArray,
  TokenFlags,
  tokenIsIdentifierOrKeyword,
  tokenIsIdentifierOrKeywordOrGreaterThan,
  tokenToString,
  tracing,
  TransformFlags,
  unescapeLeadingUnderscores
} from "./_namespaces/ts";
import * as performance from "./_namespaces/ts.performance";
var SignatureFlags = /* @__PURE__ */ ((SignatureFlags2) => {
  SignatureFlags2[SignatureFlags2["None"] = 0] = "None";
  SignatureFlags2[SignatureFlags2["Yield"] = 1] = "Yield";
  SignatureFlags2[SignatureFlags2["Await"] = 2] = "Await";
  SignatureFlags2[SignatureFlags2["Type"] = 4] = "Type";
  SignatureFlags2[SignatureFlags2["IgnoreMissingOpenBrace"] = 16] = "IgnoreMissingOpenBrace";
  SignatureFlags2[SignatureFlags2["JSDoc"] = 32] = "JSDoc";
  return SignatureFlags2;
})(SignatureFlags || {});
var SpeculationKind = /* @__PURE__ */ ((SpeculationKind2) => {
  SpeculationKind2[SpeculationKind2["TryParse"] = 0] = "TryParse";
  SpeculationKind2[SpeculationKind2["Lookahead"] = 1] = "Lookahead";
  SpeculationKind2[SpeculationKind2["Reparse"] = 2] = "Reparse";
  return SpeculationKind2;
})(SpeculationKind || {});
let NodeConstructor;
let TokenConstructor;
let IdentifierConstructor;
let PrivateIdentifierConstructor;
let SourceFileConstructor;
export const parseBaseNodeFactory = {
  createBaseSourceFileNode: (kind) => new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, -1, -1),
  createBaseIdentifierNode: (kind) => new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, -1, -1),
  createBasePrivateIdentifierNode: (kind) => new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, -1, -1),
  createBaseTokenNode: (kind) => new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, -1, -1),
  createBaseNode: (kind) => new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, -1, -1)
};
export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules, parseBaseNodeFactory);
function visitNode(cbNode, node) {
  return node && cbNode(node);
}
function visitNodes(cbNode, cbNodes, nodes) {
  if (nodes) {
    if (cbNodes) {
      return cbNodes(nodes);
    }
    for (const node of nodes) {
      const result = cbNode(node);
      if (result) {
        return result;
      }
    }
  }
}
export function isJSDocLikeText(text, start) {
  return text.charCodeAt(start + 1) === CharacterCodes.asterisk && text.charCodeAt(start + 2) === CharacterCodes.asterisk && text.charCodeAt(start + 3) !== CharacterCodes.slash;
}
export function isFileProbablyExternalModule(sourceFile) {
  return forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || getImportMetaIfNecessary(sourceFile);
}
function isAnExternalModuleIndicatorNode(node) {
  return canHaveModifiers(node) && hasModifierOfKind(node, SyntaxKind.ExportKeyword) || isImportEqualsDeclaration(node) && isExternalModuleReference(node.moduleReference) || isImportDeclaration(node) || isExportAssignment(node) || isExportDeclaration(node) ? node : void 0;
}
function getImportMetaIfNecessary(sourceFile) {
  return sourceFile.flags & NodeFlags.PossiblyContainsImportMeta ? walkTreeForImportMeta(sourceFile) : void 0;
}
function walkTreeForImportMeta(node) {
  return isImportMeta(node) ? node : forEachChild(node, walkTreeForImportMeta);
}
function hasModifierOfKind(node, kind) {
  return some(node.modifiers, (m) => m.kind === kind);
}
function isImportMeta(node) {
  return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta";
}
const forEachChildTable = {
  [SyntaxKind.QualifiedName]: function forEachChildInQualifiedName(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.left) || visitNode(cbNode, node.right);
  },
  [SyntaxKind.TypeParameter]: function forEachChildInTypeParameter(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.constraint) || visitNode(cbNode, node.default) || visitNode(cbNode, node.expression);
  },
  [SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.equalsToken) || visitNode(cbNode, node.objectAssignmentInitializer);
  },
  [SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.Parameter]: function forEachChildInParameter(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.PropertySignature]: function forEachChildInPropertySignature(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name) || visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.BindingElement]: function forEachChildInBindingElement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.IndexSignature]: function forEachChildInIndexSignature(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.ConstructorType]: function forEachChildInConstructorType(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.FunctionType]: function forEachChildInFunctionType(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.CallSignature]: forEachChildInCallOrConstructSignature,
  [SyntaxKind.ConstructSignature]: forEachChildInCallOrConstructSignature,
  [SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.exclamationToken) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.MethodSignature]: function forEachChildInMethodSignature(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.Constructor]: function forEachChildInConstructor(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.GetAccessor]: function forEachChildInGetAccessor(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.SetAccessor]: function forEachChildInSetAccessor(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type) || visitNode(cbNode, node.equalsGreaterThanToken) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.TypeReference]: function forEachChildInTypeReference(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.typeName) || visitNodes(cbNode, cbNodes, node.typeArguments);
  },
  [SyntaxKind.TypePredicate]: function forEachChildInTypePredicate(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.assertsModifier) || visitNode(cbNode, node.parameterName) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.TypeQuery]: function forEachChildInTypeQuery(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.exprName) || visitNodes(cbNode, cbNodes, node.typeArguments);
  },
  [SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.members);
  },
  [SyntaxKind.ArrayType]: function forEachChildInArrayType(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.elementType);
  },
  [SyntaxKind.TupleType]: function forEachChildInTupleType(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.elements);
  },
  [SyntaxKind.UnionType]: forEachChildInUnionOrIntersectionType,
  [SyntaxKind.IntersectionType]: forEachChildInUnionOrIntersectionType,
  [SyntaxKind.ConditionalType]: function forEachChildInConditionalType(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.checkType) || visitNode(cbNode, node.extendsType) || visitNode(cbNode, node.trueType) || visitNode(cbNode, node.falseType);
  },
  [SyntaxKind.InferType]: function forEachChildInInferType(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.typeParameter);
  },
  [SyntaxKind.ImportType]: function forEachChildInImportType(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.argument) || visitNode(cbNode, node.attributes) || visitNode(cbNode, node.qualifier) || visitNodes(cbNode, cbNodes, node.typeArguments);
  },
  [SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.assertClause);
  },
  [SyntaxKind.ParenthesizedType]: forEachChildInParenthesizedTypeOrTypeOperator,
  [SyntaxKind.TypeOperator]: forEachChildInParenthesizedTypeOrTypeOperator,
  [SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.objectType) || visitNode(cbNode, node.indexType);
  },
  [SyntaxKind.MappedType]: function forEachChildInMappedType(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.readonlyToken) || visitNode(cbNode, node.typeParameter) || visitNode(cbNode, node.nameType) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNodes(cbNode, cbNodes, node.members);
  },
  [SyntaxKind.LiteralType]: function forEachChildInLiteralType(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.literal);
  },
  [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.ObjectBindingPattern]: forEachChildInObjectOrArrayBindingPattern,
  [SyntaxKind.ArrayBindingPattern]: forEachChildInObjectOrArrayBindingPattern,
  [SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.elements);
  },
  [SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.properties);
  },
  [SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.questionDotToken) || visitNode(cbNode, node.name);
  },
  [SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.questionDotToken) || visitNode(cbNode, node.argumentExpression);
  },
  [SyntaxKind.CallExpression]: forEachChildInCallOrNewExpression,
  [SyntaxKind.NewExpression]: forEachChildInCallOrNewExpression,
  [SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tag) || visitNode(cbNode, node.questionDotToken) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.template);
  },
  [SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.type) || visitNode(cbNode, node.expression);
  },
  [SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.VoidExpression]: function forEachChildInVoidExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.operand);
  },
  [SyntaxKind.YieldExpression]: function forEachChildInYieldExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.expression);
  },
  [SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.operand);
  },
  [SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.left) || visitNode(cbNode, node.operatorToken) || visitNode(cbNode, node.right);
  },
  [SyntaxKind.AsExpression]: function forEachChildInAsExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name);
  },
  [SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.condition) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.whenTrue) || visitNode(cbNode, node.colonToken) || visitNode(cbNode, node.whenFalse);
  },
  [SyntaxKind.SpreadElement]: function forEachChildInSpreadElement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.Block]: forEachChildInBlock,
  [SyntaxKind.ModuleBlock]: forEachChildInBlock,
  [SyntaxKind.SourceFile]: function forEachChildInSourceFile(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.statements) || visitNode(cbNode, node.endOfFileToken);
  },
  [SyntaxKind.VariableStatement]: function forEachChildInVariableStatement(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.declarationList);
  },
  [SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.declarations);
  },
  [SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.IfStatement]: function forEachChildInIfStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.thenStatement) || visitNode(cbNode, node.elseStatement);
  },
  [SyntaxKind.DoStatement]: function forEachChildInDoStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.statement) || visitNode(cbNode, node.expression);
  },
  [SyntaxKind.WhileStatement]: function forEachChildInWhileStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
  },
  [SyntaxKind.ForStatement]: function forEachChildInForStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.condition) || visitNode(cbNode, node.incrementor) || visitNode(cbNode, node.statement);
  },
  [SyntaxKind.ForInStatement]: function forEachChildInForInStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
  },
  [SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.awaitModifier) || visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
  },
  [SyntaxKind.ContinueStatement]: forEachChildInContinueOrBreakStatement,
  [SyntaxKind.BreakStatement]: forEachChildInContinueOrBreakStatement,
  [SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.WithStatement]: function forEachChildInWithStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement);
  },
  [SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.caseBlock);
  },
  [SyntaxKind.CaseBlock]: function forEachChildInCaseBlock(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.clauses);
  },
  [SyntaxKind.CaseClause]: function forEachChildInCaseClause(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.statements);
  },
  [SyntaxKind.DefaultClause]: function forEachChildInDefaultClause(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.statements);
  },
  [SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.label) || visitNode(cbNode, node.statement);
  },
  [SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.TryStatement]: function forEachChildInTryStatement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.tryBlock) || visitNode(cbNode, node.catchClause) || visitNode(cbNode, node.finallyBlock);
  },
  [SyntaxKind.CatchClause]: function forEachChildInCatchClause(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.variableDeclaration) || visitNode(cbNode, node.block);
  },
  [SyntaxKind.Decorator]: function forEachChildInDecorator(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.ClassDeclaration]: forEachChildInClassDeclarationOrExpression,
  [SyntaxKind.ClassExpression]: forEachChildInClassDeclarationOrExpression,
  [SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.heritageClauses) || visitNodes(cbNode, cbNodes, node.members);
  },
  [SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.members);
  },
  [SyntaxKind.EnumMember]: function forEachChildInEnumMember(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.body);
  },
  [SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.moduleReference);
  },
  [SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.importClause) || visitNode(cbNode, node.moduleSpecifier) || visitNode(cbNode, node.attributes);
  },
  [SyntaxKind.ImportClause]: function forEachChildInImportClause(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name) || visitNode(cbNode, node.namedBindings);
  },
  [SyntaxKind.ImportAttributes]: function forEachChildInImportAttributes(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.elements);
  },
  [SyntaxKind.ImportAttribute]: function forEachChildInImportAttribute(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name) || visitNode(cbNode, node.value);
  },
  [SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name);
  },
  [SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name);
  },
  [SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name);
  },
  [SyntaxKind.NamedImports]: forEachChildInNamedImportsOrExports,
  [SyntaxKind.NamedExports]: forEachChildInNamedImportsOrExports,
  [SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.exportClause) || visitNode(cbNode, node.moduleSpecifier) || visitNode(cbNode, node.attributes);
  },
  [SyntaxKind.ImportSpecifier]: forEachChildInImportOrExportSpecifier,
  [SyntaxKind.ExportSpecifier]: forEachChildInImportOrExportSpecifier,
  [SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.expression);
  },
  [SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.head) || visitNodes(cbNode, cbNodes, node.templateSpans);
  },
  [SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal);
  },
  [SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.head) || visitNodes(cbNode, cbNodes, node.templateSpans);
  },
  [SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.type) || visitNode(cbNode, node.literal);
  },
  [SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.HeritageClause]: function forEachChildInHeritageClause(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.types);
  },
  [SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.typeArguments);
  },
  [SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.modifiers);
  },
  [SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.elements);
  },
  [SyntaxKind.JsxElement]: function forEachChildInJsxElement(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.openingElement) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingElement);
  },
  [SyntaxKind.JsxFragment]: function forEachChildInJsxFragment(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.openingFragment) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingFragment);
  },
  [SyntaxKind.JsxSelfClosingElement]: forEachChildInJsxOpeningOrSelfClosingElement,
  [SyntaxKind.JsxOpeningElement]: forEachChildInJsxOpeningOrSelfClosingElement,
  [SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.properties);
  },
  [SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer);
  },
  [SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.expression);
  },
  [SyntaxKind.JsxExpression]: function forEachChildInJsxExpression(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.expression);
  },
  [SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.tagName);
  },
  [SyntaxKind.JsxNamespacedName]: function forEachChildInJsxNamespacedName(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.namespace) || visitNode(cbNode, node.name);
  },
  [SyntaxKind.OptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier,
  [SyntaxKind.RestType]: forEachChildInOptionalRestOrJSDocParameterModifier,
  [SyntaxKind.JSDocTypeExpression]: forEachChildInOptionalRestOrJSDocParameterModifier,
  [SyntaxKind.JSDocNonNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier,
  [SyntaxKind.JSDocNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier,
  [SyntaxKind.JSDocOptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier,
  [SyntaxKind.JSDocVariadicType]: forEachChildInOptionalRestOrJSDocParameterModifier,
  [SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType(node, cbNode, cbNodes) {
    return visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.JSDoc]: function forEachChildInJSDoc(node, cbNode, cbNodes) {
    return (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment)) || visitNodes(cbNode, cbNodes, node.tags);
  },
  [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.name) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
  },
  [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.name);
  },
  [SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName(node, cbNode, _cbNodes) {
    return visitNode(cbNode, node.left) || visitNode(cbNode, node.right);
  },
  [SyntaxKind.JSDocParameterTag]: forEachChildInJSDocParameterOrPropertyTag,
  [SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag,
  [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tagName) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
  },
  [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.class) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
  },
  [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.class) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
  },
  [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.constraint) || visitNodes(cbNode, cbNodes, node.typeParameters) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
  },
  [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tagName) || (node.typeExpression && node.typeExpression.kind === SyntaxKind.JSDocTypeExpression ? visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.fullName) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment)) : visitNode(cbNode, node.fullName) || visitNode(cbNode, node.typeExpression) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment)));
  },
  [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag(node, cbNode, cbNodes) {
    return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.fullName) || visitNode(cbNode, node.typeExpression) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
  },
  [SyntaxKind.JSDocReturnTag]: forEachChildInJSDocTypeLikeTag,
  [SyntaxKind.JSDocTypeTag]: forEachChildInJSDocTypeLikeTag,
  [SyntaxKind.JSDocThisTag]: forEachChildInJSDocTypeLikeTag,
  [SyntaxKind.JSDocEnumTag]: forEachChildInJSDocTypeLikeTag,
  [SyntaxKind.JSDocSatisfiesTag]: forEachChildInJSDocTypeLikeTag,
  [SyntaxKind.JSDocThrowsTag]: forEachChildInJSDocTypeLikeTag,
  [SyntaxKind.JSDocOverloadTag]: forEachChildInJSDocTypeLikeTag,
  [SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature(node, cbNode, _cbNodes) {
    return forEach(node.typeParameters, cbNode) || forEach(node.parameters, cbNode) || visitNode(cbNode, node.type);
  },
  [SyntaxKind.JSDocLink]: forEachChildInJSDocLinkCodeOrPlain,
  [SyntaxKind.JSDocLinkCode]: forEachChildInJSDocLinkCodeOrPlain,
  [SyntaxKind.JSDocLinkPlain]: forEachChildInJSDocLinkCodeOrPlain,
  [SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral(node, cbNode, _cbNodes) {
    return forEach(node.jsDocPropertyTags, cbNode);
  },
  [SyntaxKind.JSDocTag]: forEachChildInJSDocTag,
  [SyntaxKind.JSDocClassTag]: forEachChildInJSDocTag,
  [SyntaxKind.JSDocPublicTag]: forEachChildInJSDocTag,
  [SyntaxKind.JSDocPrivateTag]: forEachChildInJSDocTag,
  [SyntaxKind.JSDocProtectedTag]: forEachChildInJSDocTag,
  [SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag,
  [SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag,
  [SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag,
  [SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression
};
function forEachChildInCallOrConstructSignature(node, cbNode, cbNodes) {
  return visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type);
}
function forEachChildInUnionOrIntersectionType(node, cbNode, cbNodes) {
  return visitNodes(cbNode, cbNodes, node.types);
}
function forEachChildInParenthesizedTypeOrTypeOperator(node, cbNode, _cbNodes) {
  return visitNode(cbNode, node.type);
}
function forEachChildInObjectOrArrayBindingPattern(node, cbNode, cbNodes) {
  return visitNodes(cbNode, cbNodes, node.elements);
}
function forEachChildInCallOrNewExpression(node, cbNode, cbNodes) {
  return visitNode(cbNode, node.expression) || // TODO: should we separate these branches out?
  visitNode(cbNode, node.questionDotToken) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNodes(cbNode, cbNodes, node.arguments);
}
function forEachChildInBlock(node, cbNode, cbNodes) {
  return visitNodes(cbNode, cbNodes, node.statements);
}
function forEachChildInContinueOrBreakStatement(node, cbNode, _cbNodes) {
  return visitNode(cbNode, node.label);
}
function forEachChildInClassDeclarationOrExpression(node, cbNode, cbNodes) {
  return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.heritageClauses) || visitNodes(cbNode, cbNodes, node.members);
}
function forEachChildInNamedImportsOrExports(node, cbNode, cbNodes) {
  return visitNodes(cbNode, cbNodes, node.elements);
}
function forEachChildInImportOrExportSpecifier(node, cbNode, _cbNodes) {
  return visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name);
}
function forEachChildInJsxOpeningOrSelfClosingElement(node, cbNode, cbNodes) {
  return visitNode(cbNode, node.tagName) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.attributes);
}
function forEachChildInOptionalRestOrJSDocParameterModifier(node, cbNode, _cbNodes) {
  return visitNode(cbNode, node.type);
}
function forEachChildInJSDocParameterOrPropertyTag(node, cbNode, cbNodes) {
  return visitNode(cbNode, node.tagName) || (node.isNameFirst ? visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression) : visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name)) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
}
function forEachChildInJSDocTypeLikeTag(node, cbNode, cbNodes) {
  return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.typeExpression) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
}
function forEachChildInJSDocLinkCodeOrPlain(node, cbNode, _cbNodes) {
  return visitNode(cbNode, node.name);
}
function forEachChildInJSDocTag(node, cbNode, cbNodes) {
  return visitNode(cbNode, node.tagName) || (typeof node.comment === "string" ? void 0 : visitNodes(cbNode, cbNodes, node.comment));
}
function forEachChildInPartiallyEmittedExpression(node, cbNode, _cbNodes) {
  return visitNode(cbNode, node.expression);
}
export function forEachChild(node, cbNode, cbNodes) {
  if (node === void 0 || node.kind <= SyntaxKind.LastToken) {
    return;
  }
  const fn = forEachChildTable[node.kind];
  return fn === void 0 ? void 0 : fn(node, cbNode, cbNodes);
}
export function forEachChildRecursively(rootNode, cbNode, cbNodes) {
  const queue = gatherPossibleChildren(rootNode);
  const parents = [];
  while (parents.length < queue.length) {
    parents.push(rootNode);
  }
  while (queue.length !== 0) {
    const current = queue.pop();
    const parent = parents.pop();
    if (isArray(current)) {
      if (cbNodes) {
        const res = cbNodes(current, parent);
        if (res) {
          if (res === "skip") continue;
          return res;
        }
      }
      for (let i = current.length - 1; i >= 0; --i) {
        queue.push(current[i]);
        parents.push(parent);
      }
    } else {
      const res = cbNode(current, parent);
      if (res) {
        if (res === "skip") continue;
        return res;
      }
      if (current.kind >= SyntaxKind.FirstNode) {
        for (const child of gatherPossibleChildren(current)) {
          queue.push(child);
          parents.push(current);
        }
      }
    }
  }
}
function gatherPossibleChildren(node) {
  const children = [];
  forEachChild(node, addWorkItem, addWorkItem);
  return children;
  function addWorkItem(n) {
    children.unshift(n);
  }
}
function setExternalModuleIndicator(sourceFile) {
  sourceFile.externalModuleIndicator = isFileProbablyExternalModule(sourceFile);
}
export function createSourceFile(fileName, sourceText, languageVersionOrOptions, setParentNodes = false, scriptKind) {
  tracing?.push(
    tracing.Phase.Parse,
    "createSourceFile",
    { path: fileName },
    /*separateBeginAndEnd*/
    true
  );
  performance.mark("beforeParse");
  let result;
  perfLogger?.logStartParseSourceFile(fileName);
  const {
    languageVersion,
    setExternalModuleIndicator: overrideSetExternalModuleIndicator,
    impliedNodeFormat: format,
    jsDocParsingMode
  } = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions : { languageVersion: languageVersionOrOptions };
  if (languageVersion === ScriptTarget.JSON) {
    result = Parser.parseSourceFile(
      fileName,
      sourceText,
      languageVersion,
      /*syntaxCursor*/
      void 0,
      setParentNodes,
      ScriptKind.JSON,
      noop,
      jsDocParsingMode
    );
  } else {
    const setIndicator = format === void 0 ? overrideSetExternalModuleIndicator : (file) => {
      file.impliedNodeFormat = format;
      return (overrideSetExternalModuleIndicator || setExternalModuleIndicator)(file);
    };
    result = Parser.parseSourceFile(
      fileName,
      sourceText,
      languageVersion,
      /*syntaxCursor*/
      void 0,
      setParentNodes,
      scriptKind,
      setIndicator,
      jsDocParsingMode
    );
  }
  perfLogger?.logStopParseSourceFile();
  performance.mark("afterParse");
  performance.measure("Parse", "beforeParse", "afterParse");
  tracing?.pop();
  return result;
}
export function parseIsolatedEntityName(text, languageVersion) {
  return Parser.parseIsolatedEntityName(text, languageVersion);
}
export function parseJsonText(fileName, sourceText) {
  return Parser.parseJsonText(fileName, sourceText);
}
export function isExternalModule(file) {
  return file.externalModuleIndicator !== void 0;
}
export function updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks = false) {
  const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
  newSourceFile.flags |= sourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags;
  return newSourceFile;
}
export function parseIsolatedJSDocComment(content, start, length) {
  const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
  if (result && result.jsDoc) {
    Parser.fixupParentReferences(result.jsDoc);
  }
  return result;
}
export function parseJSDocTypeExpressionForTests(content, start, length) {
  return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length);
}
var Parser;
((Parser2) => {
  var scanner = createScanner(
    ScriptTarget.Latest,
    /*skipTrivia*/
    true
  );
  var disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext;
  var NodeConstructor2;
  var TokenConstructor2;
  var IdentifierConstructor2;
  var PrivateIdentifierConstructor2;
  var SourceFileConstructor2;
  function countNode(node) {
    nodeCount++;
    return node;
  }
  var baseNodeFactory = {
    createBaseSourceFileNode: (kind) => countNode(new SourceFileConstructor2(
      kind,
      /*pos*/
      0,
      /*end*/
      0
    )),
    createBaseIdentifierNode: (kind) => countNode(new IdentifierConstructor2(
      kind,
      /*pos*/
      0,
      /*end*/
      0
    )),
    createBasePrivateIdentifierNode: (kind) => countNode(new PrivateIdentifierConstructor2(
      kind,
      /*pos*/
      0,
      /*end*/
      0
    )),
    createBaseTokenNode: (kind) => countNode(new TokenConstructor2(
      kind,
      /*pos*/
      0,
      /*end*/
      0
    )),
    createBaseNode: (kind) => countNode(new NodeConstructor2(
      kind,
      /*pos*/
      0,
      /*end*/
      0
    ))
  };
  var factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, baseNodeFactory);
  var {
    createNodeArray: factoryCreateNodeArray,
    createNumericLiteral: factoryCreateNumericLiteral,
    createStringLiteral: factoryCreateStringLiteral,
    createLiteralLikeNode: factoryCreateLiteralLikeNode,
    createIdentifier: factoryCreateIdentifier,
    createPrivateIdentifier: factoryCreatePrivateIdentifier,
    createToken: factoryCreateToken,
    createArrayLiteralExpression: factoryCreateArrayLiteralExpression,
    createObjectLiteralExpression: factoryCreateObjectLiteralExpression,
    createPropertyAccessExpression: factoryCreatePropertyAccessExpression,
    createPropertyAccessChain: factoryCreatePropertyAccessChain,
    createElementAccessExpression: factoryCreateElementAccessExpression,
    createElementAccessChain: factoryCreateElementAccessChain,
    createCallExpression: factoryCreateCallExpression,
    createCallChain: factoryCreateCallChain,
    createNewExpression: factoryCreateNewExpression,
    createParenthesizedExpression: factoryCreateParenthesizedExpression,
    createBlock: factoryCreateBlock,
    createVariableStatement: factoryCreateVariableStatement,
    createExpressionStatement: factoryCreateExpressionStatement,
    createIfStatement: factoryCreateIfStatement,
    createWhileStatement: factoryCreateWhileStatement,
    createForStatement: factoryCreateForStatement,
    createForOfStatement: factoryCreateForOfStatement,
    createVariableDeclaration: factoryCreateVariableDeclaration,
    createVariableDeclarationList: factoryCreateVariableDeclarationList
  } = factory;
  var fileName;
  var sourceFlags;
  var sourceText;
  var languageVersion;
  var scriptKind;
  var languageVariant;
  var parseDiagnostics;
  var jsDocDiagnostics;
  var syntaxCursor;
  var currentToken;
  var nodeCount;
  var identifiers;
  var identifierCount;
  var parsingContext;
  var notParenthesizedArrow;
  var contextFlags;
  var topLevel = true;
  var parseErrorBeforeNextFinishedNode = false;
  function parseSourceFile(fileName2, sourceText2, languageVersion2, syntaxCursor2, setParentNodes = false, scriptKind2, setExternalModuleIndicatorOverride, jsDocParsingMode = JSDocParsingMode.ParseAll) {
    scriptKind2 = ensureScriptKind(fileName2, scriptKind2);
    if (scriptKind2 === ScriptKind.JSON) {
      const result2 = parseJsonText2(fileName2, sourceText2, languageVersion2, syntaxCursor2, setParentNodes);
      convertToJson(
        result2,
        result2.statements[0]?.expression,
        result2.parseDiagnostics,
        /*returnValue*/
        false,
        /*jsonConversionNotifier*/
        void 0
      );
      result2.referencedFiles = emptyArray;
      result2.typeReferenceDirectives = emptyArray;
      result2.libReferenceDirectives = emptyArray;
      result2.amdDependencies = emptyArray;
      result2.hasNoDefaultLib = false;
      result2.pragmas = emptyMap;
      return result2;
    }
    initializeState(fileName2, sourceText2, languageVersion2, syntaxCursor2, scriptKind2, jsDocParsingMode);
    const result = parseSourceFileWorker(languageVersion2, setParentNodes, scriptKind2, setExternalModuleIndicatorOverride || setExternalModuleIndicator, jsDocParsingMode);
    clearState();
    return result;
  }
  Parser2.parseSourceFile = parseSourceFile;
  function parseIsolatedEntityName2(content, languageVersion2) {
    initializeState(
      "",
      content,
      languageVersion2,
      /*syntaxCursor*/
      void 0,
      ScriptKind.JS,
      JSDocParsingMode.ParseAll
    );
    nextToken();
    const entityName = parseEntityName(
      /*allowReservedWords*/
      true
    );
    const isValid = token() === SyntaxKind.EndOfFileToken && !parseDiagnostics.length;
    clearState();
    return isValid ? entityName : void 0;
  }
  Parser2.parseIsolatedEntityName = parseIsolatedEntityName2;
  function parseJsonText2(fileName2, sourceText2, languageVersion2 = ScriptTarget.ES2015, syntaxCursor2, setParentNodes = false) {
    initializeState(fileName2, sourceText2, languageVersion2, syntaxCursor2, ScriptKind.JSON, JSDocParsingMode.ParseAll);
    sourceFlags = contextFlags;
    nextToken();
    const pos = getNodePos();
    let statements, endOfFileToken;
    if (token() === SyntaxKind.EndOfFileToken) {
      statements = createNodeArray([], pos, pos);
      endOfFileToken = parseTokenNode();
    } else {
      let expressions;
      while (token() !== SyntaxKind.EndOfFileToken) {
        let expression2;
        switch (token()) {
          case SyntaxKind.OpenBracketToken:
            expression2 = parseArrayLiteralExpression();
            break;
          case SyntaxKind.TrueKeyword:
          case SyntaxKind.FalseKeyword:
          case SyntaxKind.NullKeyword:
            expression2 = parseTokenNode();
            break;
          case SyntaxKind.MinusToken:
            if (lookAhead(() => nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken)) {
              expression2 = parsePrefixUnaryExpression();
            } else {
              expression2 = parseObjectLiteralExpression();
            }
            break;
          case SyntaxKind.NumericLiteral:
          case SyntaxKind.StringLiteral:
            if (lookAhead(() => nextToken() !== SyntaxKind.ColonToken)) {
              expression2 = parseLiteralNode();
              break;
            }
          // falls through
          default:
            expression2 = parseObjectLiteralExpression();
            break;
        }
        if (expressions && isArray(expressions)) {
          expressions.push(expression2);
        } else if (expressions) {
          expressions = [expressions, expression2];
        } else {
          expressions = expression2;
          if (token() !== SyntaxKind.EndOfFileToken) {
            parseErrorAtCurrentToken(Diagnostics.Unexpected_token);
          }
        }
      }
      const expression = isArray(expressions) ? finishNode(factoryCreateArrayLiteralExpression(expressions), pos) : Debug.checkDefined(expressions);
      const statement = factoryCreateExpressionStatement(expression);
      finishNode(statement, pos);
      statements = createNodeArray([statement], pos);
      endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token);
    }
    const sourceFile = createSourceFile2(
      fileName2,
      ScriptTarget.ES2015,
      ScriptKind.JSON,
      /*isDeclarationFile*/
      false,
      statements,
      endOfFileToken,
      sourceFlags,
      noop
    );
    if (setParentNodes) {
      fixupParentReferences(sourceFile);
    }
    sourceFile.nodeCount = nodeCount;
    sourceFile.identifierCount = identifierCount;
    sourceFile.identifiers = identifiers;
    sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
    if (jsDocDiagnostics) {
      sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
    }
    const result = sourceFile;
    clearState();
    return result;
  }
  Parser2.parseJsonText = parseJsonText2;
  function initializeState(_fileName, _sourceText, _languageVersion, _syntaxCursor, _scriptKind, _jsDocParsingMode) {
    NodeConstructor2 = objectAllocator.getNodeConstructor();
    TokenConstructor2 = objectAllocator.getTokenConstructor();
    IdentifierConstructor2 = objectAllocator.getIdentifierConstructor();
    PrivateIdentifierConstructor2 = objectAllocator.getPrivateIdentifierConstructor();
    SourceFileConstructor2 = objectAllocator.getSourceFileConstructor();
    fileName = normalizePath(_fileName);
    sourceText = _sourceText;
    languageVersion = _languageVersion;
    syntaxCursor = _syntaxCursor;
    scriptKind = _scriptKind;
    languageVariant = getLanguageVariant(_scriptKind);
    parseDiagnostics = [];
    parsingContext = 0;
    identifiers = /* @__PURE__ */ new Map();
    identifierCount = 0;
    nodeCount = 0;
    sourceFlags = 0;
    topLevel = true;
    switch (scriptKind) {
      case ScriptKind.JS:
      case ScriptKind.JSX:
        contextFlags = NodeFlags.JavaScriptFile;
        break;
      case ScriptKind.JSON:
        contextFlags = NodeFlags.JavaScriptFile | NodeFlags.JsonFile;
        break;
      default:
        contextFlags = NodeFlags.None;
        break;
    }
    parseErrorBeforeNextFinishedNode = false;
    scanner.setText(sourceText);
    scanner.setOnError(scanError);
    scanner.setScriptTarget(languageVersion);
    scanner.setLanguageVariant(languageVariant);
    scanner.setScriptKind(scriptKind);
    scanner.setJSDocParsingMode(_jsDocParsingMode);
  }
  function clearState() {
    scanner.clearCommentDirectives();
    scanner.setText("");
    scanner.setOnError(void 0);
    scanner.setScriptKind(ScriptKind.Unknown);
    scanner.setJSDocParsingMode(JSDocParsingMode.ParseAll);
    sourceText = void 0;
    languageVersion = void 0;
    syntaxCursor = void 0;
    scriptKind = void 0;
    languageVariant = void 0;
    sourceFlags = 0;
    parseDiagnostics = void 0;
    jsDocDiagnostics = void 0;
    parsingContext = 0;
    identifiers = void 0;
    notParenthesizedArrow = void 0;
    topLevel = true;
  }
  function parseSourceFileWorker(languageVersion2, setParentNodes, scriptKind2, setExternalModuleIndicator2, jsDocParsingMode) {
    const isDeclarationFile = isDeclarationFileName(fileName);
    if (isDeclarationFile) {
      contextFlags |= NodeFlags.Ambient;
    }
    sourceFlags = contextFlags;
    nextToken();
    const statements = parseList(0 /* SourceElements */, parseStatement);
    Debug.assert(token() === SyntaxKind.EndOfFileToken);
    const endHasJSDoc = hasPrecedingJSDocComment();
    const endOfFileToken = withJSDoc(parseTokenNode(), endHasJSDoc);
    const sourceFile = createSourceFile2(fileName, languageVersion2, scriptKind2, isDeclarationFile, statements, endOfFileToken, sourceFlags, setExternalModuleIndicator2);
    processCommentPragmas(sourceFile, sourceText);
    processPragmasIntoFields(sourceFile, reportPragmaDiagnostic);
    sourceFile.commentDirectives = scanner.getCommentDirectives();
    sourceFile.nodeCount = nodeCount;
    sourceFile.identifierCount = identifierCount;
    sourceFile.identifiers = identifiers;
    sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
    sourceFile.jsDocParsingMode = jsDocParsingMode;
    if (jsDocDiagnostics) {
      sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
    }
    if (setParentNodes) {
      fixupParentReferences(sourceFile);
    }
    return sourceFile;
    function reportPragmaDiagnostic(pos, end, diagnostic) {
      parseDiagnostics.push(createDetachedDiagnostic(fileName, sourceText, pos, end, diagnostic));
    }
  }
  let hasDeprecatedTag = false;
  function withJSDoc(node, hasJSDoc) {
    if (!hasJSDoc) {
      return node;
    }
    Debug.assert(!node.jsDoc);
    const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), (comment) => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
    if (jsDoc.length) node.jsDoc = jsDoc;
    if (hasDeprecatedTag) {
      hasDeprecatedTag = false;
      node.flags |= NodeFlags.Deprecated;
    }
    return node;
  }
  function reparseTopLevelAwait(sourceFile) {
    const savedSyntaxCursor = syntaxCursor;
    const baseSyntaxCursor = IncrementalParser.createSyntaxCursor(sourceFile);
    syntaxCursor = { currentNode: currentNode2 };
    const statements = [];
    const savedParseDiagnostics = parseDiagnostics;
    parseDiagnostics = [];
    let pos = 0;
    let start = findNextStatementWithAwait(sourceFile.statements, 0);
    while (start !== -1) {
      const prevStatement = sourceFile.statements[pos];
      const nextStatement = sourceFile.statements[start];
      addRange(statements, sourceFile.statements, pos, start);
      pos = findNextStatementWithoutAwait(sourceFile.statements, start);
      const diagnosticStart = findIndex(savedParseDiagnostics, (diagnostic) => diagnostic.start >= prevStatement.pos);
      const diagnosticEnd = diagnosticStart >= 0 ? findIndex(savedParseDiagnostics, (diagnostic) => diagnostic.start >= nextStatement.pos, diagnosticStart) : -1;
      if (diagnosticStart >= 0) {
        addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart, diagnosticEnd >= 0 ? diagnosticEnd : void 0);
      }
      speculationHelper(() => {
        const savedContextFlags = contextFlags;
        contextFlags |= NodeFlags.AwaitContext;
        scanner.resetTokenState(nextStatement.pos);
        nextToken();
        while (token() !== SyntaxKind.EndOfFileToken) {
          const startPos = scanner.getTokenFullStart();
          const statement = parseListElement(0 /* SourceElements */, parseStatement);
          statements.push(statement);
          if (startPos === scanner.getTokenFullStart()) {
            nextToken();
          }
          if (pos >= 0) {
            const nonAwaitStatement = sourceFile.statements[pos];
            if (statement.end === nonAwaitStatement.pos) {
              break;
            }
            if (statement.end > nonAwaitStatement.pos) {
              pos = findNextStatementWithoutAwait(sourceFile.statements, pos + 1);
            }
          }
        }
        contextFlags = savedContextFlags;
      }, 2 /* Reparse */);
      start = pos >= 0 ? findNextStatementWithAwait(sourceFile.statements, pos) : -1;
    }
    if (pos >= 0) {
      const prevStatement = sourceFile.statements[pos];
      addRange(statements, sourceFile.statements, pos);
      const diagnosticStart = findIndex(savedParseDiagnostics, (diagnostic) => diagnostic.start >= prevStatement.pos);
      if (diagnosticStart >= 0) {
        addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart);
      }
    }
    syntaxCursor = savedSyntaxCursor;
    return factory.updateSourceFile(sourceFile, setTextRange(factoryCreateNodeArray(statements), sourceFile.statements));
    function containsPossibleTopLevelAwait(node) {
      return !(node.flags & NodeFlags.AwaitContext) && !!(node.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait);
    }
    function findNextStatementWithAwait(statements2, start2) {
      for (let i = start2; i < statements2.length; i++) {
        if (containsPossibleTopLevelAwait(statements2[i])) {
          return i;
        }
      }
      return -1;
    }
    function findNextStatementWithoutAwait(statements2, start2) {
      for (let i = start2; i < statements2.length; i++) {
        if (!containsPossibleTopLevelAwait(statements2[i])) {
          return i;
        }
      }
      return -1;
    }
    function currentNode2(position) {
      const node = baseSyntaxCursor.currentNode(position);
      if (topLevel && node && containsPossibleTopLevelAwait(node)) {
        node.intersectsChange = true;
      }
      return node;
    }
  }
  function fixupParentReferences(rootNode) {
    setParentRecursive(
      rootNode,
      /*incremental*/
      true
    );
  }
  Parser2.fixupParentReferences = fixupParentReferences;
  function createSourceFile2(fileName2, languageVersion2, scriptKind2, isDeclarationFile, statements, endOfFileToken, flags, setExternalModuleIndicator2) {
    let sourceFile = factory.createSourceFile(statements, endOfFileToken, flags);
    setTextRangePosWidth(sourceFile, 0, sourceText.length);
    setFields(sourceFile);
    if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) {
      sourceFile = reparseTopLevelAwait(sourceFile);
      setFields(sourceFile);
    }
    return sourceFile;
    function setFields(sourceFile2) {
      sourceFile2.text = sourceText;
      sourceFile2.bindDiagnostics = [];
      sourceFile2.bindSuggestionDiagnostics = void 0;
      sourceFile2.languageVersion = languageVersion2;
      sourceFile2.fileName = fileName2;
      sourceFile2.languageVariant = getLanguageVariant(scriptKind2);
      sourceFile2.isDeclarationFile = isDeclarationFile;
      sourceFile2.scriptKind = scriptKind2;
      setExternalModuleIndicator2(sourceFile2);
      sourceFile2.setExternalModuleIndicator = setExternalModuleIndicator2;
    }
  }
  function setContextFlag(val, flag) {
    if (val) {
      contextFlags |= flag;
    } else {
      contextFlags &= ~flag;
    }
  }
  function setDisallowInContext(val) {
    setContextFlag(val, NodeFlags.DisallowInContext);
  }
  function setYieldContext(val) {
    setContextFlag(val, NodeFlags.YieldContext);
  }
  function setDecoratorContext(val) {
    setContextFlag(val, NodeFlags.DecoratorContext);
  }
  function setAwaitContext(val) {
    setContextFlag(val, NodeFlags.AwaitContext);
  }
  function doOutsideOfContext(context, func) {
    const contextFlagsToClear = context & contextFlags;
    if (contextFlagsToClear) {
      setContextFlag(
        /*val*/
        false,
        contextFlagsToClear
      );
      const result = func();
      setContextFlag(
        /*val*/
        true,
        contextFlagsToClear
      );
      return result;
    }
    return func();
  }
  function doInsideOfContext(context, func) {
    const contextFlagsToSet = context & ~contextFlags;
    if (contextFlagsToSet) {
      setContextFlag(
        /*val*/
        true,
        contextFlagsToSet
      );
      const result = func();
      setContextFlag(
        /*val*/
        false,
        contextFlagsToSet
      );
      return result;
    }
    return func();
  }
  function allowInAnd(func) {
    return doOutsideOfContext(NodeFlags.DisallowInContext, func);
  }
  function disallowInAnd(func) {
    return doInsideOfContext(NodeFlags.DisallowInContext, func);
  }
  function allowConditionalTypesAnd(func) {
    return doOutsideOfContext(NodeFlags.DisallowConditionalTypesContext, func);
  }
  function disallowConditionalTypesAnd(func) {
    return doInsideOfContext(NodeFlags.DisallowConditionalTypesContext, func);
  }
  function doInYieldContext(func) {
    return doInsideOfContext(NodeFlags.YieldContext, func);
  }
  function doInDecoratorContext(func) {
    return doInsideOfContext(NodeFlags.DecoratorContext, func);
  }
  function doInAwaitContext(func) {
    return doInsideOfContext(NodeFlags.AwaitContext, func);
  }
  function doOutsideOfAwaitContext(func) {
    return doOutsideOfContext(NodeFlags.AwaitContext, func);
  }
  function doInYieldAndAwaitContext(func) {
    return doInsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func);
  }
  function doOutsideOfYieldAndAwaitContext(func) {
    return doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func);
  }
  function inContext(flags) {
    return (contextFlags & flags) !== 0;
  }
  function inYieldContext() {
    return inContext(NodeFlags.YieldContext);
  }
  function inDisallowInContext() {
    return inContext(NodeFlags.DisallowInContext);
  }
  function inDisallowConditionalTypesContext() {
    return inContext(NodeFlags.DisallowConditionalTypesContext);
  }
  function inDecoratorContext() {
    return inContext(NodeFlags.DecoratorContext);
  }
  function inAwaitContext() {
    return inContext(NodeFlags.AwaitContext);
  }
  function parseErrorAtCurrentToken(message, ...args) {
    return parseErrorAt(scanner.getTokenStart(), scanner.getTokenEnd(), message, ...args);
  }
  function parseErrorAtPosition(start, length, message, ...args) {
    const lastError = lastOrUndefined(parseDiagnostics);
    let result;
    if (!lastError || start !== lastError.start) {
      result = createDetachedDiagnostic(fileName, sourceText, start, length, message, ...args);
      parseDiagnostics.push(result);
    }
    parseErrorBeforeNextFinishedNode = true;
    return result;
  }
  function parseErrorAt(start, end, message, ...args) {
    return parseErrorAtPosition(start, end - start, message, ...args);
  }
  function parseErrorAtRange(range, message, ...args) {
    parseErrorAt(range.pos, range.end, message, ...args);
  }
  function scanError(message, length, arg0) {
    parseErrorAtPosition(scanner.getTokenEnd(), length, message, arg0);
  }
  function getNodePos() {
    return scanner.getTokenFullStart();
  }
  function hasPrecedingJSDocComment() {
    return scanner.hasPrecedingJSDocComment();
  }
  function token() {
    return currentToken;
  }
  function nextTokenWithoutCheck() {
    return currentToken = scanner.scan();
  }
  function nextTokenAnd(func) {
    nextToken();
    return func();
  }
  function nextToken() {
    if (isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) {
      parseErrorAt(scanner.getTokenStart(), scanner.getTokenEnd(), Diagnostics.Keywords_cannot_contain_escape_characters);
    }
    return nextTokenWithoutCheck();
  }
  function nextTokenJSDoc() {
    return currentToken = scanner.scanJsDocToken();
  }
  function nextJSDocCommentTextToken(inBackticks) {
    return currentToken = scanner.scanJSDocCommentTextToken(inBackticks);
  }
  function reScanGreaterToken() {
    return currentToken = scanner.reScanGreaterToken();
  }
  function reScanSlashToken() {
    return currentToken = scanner.reScanSlashToken();
  }
  function reScanTemplateToken(isTaggedTemplate) {
    return currentToken = scanner.reScanTemplateToken(isTaggedTemplate);
  }
  function reScanLessThanToken() {
    return currentToken = scanner.reScanLessThanToken();
  }
  function reScanHashToken() {
    return currentToken = scanner.reScanHashToken();
  }
  function scanJsxIdentifier() {
    return currentToken = scanner.scanJsxIdentifier();
  }
  function scanJsxText() {
    return currentToken = scanner.scanJsxToken();
  }
  function scanJsxAttributeValue() {
    return currentToken = scanner.scanJsxAttributeValue();
  }
  function speculationHelper(callback, speculationKind) {
    const saveToken = currentToken;
    const saveParseDiagnosticsLength = parseDiagnostics.length;
    const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
    const saveContextFlags = contextFlags;
    const result = speculationKind !== 0 /* TryParse */ ? scanner.lookAhead(callback) : scanner.tryScan(callback);
    Debug.assert(saveContextFlags === contextFlags);
    if (!result || speculationKind !== 0 /* TryParse */) {
      currentToken = saveToken;
      if (speculationKind !== 2 /* Reparse */) {
        parseDiagnostics.length = saveParseDiagnosticsLength;
      }
      parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
    }
    return result;
  }
  function lookAhead(callback) {
    return speculationHelper(callback, 1 /* Lookahead */);
  }
  function tryParse(callback) {
    return speculationHelper(callback, 0 /* TryParse */);
  }
  function isBindingIdentifier() {
    if (token() === SyntaxKind.Identifier) {
      return true;
    }
    return token() > SyntaxKind.LastReservedWord;
  }
  function isIdentifier() {
    if (token() === SyntaxKind.Identifier) {
      return true;
    }
    if (token() === SyntaxKind.YieldKeyword && inYieldContext()) {
      return false;
    }
    if (token() === SyntaxKind.AwaitKeyword && inAwaitContext()) {
      return false;
    }
    return token() > SyntaxKind.LastReservedWord;
  }
  function parseExpected(kind, diagnosticMessage, shouldAdvance = true) {
    if (token() === kind) {
      if (shouldAdvance) {
        nextToken();
      }
      return true;
    }
    if (diagnosticMessage) {
      parseErrorAtCurrentToken(diagnosticMessage);
    } else {
      parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
    }
    return false;
  }
  const viableKeywordSuggestions = Object.keys(textToKeywordObj).filter((keyword) => keyword.length > 2);
  function parseErrorForMissingSemicolonAfter(node) {
    if (isTaggedTemplateExpression(node)) {
      parseErrorAt(skipTrivia(sourceText, node.template.pos), node.template.end, Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings);
      return;
    }
    const expressionText = isIdentifierNode(node) ? idText(node) : void 0;
    if (!expressionText || !isIdentifierText(expressionText, languageVersion)) {
      parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
      return;
    }
    const pos = skipTrivia(sourceText, node.pos);
    switch (expressionText) {
      case "const":
      case "let":
      case "var":
        parseErrorAt(pos, node.end, Diagnostics.Variable_declaration_not_allowed_at_this_location);
        return;
      case "declare":
        return;
      case "interface":
        parseErrorForInvalidName(Diagnostics.Interface_name_cannot_be_0, Diagnostics.Interface_must_be_given_a_name, SyntaxKind.OpenBraceToken);
        return;
      case "is":
        parseErrorAt(pos, scanner.getTokenStart(), Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
        return;
      case "module":
      case "namespace":
        parseErrorForInvalidName(Diagnostics.Namespace_name_cannot_be_0, Diagnostics.Namespace_must_be_given_a_name, SyntaxKind.OpenBraceToken);
        return;
      case "type":
        parseErrorForInvalidName(Diagnostics.Type_alias_name_cannot_be_0, Diagnostics.Type_alias_must_be_given_a_name, SyntaxKind.EqualsToken);
        return;
    }
    const suggestion = getSpellingSuggestion(expressionText, viableKeywordSuggestions, (n) => n) ?? getSpaceSuggestion(expressionText);
    if (suggestion) {
      parseErrorAt(pos, node.end, Diagnostics.Unknown_keyword_or_identifier_Did_you_mean_0, suggestion);
      return;
    }
    if (token() === SyntaxKind.Unknown) {
      return;
    }
    parseErrorAt(pos, node.end, Diagnostics.Unexpected_keyword_or_identifier);
  }
  function parseErrorForInvalidName(nameDiagnostic, blankDiagnostic, tokenIfBlankName) {
    if (token() === tokenIfBlankName) {
      parseErrorAtCurrentToken(blankDiagnostic);
    } else {
      parseErrorAtCurrentToken(nameDiagnostic, scanner.getTokenValue());
    }
  }
  function getSpaceSuggestion(expressionText) {
    for (const keyword of viableKeywordSuggestions) {
      if (expressionText.length > keyword.length + 2 && startsWith(expressionText, keyword)) {
        return `${keyword} ${expressionText.slice(keyword.length)}`;
      }
    }
    return void 0;
  }
  function parseSemicolonAfterPropertyName(name, type, initializer) {
    if (token() === SyntaxKind.AtToken && !scanner.hasPrecedingLineBreak()) {
      parseErrorAtCurrentToken(Diagnostics.Decorators_must_precede_the_name_and_all_keywords_of_property_declarations);
      return;
    }
    if (token() === SyntaxKind.OpenParenToken) {
      parseErrorAtCurrentToken(Diagnostics.Cannot_start_a_function_call_in_a_type_annotation);
      nextToken();
      return;
    }
    if (type && !canParseSemicolon()) {
      if (initializer) {
        parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
      } else {
        parseErrorAtCurrentToken(Diagnostics.Expected_for_property_initializer);
      }
      return;
    }
    if (tryParseSemicolon()) {
      return;
    }
    if (initializer) {
      parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
      return;
    }
    parseErrorForMissingSemicolonAfter(name);
  }
  function parseExpectedJSDoc(kind) {
    if (token() === kind) {
      nextTokenJSDoc();
      return true;
    }
    Debug.assert(isKeywordOrPunctuation(kind));
    parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
    return false;
  }
  function parseExpectedMatchingBrackets(openKind, closeKind, openParsed, openPosition) {
    if (token() === closeKind) {
      nextToken();
      return;
    }
    const lastError = parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(closeKind));
    if (!openParsed) {
      return;
    }
    if (lastError) {
      addRelatedInfo(
        lastError,
        createDetachedDiagnostic(fileName, sourceText, openPosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, tokenToString(openKind), tokenToString(closeKind))
      );
    }
  }
  function parseOptional(t) {
    if (token() === t) {
      nextToken();
      return true;
    }
    return false;
  }
  function parseOptionalToken(t) {
    if (token() === t) {
      return parseTokenNode();
    }
    return void 0;
  }
  function parseOptionalTokenJSDoc(t) {
    if (token() === t) {
      return parseTokenNodeJSDoc();
    }
    return void 0;
  }
  function parseExpectedToken(t, diagnosticMessage, arg0) {
    return parseOptionalToken(t) || createMissingNode(
      t,
      /*reportAtCurrentPosition*/
      false,
      diagnosticMessage || Diagnostics._0_expected,
      arg0 || tokenToString(t)
    );
  }
  function parseExpectedTokenJSDoc(t) {
    const optional = parseOptionalTokenJSDoc(t);
    if (optional) return optional;
    Debug.assert(isKeywordOrPunctuation(t));
    return createMissingNode(
      t,
      /*reportAtCurrentPosition*/
      false,
      Diagnostics._0_expected,
      tokenToString(t)
    );
  }
  function parseTokenNode() {
    const pos = getNodePos();
    const kind = token();
    nextToken();
    return finishNode(factoryCreateToken(kind), pos);
  }
  function parseTokenNodeJSDoc() {
    const pos = getNodePos();
    const kind = token();
    nextTokenJSDoc();
    return finishNode(factoryCreateToken(kind), pos);
  }
  function canParseSemicolon() {
    if (token() === SyntaxKind.SemicolonToken) {
      return true;
    }
    return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak();
  }
  function tryParseSemicolon() {
    if (!canParseSemicolon()) {
      return false;
    }
    if (token() === SyntaxKind.SemicolonToken) {
      nextToken();
    }
    return true;
  }
  function parseSemicolon() {
    return tryParseSemicolon() || parseExpected(SyntaxKind.SemicolonToken);
  }
  function createNodeArray(elements, pos, end, hasTrailingComma) {
    const array = factoryCreateNodeArray(elements, hasTrailingComma);
    setTextRangePosEnd(array, pos, end ?? scanner.getTokenFullStart());
    return array;
  }
  function finishNode(node, pos, end) {
    setTextRangePosEnd(node, pos, end ?? scanner.getTokenFullStart());
    if (contextFlags) {
      node.flags |= contextFlags;
    }
    if (parseErrorBeforeNextFinishedNode) {
      parseErrorBeforeNextFinishedNode = false;
      node.flags |= NodeFlags.ThisNodeHasError;
    }
    return node;
  }
  function createMissingNode(kind, reportAtCurrentPosition, diagnosticMessage, ...args) {
    if (reportAtCurrentPosition) {
      parseErrorAtPosition(scanner.getTokenFullStart(), 0, diagnosticMessage, ...args);
    } else if (diagnosticMessage) {
      parseErrorAtCurrentToken(diagnosticMessage, ...args);
    }
    const pos = getNodePos();
    const result = kind === SyntaxKind.Identifier ? factoryCreateIdentifier(
      "",
      /*originalKeywordKind*/
      void 0
    ) : isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(
      kind,
      "",
      "",
      /*templateFlags*/
      void 0
    ) : kind === SyntaxKind.NumericLiteral ? factoryCreateNumericLiteral(
      "",
      /*numericLiteralFlags*/
      void 0
    ) : kind === SyntaxKind.StringLiteral ? factoryCreateStringLiteral(
      "",
      /*isSingleQuote*/
      void 0
    ) : kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() : factoryCreateToken(kind);
    return finishNode(result, pos);
  }
  function internIdentifier(text) {
    let identifier = identifiers.get(text);
    if (identifier === void 0) {
      identifiers.set(text, identifier = text);
    }
    return identifier;
  }
  function createIdentifier(isIdentifier2, diagnosticMessage, privateIdentifierDiagnosticMessage) {
    if (isIdentifier2) {
      identifierCount++;
      const pos = getNodePos();
      const originalKeywordKind = token();
      const text = internIdentifier(scanner.getTokenValue());
      const hasExtendedUnicodeEscape = scanner.hasExtendedUnicodeEscape();
      nextTokenWithoutCheck();
      return finishNode(factoryCreateIdentifier(text, originalKeywordKind, hasExtendedUnicodeEscape), pos);
    }
    if (token() === SyntaxKind.PrivateIdentifier) {
      parseErrorAtCurrentToken(privateIdentifierDiagnosticMessage || Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
      return createIdentifier(
        /*isIdentifier*/
        true
      );
    }
    if (token() === SyntaxKind.Unknown && scanner.tryScan(() => scanner.reScanInvalidIdentifier() === SyntaxKind.Identifier)) {
      return createIdentifier(
        /*isIdentifier*/
        true
      );
    }
    identifierCount++;
    const reportAtCurrentPosition = token() === SyntaxKind.EndOfFileToken;
    const isReservedWord = scanner.isReservedWord();
    const msgArg = scanner.getTokenText();
    const defaultMessage = isReservedWord ? Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here : Diagnostics.Identifier_expected;
    return createMissingNode(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg);
  }
  function parseBindingIdentifier(privateIdentifierDiagnosticMessage) {
    return createIdentifier(
      isBindingIdentifier(),
      /*diagnosticMessage*/
      void 0,
      privateIdentifierDiagnosticMessage
    );
  }
  function parseIdentifier(diagnosticMessage, privateIdentifierDiagnosticMessage) {
    return createIdentifier(isIdentifier(), diagnosticMessage, privateIdentifierDiagnosticMessage);
  }
  function parseIdentifierName(diagnosticMessage) {
    return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage);
  }
  function parseIdentifierNameErrorOnUnicodeEscapeSequence() {
    if (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape()) {
      parseErrorAtCurrentToken(Diagnostics.Unicode_escape_sequence_cannot_appear_here);
    }
    return createIdentifier(tokenIsIdentifierOrKeyword(token()));
  }
  function isLiteralPropertyName() {
    return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral;
  }
  function isImportAttributeName() {
    return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.StringLiteral;
  }
  function parsePropertyNameWorker(allowComputedPropertyNames) {
    if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
      const node = parseLiteralNode();
      node.text = internIdentifier(node.text);
      return node;
    }
    if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) {
      return parseComputedPropertyName();
    }
    if (token() === SyntaxKind.PrivateIdentifier) {
      return parsePrivateIdentifier();
    }
    return parseIdentifierName();
  }
  function parsePropertyName() {
    return parsePropertyNameWorker(
      /*allowComputedPropertyNames*/
      true
    );
  }
  function parseComputedPropertyName() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.OpenBracketToken);
    const expression = allowInAnd(parseExpression);
    parseExpected(SyntaxKind.CloseBracketToken);
    return finishNode(factory.createComputedPropertyName(expression), pos);
  }
  function parsePrivateIdentifier() {
    const pos = getNodePos();
    const node = factoryCreatePrivateIdentifier(internIdentifier(scanner.getTokenValue()));
    nextToken();
    return finishNode(node, pos);
  }
  function parseContextualModifier(t) {
    return token() === t && tryParse(nextTokenCanFollowModifier);
  }
  function nextTokenIsOnSameLineAndCanFollowModifier() {
    nextToken();
    if (scanner.hasPrecedingLineBreak()) {
      return false;
    }
    return canFollowModifier();
  }
  function nextTokenCanFollowModifier() {
    switch (token()) {
      case SyntaxKind.ConstKeyword:
        return nextToken() === SyntaxKind.EnumKeyword;
      case SyntaxKind.ExportKeyword:
        nextToken();
        if (token() === SyntaxKind.DefaultKeyword) {
          return lookAhead(nextTokenCanFollowDefaultKeyword);
        }
        if (token() === SyntaxKind.TypeKeyword) {
          return lookAhead(nextTokenCanFollowExportModifier);
        }
        return canFollowExportModifier();
      case SyntaxKind.DefaultKeyword:
        return nextTokenCanFollowDefaultKeyword();
      case SyntaxKind.StaticKeyword:
      case SyntaxKind.GetKeyword:
      case SyntaxKind.SetKeyword:
        nextToken();
        return canFollowModifier();
      default:
        return nextTokenIsOnSameLineAndCanFollowModifier();
    }
  }
  function canFollowExportModifier() {
    return token() === SyntaxKind.AtToken || token() !== SyntaxKind.AsteriskToken && token() !== SyntaxKind.AsKeyword && token() !== SyntaxKind.OpenBraceToken && canFollowModifier();
  }
  function nextTokenCanFollowExportModifier() {
    nextToken();
    return canFollowExportModifier();
  }
  function parseAnyContextualModifier() {
    return isModifierKind(token()) && tryParse(nextTokenCanFollowModifier);
  }
  function canFollowModifier() {
    return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
  }
  function nextTokenCanFollowDefaultKeyword() {
    nextToken();
    return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword || token() === SyntaxKind.InterfaceKeyword || token() === SyntaxKind.AtToken || token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine) || token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine);
  }
  function isListElement(parsingContext2, inErrorRecovery) {
    const node = currentNode(parsingContext2);
    if (node) {
      return true;
    }
    switch (parsingContext2) {
      case 0 /* SourceElements */:
      case 1 /* BlockStatements */:
      case 3 /* SwitchClauseStatements */:
        return !(token() === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement();
      case 2 /* SwitchClauses */:
        return token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
      case 4 /* TypeMembers */:
        return lookAhead(isTypeMemberStart);
      case 5 /* ClassMembers */:
        return lookAhead(isClassMemberStart) || token() === SyntaxKind.SemicolonToken && !inErrorRecovery;
      case 6 /* EnumMembers */:
        return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
      case 12 /* ObjectLiteralMembers */:
        switch (token()) {
          case SyntaxKind.OpenBracketToken:
          case SyntaxKind.AsteriskToken:
          case SyntaxKind.DotDotDotToken:
          case SyntaxKind.DotToken:
            return true;
          default:
            return isLiteralPropertyName();
        }
      case 18 /* RestProperties */:
        return isLiteralPropertyName();
      case 9 /* ObjectBindingElements */:
        return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
      case 24 /* ImportAttributes */:
        return isImportAttributeName();
      case 7 /* HeritageClauseElement */:
        if (token() === SyntaxKind.OpenBraceToken) {
          return lookAhead(isValidHeritageClauseObjectLiteral);
        }
        if (!inErrorRecovery) {
          return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
        } else {
          return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
        }
      case 8 /* VariableDeclarations */:
        return isBindingIdentifierOrPrivateIdentifierOrPattern();
      case 10 /* ArrayBindingElements */:
        return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern();
      case 19 /* TypeParameters */:
        return token() === SyntaxKind.InKeyword || token() === SyntaxKind.ConstKeyword || isIdentifier();
      case 15 /* ArrayLiteralMembers */:
        switch (token()) {
          case SyntaxKind.CommaToken:
          case SyntaxKind.DotToken:
            return true;
        }
      // falls through
      case 11 /* ArgumentExpressions */:
        return token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
      case 16 /* Parameters */:
        return isStartOfParameter(
          /*isJSDocParameter*/
          false
        );
      case 17 /* JSDocParameters */:
        return isStartOfParameter(
          /*isJSDocParameter*/
          true
        );
      case 20 /* TypeArguments */:
      case 21 /* TupleElementTypes */:
        return token() === SyntaxKind.CommaToken || isStartOfType();
      case 22 /* HeritageClauses */:
        return isHeritageClause();
      case 23 /* ImportOrExportSpecifiers */:
        if (token() === SyntaxKind.FromKeyword && lookAhead(nextTokenIsStringLiteral)) {
          return false;
        }
        return tokenIsIdentifierOrKeyword(token());
      case 13 /* JsxAttributes */:
        return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken;
      case 14 /* JsxChildren */:
        return true;
      case 25 /* JSDocComment */:
        return true;
      case 26 /* Count */:
        return Debug.fail("ParsingContext.Count used as a context");
      // Not a real context, only a marker.
      default:
        Debug.assertNever(parsingContext2, "Non-exhaustive case in 'isListElement'.");
    }
  }
  function isValidHeritageClauseObjectLiteral() {
    Debug.assert(token() === SyntaxKind.OpenBraceToken);
    if (nextToken() === SyntaxKind.CloseBraceToken) {
      const next = nextToken();
      return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword;
    }
    return true;
  }
  function nextTokenIsIdentifier() {
    nextToken();
    return isIdentifier();
  }
  function nextTokenIsIdentifierOrKeyword() {
    nextToken();
    return tokenIsIdentifierOrKeyword(token());
  }
  function nextTokenIsIdentifierOrKeywordOrGreaterThan() {
    nextToken();
    return tokenIsIdentifierOrKeywordOrGreaterThan(token());
  }
  function isHeritageClauseExtendsOrImplementsKeyword() {
    if (token() === SyntaxKind.ImplementsKeyword || token() === SyntaxKind.ExtendsKeyword) {
      return lookAhead(nextTokenIsStartOfExpression);
    }
    return false;
  }
  function nextTokenIsStartOfExpression() {
    nextToken();
    return isStartOfExpression();
  }
  function nextTokenIsStartOfType() {
    nextToken();
    return isStartOfType();
  }
  function isListTerminator(kind) {
    if (token() === SyntaxKind.EndOfFileToken) {
      return true;
    }
    switch (kind) {
      case 1 /* BlockStatements */:
      case 2 /* SwitchClauses */:
      case 4 /* TypeMembers */:
      case 5 /* ClassMembers */:
      case 6 /* EnumMembers */:
      case 12 /* ObjectLiteralMembers */:
      case 9 /* ObjectBindingElements */:
      case 23 /* ImportOrExportSpecifiers */:
      case 24 /* ImportAttributes */:
        return token() === SyntaxKind.CloseBraceToken;
      case 3 /* SwitchClauseStatements */:
        return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
      case 7 /* HeritageClauseElement */:
        return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
      case 8 /* VariableDeclarations */:
        return isVariableDeclaratorListTerminator();
      case 19 /* TypeParameters */:
        return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
      case 11 /* ArgumentExpressions */:
        return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken;
      case 15 /* ArrayLiteralMembers */:
      case 21 /* TupleElementTypes */:
      case 10 /* ArrayBindingElements */:
        return token() === SyntaxKind.CloseBracketToken;
      case 17 /* JSDocParameters */:
      case 16 /* Parameters */:
      case 18 /* RestProperties */:
        return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken;
      case 20 /* TypeArguments */:
        return token() !== SyntaxKind.CommaToken;
      case 22 /* HeritageClauses */:
        return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.CloseBraceToken;
      case 13 /* JsxAttributes */:
        return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken;
      case 14 /* JsxChildren */:
        return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash);
      default:
        return false;
    }
  }
  function isVariableDeclaratorListTerminator() {
    if (canParseSemicolon()) {
      return true;
    }
    if (isInOrOfKeyword(token())) {
      return true;
    }
    if (token() === SyntaxKind.EqualsGreaterThanToken) {
      return true;
    }
    return false;
  }
  function isInSomeParsingContext() {
    Debug.assert(parsingContext, "Missing parsing context");
    for (let kind = 0; kind < 26 /* Count */; kind++) {
      if (parsingContext & 1 << kind) {
        if (isListElement(
          kind,
          /*inErrorRecovery*/
          true
        ) || isListTerminator(kind)) {
          return true;
        }
      }
    }
    return false;
  }
  function parseList(kind, parseElement) {
    const saveParsingContext = parsingContext;
    parsingContext |= 1 << kind;
    const list = [];
    const listPos = getNodePos();
    while (!isListTerminator(kind)) {
      if (isListElement(
        kind,
        /*inErrorRecovery*/
        false
      )) {
        list.push(parseListElement(kind, parseElement));
        continue;
      }
      if (abortParsingListOrMoveToNextToken(kind)) {
        break;
      }
    }
    parsingContext = saveParsingContext;
    return createNodeArray(list, listPos);
  }
  function parseListElement(parsingContext2, parseElement) {
    const node = currentNode(parsingContext2);
    if (node) {
      return consumeNode(node);
    }
    return parseElement();
  }
  function currentNode(parsingContext2, pos) {
    if (!syntaxCursor || !isReusableParsingContext(parsingContext2) || parseErrorBeforeNextFinishedNode) {
      return void 0;
    }
    const node = syntaxCursor.currentNode(pos ?? scanner.getTokenFullStart());
    if (nodeIsMissing(node) || node.intersectsChange || containsParseError(node)) {
      return void 0;
    }
    const nodeContextFlags = node.flags & NodeFlags.ContextFlags;
    if (nodeContextFlags !== contextFlags) {
      return void 0;
    }
    if (!canReuseNode(node, parsingContext2)) {
      return void 0;
    }
    if (canHaveJSDoc(node) && node.jsDoc?.jsDocCache) {
      node.jsDoc.jsDocCache = void 0;
    }
    return node;
  }
  function consumeNode(node) {
    scanner.resetTokenState(node.end);
    nextToken();
    return node;
  }
  function isReusableParsingContext(parsingContext2) {
    switch (parsingContext2) {
      case 5 /* ClassMembers */:
      case 2 /* SwitchClauses */:
      case 0 /* SourceElements */:
      case 1 /* BlockStatements */:
      case 3 /* SwitchClauseStatements */:
      case 6 /* EnumMembers */:
      case 4 /* TypeMembers */:
      case 8 /* VariableDeclarations */:
      case 17 /* JSDocParameters */:
      case 16 /* Parameters */:
        return true;
    }
    return false;
  }
  function canReuseNode(node, parsingContext2) {
    switch (parsingContext2) {
      case 5 /* ClassMembers */:
        return isReusableClassMember(node);
      case 2 /* SwitchClauses */:
        return isReusableSwitchClause(node);
      case 0 /* SourceElements */:
      case 1 /* BlockStatements */:
      case 3 /* SwitchClauseStatements */:
        return isReusableStatement(node);
      case 6 /* EnumMembers */:
        return isReusableEnumMember(node);
      case 4 /* TypeMembers */:
        return isReusableTypeMember(node);
      case 8 /* VariableDeclarations */:
        return isReusableVariableDeclaration(node);
      case 17 /* JSDocParameters */:
      case 16 /* Parameters */:
        return isReusableParameter(node);
    }
    return false;
  }
  function isReusableClassMember(node) {
    if (node) {
      switch (node.kind) {
        case SyntaxKind.Constructor:
        case SyntaxKind.IndexSignature:
        case SyntaxKind.GetAccessor:
        case SyntaxKind.SetAccessor:
        case SyntaxKind.PropertyDeclaration:
        case SyntaxKind.SemicolonClassElement:
          return true;
        case SyntaxKind.MethodDeclaration:
          const methodDeclaration = node;
          const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier && methodDeclaration.name.escapedText === "constructor";
          return !nameIsConstructor;
      }
    }
    return false;
  }
  function isReusableSwitchClause(node) {
    if (node) {
      switch (node.kind) {
        case SyntaxKind.CaseClause:
        case SyntaxKind.DefaultClause:
          return true;
      }
    }
    return false;
  }
  function isReusableStatement(node) {
    if (node) {
      switch (node.kind) {
        case SyntaxKind.FunctionDeclaration:
        case SyntaxKind.VariableStatement:
        case SyntaxKind.Block:
        case SyntaxKind.IfStatement:
        case SyntaxKind.ExpressionStatement:
        case SyntaxKind.ThrowStatement:
        case SyntaxKind.ReturnStatement:
        case SyntaxKind.SwitchStatement:
        case SyntaxKind.BreakStatement:
        case SyntaxKind.ContinueStatement:
        case SyntaxKind.ForInStatement:
        case SyntaxKind.ForOfStatement:
        case SyntaxKind.ForStatement:
        case SyntaxKind.WhileStatement:
        case SyntaxKind.WithStatement:
        case SyntaxKind.EmptyStatement:
        case SyntaxKind.TryStatement:
        case SyntaxKind.LabeledStatement:
        case SyntaxKind.DoStatement:
        case SyntaxKind.DebuggerStatement:
        case SyntaxKind.ImportDeclaration:
        case SyntaxKind.ImportEqualsDeclaration:
        case SyntaxKind.ExportDeclaration:
        case SyntaxKind.ExportAssignment:
        case SyntaxKind.ModuleDeclaration:
        case SyntaxKind.ClassDeclaration:
        case SyntaxKind.InterfaceDeclaration:
        case SyntaxKind.EnumDeclaration:
        case SyntaxKind.TypeAliasDeclaration:
          return true;
      }
    }
    return false;
  }
  function isReusableEnumMember(node) {
    return node.kind === SyntaxKind.EnumMember;
  }
  function isReusableTypeMember(node) {
    if (node) {
      switch (node.kind) {
        case SyntaxKind.ConstructSignature:
        case SyntaxKind.MethodSignature:
        case SyntaxKind.IndexSignature:
        case SyntaxKind.PropertySignature:
        case SyntaxKind.CallSignature:
          return true;
      }
    }
    return false;
  }
  function isReusableVariableDeclaration(node) {
    if (node.kind !== SyntaxKind.VariableDeclaration) {
      return false;
    }
    const variableDeclarator = node;
    return variableDeclarator.initializer === void 0;
  }
  function isReusableParameter(node) {
    if (node.kind !== SyntaxKind.Parameter) {
      return false;
    }
    const parameter = node;
    return parameter.initializer === void 0;
  }
  function abortParsingListOrMoveToNextToken(kind) {
    parsingContextErrors(kind);
    if (isInSomeParsingContext()) {
      return true;
    }
    nextToken();
    return false;
  }
  function parsingContextErrors(context) {
    switch (context) {
      case 0 /* SourceElements */:
        return token() === SyntaxKind.DefaultKeyword ? parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ExportKeyword)) : parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected);
      case 1 /* BlockStatements */:
        return parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected);
      case 2 /* SwitchClauses */:
        return parseErrorAtCurrentToken(Diagnostics.case_or_default_expected);
      case 3 /* SwitchClauseStatements */:
        return parseErrorAtCurrentToken(Diagnostics.Statement_expected);
      case 18 /* RestProperties */:
      // fallthrough
      case 4 /* TypeMembers */:
        return parseErrorAtCurrentToken(Diagnostics.Property_or_signature_expected);
      case 5 /* ClassMembers */:
        return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected);
      case 6 /* EnumMembers */:
        return parseErrorAtCurrentToken(Diagnostics.Enum_member_expected);
      case 7 /* HeritageClauseElement */:
        return parseErrorAtCurrentToken(Diagnostics.Expression_expected);
      case 8 /* VariableDeclarations */:
        return isKeyword(token()) ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token())) : parseErrorAtCurrentToken(Diagnostics.Variable_declaration_expected);
      case 9 /* ObjectBindingElements */:
        return parseErrorAtCurrentToken(Diagnostics.Property_destructuring_pattern_expected);
      case 10 /* ArrayBindingElements */:
        return parseErrorAtCurrentToken(Diagnostics.Array_element_destructuring_pattern_expected);
      case 11 /* ArgumentExpressions */:
        return parseErrorAtCurrentToken(Diagnostics.Argument_expression_expected);
      case 12 /* ObjectLiteralMembers */:
        return parseErrorAtCurrentToken(Diagnostics.Property_assignment_expected);
      case 15 /* ArrayLiteralMembers */:
        return parseErrorAtCurrentToken(Diagnostics.Expression_or_comma_expected);
      case 17 /* JSDocParameters */:
        return parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
      case 16 /* Parameters */:
        return isKeyword(token()) ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_parameter_name, tokenToString(token())) : parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
      case 19 /* TypeParameters */:
        return parseErrorAtCurrentToken(Diagnostics.Type_parameter_declaration_expected);
      case 20 /* TypeArguments */:
        return parseErrorAtCurrentToken(Diagnostics.Type_argument_expected);
      case 21 /* TupleElementTypes */:
        return parseErrorAtCurrentToken(Diagnostics.Type_expected);
      case 22 /* HeritageClauses */:
        return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_expected);
      case 23 /* ImportOrExportSpecifiers */:
        if (token() === SyntaxKind.FromKeyword) {
          return parseErrorAtCurrentToken(Diagnostics._0_expected, "}");
        }
        return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
      case 13 /* JsxAttributes */:
        return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
      case 14 /* JsxChildren */:
        return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
      case 24 /* ImportAttributes */:
        return parseErrorAtCurrentToken(Diagnostics.Identifier_or_string_literal_expected);
      case 25 /* JSDocComment */:
        return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
      case 26 /* Count */:
        return Debug.fail("ParsingContext.Count used as a context");
      // Not a real context, only a marker.
      default:
        Debug.assertNever(context);
    }
  }
  function parseDelimitedList(kind, parseElement, considerSemicolonAsDelimiter) {
    const saveParsingContext = parsingContext;
    parsingContext |= 1 << kind;
    const list = [];
    const listPos = getNodePos();
    let commaStart = -1;
    while (true) {
      if (isListElement(
        kind,
        /*inErrorRecovery*/
        false
      )) {
        const startPos = scanner.getTokenFullStart();
        const result = parseListElement(kind, parseElement);
        if (!result) {
          parsingContext = saveParsingContext;
          return void 0;
        }
        list.push(result);
        commaStart = scanner.getTokenStart();
        if (parseOptional(SyntaxKind.CommaToken)) {
          continue;
        }
        commaStart = -1;
        if (isListTerminator(kind)) {
          break;
        }
        parseExpected(SyntaxKind.CommaToken, getExpectedCommaDiagnostic(kind));
        if (considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) {
          nextToken();
        }
        if (startPos === scanner.getTokenFullStart()) {
          nextToken();
        }
        continue;
      }
      if (isListTerminator(kind)) {
        break;
      }
      if (abortParsingListOrMoveToNextToken(kind)) {
        break;
      }
    }
    parsingContext = saveParsingContext;
    return createNodeArray(
      list,
      listPos,
      /*end*/
      void 0,
      commaStart >= 0
    );
  }
  function getExpectedCommaDiagnostic(kind) {
    return kind === 6 /* EnumMembers */ ? Diagnostics.An_enum_member_name_must_be_followed_by_a_or : void 0;
  }
  function createMissingList() {
    const list = createNodeArray([], getNodePos());
    list.isMissingList = true;
    return list;
  }
  function isMissingList(arr) {
    return !!arr.isMissingList;
  }
  function parseBracketedList(kind, parseElement, open, close) {
    if (parseExpected(open)) {
      const result = parseDelimitedList(kind, parseElement);
      parseExpected(close);
      return result;
    }
    return createMissingList();
  }
  function parseEntityName(allowReservedWords, diagnosticMessage) {
    const pos = getNodePos();
    let entity = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage);
    while (parseOptional(SyntaxKind.DotToken)) {
      if (token() === SyntaxKind.LessThanToken) {
        break;
      }
      entity = finishNode(
        factory.createQualifiedName(
          entity,
          parseRightSideOfDot(
            allowReservedWords,
            /*allowPrivateIdentifiers*/
            false,
            /*allowUnicodeEscapeSequenceInIdentifierName*/
            true
          )
        ),
        pos
      );
    }
    return entity;
  }
  function createQualifiedName(entity, name) {
    return finishNode(factory.createQualifiedName(entity, name), entity.pos);
  }
  function parseRightSideOfDot(allowIdentifierNames, allowPrivateIdentifiers, allowUnicodeEscapeSequenceInIdentifierName) {
    if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token())) {
      const matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
      if (matchesPattern) {
        return createMissingNode(
          SyntaxKind.Identifier,
          /*reportAtCurrentPosition*/
          true,
          Diagnostics.Identifier_expected
        );
      }
    }
    if (token() === SyntaxKind.PrivateIdentifier) {
      const node = parsePrivateIdentifier();
      return allowPrivateIdentifiers ? node : createMissingNode(
        SyntaxKind.Identifier,
        /*reportAtCurrentPosition*/
        true,
        Diagnostics.Identifier_expected
      );
    }
    if (allowIdentifierNames) {
      return allowUnicodeEscapeSequenceInIdentifierName ? parseIdentifierName() : parseIdentifierNameErrorOnUnicodeEscapeSequence();
    }
    return parseIdentifier();
  }
  function parseTemplateSpans(isTaggedTemplate) {
    const pos = getNodePos();
    const list = [];
    let node;
    do {
      node = parseTemplateSpan(isTaggedTemplate);
      list.push(node);
    } while (node.literal.kind === SyntaxKind.TemplateMiddle);
    return createNodeArray(list, pos);
  }
  function parseTemplateExpression(isTaggedTemplate) {
    const pos = getNodePos();
    return finishNode(
      factory.createTemplateExpression(
        parseTemplateHead(isTaggedTemplate),
        parseTemplateSpans(isTaggedTemplate)
      ),
      pos
    );
  }
  function parseTemplateType() {
    const pos = getNodePos();
    return finishNode(
      factory.createTemplateLiteralType(
        parseTemplateHead(
          /*isTaggedTemplate*/
          false
        ),
        parseTemplateTypeSpans()
      ),
      pos
    );
  }
  function parseTemplateTypeSpans() {
    const pos = getNodePos();
    const list = [];
    let node;
    do {
      node = parseTemplateTypeSpan();
      list.push(node);
    } while (node.literal.kind === SyntaxKind.TemplateMiddle);
    return createNodeArray(list, pos);
  }
  function parseTemplateTypeSpan() {
    const pos = getNodePos();
    return finishNode(
      factory.createTemplateLiteralTypeSpan(
        parseType(),
        parseLiteralOfTemplateSpan(
          /*isTaggedTemplate*/
          false
        )
      ),
      pos
    );
  }
  function parseLiteralOfTemplateSpan(isTaggedTemplate) {
    if (token() === SyntaxKind.CloseBraceToken) {
      reScanTemplateToken(isTaggedTemplate);
      return parseTemplateMiddleOrTemplateTail();
    } else {
      return parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken));
    }
  }
  function parseTemplateSpan(isTaggedTemplate) {
    const pos = getNodePos();
    return finishNode(
      factory.createTemplateSpan(
        allowInAnd(parseExpression),
        parseLiteralOfTemplateSpan(isTaggedTemplate)
      ),
      pos
    );
  }
  function parseLiteralNode() {
    return parseLiteralLikeNode(token());
  }
  function parseTemplateHead(isTaggedTemplate) {
    if (!isTaggedTemplate && scanner.getTokenFlags() & TokenFlags.IsInvalid) {
      reScanTemplateToken(
        /*isTaggedTemplate*/
        false
      );
    }
    const fragment = parseLiteralLikeNode(token());
    Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
    return fragment;
  }
  function parseTemplateMiddleOrTemplateTail() {
    const fragment = parseLiteralLikeNode(token());
    Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind");
    return fragment;
  }
  function getTemplateLiteralRawText(kind) {
    const isLast = kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.TemplateTail;
    const tokenText = scanner.getTokenText();
    return tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2));
  }
  function parseLiteralLikeNode(kind) {
    const pos = getNodePos();
    const node = isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags) : (
      // Note that theoretically the following condition would hold true literals like 009,
      // which is not octal. But because of how the scanner separates the tokens, we would
      // never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
      // We also do not need to check for negatives because any prefix operator would be part of a
      // parent unary expression.
      kind === SyntaxKind.NumericLiteral ? factoryCreateNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : kind === SyntaxKind.StringLiteral ? factoryCreateStringLiteral(
        scanner.getTokenValue(),
        /*isSingleQuote*/
        void 0,
        scanner.hasExtendedUnicodeEscape()
      ) : isLiteralKind(kind) ? factoryCreateLiteralLikeNode(kind, scanner.getTokenValue()) : Debug.fail()
    );
    if (scanner.hasExtendedUnicodeEscape()) {
      node.hasExtendedUnicodeEscape = true;
    }
    if (scanner.isUnterminated()) {
      node.isUnterminated = true;
    }
    nextToken();
    return finishNode(node, pos);
  }
  function parseEntityNameOfTypeReference() {
    return parseEntityName(
      /*allowReservedWords*/
      true,
      Diagnostics.Type_expected
    );
  }
  function parseTypeArgumentsOfTypeReference() {
    if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) {
      return parseBracketedList(20 /* TypeArguments */, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
    }
  }
  function parseTypeReference() {
    const pos = getNodePos();
    return finishNode(
      factory.createTypeReferenceNode(
        parseEntityNameOfTypeReference(),
        parseTypeArgumentsOfTypeReference()
      ),
      pos
    );
  }
  function typeHasArrowFunctionBlockingParseError(node) {
    switch (node.kind) {
      case SyntaxKind.TypeReference:
        return nodeIsMissing(node.typeName);
      case SyntaxKind.FunctionType:
      case SyntaxKind.ConstructorType: {
        const { parameters, type } = node;
        return isMissingList(parameters) || typeHasArrowFunctionBlockingParseError(type);
      }
      case SyntaxKind.ParenthesizedType:
        return typeHasArrowFunctionBlockingParseError(node.type);
      default:
        return false;
    }
  }
  function parseThisTypePredicate(lhs) {
    nextToken();
    return finishNode(factory.createTypePredicateNode(
      /*assertsModifier*/
      void 0,
      lhs,
      parseType()
    ), lhs.pos);
  }
  function parseThisTypeNode() {
    const pos = getNodePos();
    nextToken();
    return finishNode(factory.createThisTypeNode(), pos);
  }
  function parseJSDocAllType() {
    const pos = getNodePos();
    nextToken();
    return finishNode(factory.createJSDocAllType(), pos);
  }
  function parseJSDocNonNullableType() {
    const pos = getNodePos();
    nextToken();
    return finishNode(factory.createJSDocNonNullableType(
      parseNonArrayType(),
      /*postfix*/
      false
    ), pos);
  }
  function parseJSDocUnknownOrNullableType() {
    const pos = getNodePos();
    nextToken();
    if (token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.BarToken) {
      return finishNode(factory.createJSDocUnknownType(), pos);
    } else {
      return finishNode(factory.createJSDocNullableType(
        parseType(),
        /*postfix*/
        false
      ), pos);
    }
  }
  function parseJSDocFunctionType() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    if (lookAhead(nextTokenIsOpenParen)) {
      nextToken();
      const parameters = parseParameters(4 /* Type */ | 32 /* JSDoc */);
      const type = parseReturnType(
        SyntaxKind.ColonToken,
        /*isType*/
        false
      );
      return withJSDoc(finishNode(factory.createJSDocFunctionType(parameters, type), pos), hasJSDoc);
    }
    return finishNode(factory.createTypeReferenceNode(
      parseIdentifierName(),
      /*typeArguments*/
      void 0
    ), pos);
  }
  function parseJSDocParameter() {
    const pos = getNodePos();
    let name;
    if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) {
      name = parseIdentifierName();
      parseExpected(SyntaxKind.ColonToken);
    }
    return finishNode(
      factory.createParameterDeclaration(
        /*modifiers*/
        void 0,
        /*dotDotDotToken*/
        void 0,
        // TODO(rbuckton): JSDoc parameters don't have names (except `this`/`new`), should we manufacture an empty identifier?
        name,
        /*questionToken*/
        void 0,
        parseJSDocType(),
        /*initializer*/
        void 0
      ),
      pos
    );
  }
  function parseJSDocType() {
    scanner.setInJSDocType(true);
    const pos = getNodePos();
    if (parseOptional(SyntaxKind.ModuleKeyword)) {
      const moduleTag = factory.createJSDocNamepathType(
        /*type*/
        void 0
      );
      terminate:
        while (true) {
          switch (token()) {
            case SyntaxKind.CloseBraceToken:
            case SyntaxKind.EndOfFileToken:
            case SyntaxKind.CommaToken:
            case SyntaxKind.WhitespaceTrivia:
              break terminate;
            default:
              nextTokenJSDoc();
          }
        }
      scanner.setInJSDocType(false);
      return finishNode(moduleTag, pos);
    }
    const hasDotDotDot = parseOptional(SyntaxKind.DotDotDotToken);
    let type = parseTypeOrTypePredicate();
    scanner.setInJSDocType(false);
    if (hasDotDotDot) {
      type = finishNode(factory.createJSDocVariadicType(type), pos);
    }
    if (token() === SyntaxKind.EqualsToken) {
      nextToken();
      return finishNode(factory.createJSDocOptionalType(type), pos);
    }
    return type;
  }
  function parseTypeQuery() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.TypeOfKeyword);
    const entityName = parseEntityName(
      /*allowReservedWords*/
      true
    );
    const typeArguments = !scanner.hasPrecedingLineBreak() ? tryParseTypeArguments() : void 0;
    return finishNode(factory.createTypeQueryNode(entityName, typeArguments), pos);
  }
  function parseTypeParameter() {
    const pos = getNodePos();
    const modifiers = parseModifiers(
      /*allowDecorators*/
      false,
      /*permitConstAsModifier*/
      true
    );
    const name = parseIdentifier();
    let constraint;
    let expression;
    if (parseOptional(SyntaxKind.ExtendsKeyword)) {
      if (isStartOfType() || !isStartOfExpression()) {
        constraint = parseType();
      } else {
        expression = parseUnaryExpressionOrHigher();
      }
    }
    const defaultType = parseOptional(SyntaxKind.EqualsToken) ? parseType() : void 0;
    const node = factory.createTypeParameterDeclaration(modifiers, name, constraint, defaultType);
    node.expression = expression;
    return finishNode(node, pos);
  }
  function parseTypeParameters() {
    if (token() === SyntaxKind.LessThanToken) {
      return parseBracketedList(19 /* TypeParameters */, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
    }
  }
  function isStartOfParameter(isJSDocParameter) {
    return token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern() || isModifierKind(token()) || token() === SyntaxKind.AtToken || isStartOfType(
      /*inStartOfParameter*/
      !isJSDocParameter
    );
  }
  function parseNameOfParameter(modifiers) {
    const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_cannot_be_used_as_parameters);
    if (getFullWidth(name) === 0 && !some(modifiers) && isModifierKind(token())) {
      nextToken();
    }
    return name;
  }
  function isParameterNameStart() {
    return isBindingIdentifier() || token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken;
  }
  function parseParameter(inOuterAwaitContext) {
    return parseParameterWorker(inOuterAwaitContext);
  }
  function parseParameterForSpeculation(inOuterAwaitContext) {
    return parseParameterWorker(
      inOuterAwaitContext,
      /*allowAmbiguity*/
      false
    );
  }
  function parseParameterWorker(inOuterAwaitContext, allowAmbiguity = true) {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const modifiers = inOuterAwaitContext ? doInAwaitContext(() => parseModifiers(
      /*allowDecorators*/
      true
    )) : doOutsideOfAwaitContext(() => parseModifiers(
      /*allowDecorators*/
      true
    ));
    if (token() === SyntaxKind.ThisKeyword) {
      const node2 = factory.createParameterDeclaration(
        modifiers,
        /*dotDotDotToken*/
        void 0,
        createIdentifier(
          /*isIdentifier*/
          true
        ),
        /*questionToken*/
        void 0,
        parseTypeAnnotation(),
        /*initializer*/
        void 0
      );
      const modifier = firstOrUndefined(modifiers);
      if (modifier) {
        parseErrorAtRange(modifier, Diagnostics.Neither_decorators_nor_modifiers_may_be_applied_to_this_parameters);
      }
      return withJSDoc(finishNode(node2, pos), hasJSDoc);
    }
    const savedTopLevel = topLevel;
    topLevel = false;
    const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
    if (!allowAmbiguity && !isParameterNameStart()) {
      return void 0;
    }
    const node = withJSDoc(
      finishNode(
        factory.createParameterDeclaration(
          modifiers,
          dotDotDotToken,
          parseNameOfParameter(modifiers),
          parseOptionalToken(SyntaxKind.QuestionToken),
          parseTypeAnnotation(),
          parseInitializer()
        ),
        pos
      ),
      hasJSDoc
    );
    topLevel = savedTopLevel;
    return node;
  }
  function parseReturnType(returnToken, isType) {
    if (shouldParseReturnType(returnToken, isType)) {
      return allowConditionalTypesAnd(parseTypeOrTypePredicate);
    }
  }
  function shouldParseReturnType(returnToken, isType) {
    if (returnToken === SyntaxKind.EqualsGreaterThanToken) {
      parseExpected(returnToken);
      return true;
    } else if (parseOptional(SyntaxKind.ColonToken)) {
      return true;
    } else if (isType && token() === SyntaxKind.EqualsGreaterThanToken) {
      parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
      nextToken();
      return true;
    }
    return false;
  }
  function parseParametersWorker(flags, allowAmbiguity) {
    const savedYieldContext = inYieldContext();
    const savedAwaitContext = inAwaitContext();
    setYieldContext(!!(flags & 1 /* Yield */));
    setAwaitContext(!!(flags & 2 /* Await */));
    const parameters = flags & 32 /* JSDoc */ ? parseDelimitedList(17 /* JSDocParameters */, parseJSDocParameter) : parseDelimitedList(16 /* Parameters */, () => allowAmbiguity ? parseParameter(savedAwaitContext) : parseParameterForSpeculation(savedAwaitContext));
    setYieldContext(savedYieldContext);
    setAwaitContext(savedAwaitContext);
    return parameters;
  }
  function parseParameters(flags) {
    if (!parseExpected(SyntaxKind.OpenParenToken)) {
      return createMissingList();
    }
    const parameters = parseParametersWorker(
      flags,
      /*allowAmbiguity*/
      true
    );
    parseExpected(SyntaxKind.CloseParenToken);
    return parameters;
  }
  function parseTypeMemberSemicolon() {
    if (parseOptional(SyntaxKind.CommaToken)) {
      return;
    }
    parseSemicolon();
  }
  function parseSignatureMember(kind) {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    if (kind === SyntaxKind.ConstructSignature) {
      parseExpected(SyntaxKind.NewKeyword);
    }
    const typeParameters = parseTypeParameters();
    const parameters = parseParameters(4 /* Type */);
    const type = parseReturnType(
      SyntaxKind.ColonToken,
      /*isType*/
      true
    );
    parseTypeMemberSemicolon();
    const node = kind === SyntaxKind.CallSignature ? factory.createCallSignature(typeParameters, parameters, type) : factory.createConstructSignature(typeParameters, parameters, type);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function isIndexSignature() {
    return token() === SyntaxKind.OpenBracketToken && lookAhead(isUnambiguouslyIndexSignature);
  }
  function isUnambiguouslyIndexSignature() {
    nextToken();
    if (token() === SyntaxKind.DotDotDotToken || token() === SyntaxKind.CloseBracketToken) {
      return true;
    }
    if (isModifierKind(token())) {
      nextToken();
      if (isIdentifier()) {
        return true;
      }
    } else if (!isIdentifier()) {
      return false;
    } else {
      nextToken();
    }
    if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken) {
      return true;
    }
    if (token() !== SyntaxKind.QuestionToken) {
      return false;
    }
    nextToken();
    return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken;
  }
  function parseIndexSignatureDeclaration(pos, hasJSDoc, modifiers) {
    const parameters = parseBracketedList(16 /* Parameters */, () => parseParameter(
      /*inOuterAwaitContext*/
      false
    ), SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
    const type = parseTypeAnnotation();
    parseTypeMemberSemicolon();
    const node = factory.createIndexSignature(modifiers, parameters, type);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parsePropertyOrMethodSignature(pos, hasJSDoc, modifiers) {
    const name = parsePropertyName();
    const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
    let node;
    if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
      const typeParameters = parseTypeParameters();
      const parameters = parseParameters(4 /* Type */);
      const type = parseReturnType(
        SyntaxKind.ColonToken,
        /*isType*/
        true
      );
      node = factory.createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type);
    } else {
      const type = parseTypeAnnotation();
      node = factory.createPropertySignature(modifiers, name, questionToken, type);
      if (token() === SyntaxKind.EqualsToken) node.initializer = parseInitializer();
    }
    parseTypeMemberSemicolon();
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function isTypeMemberStart() {
    if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.GetKeyword || token() === SyntaxKind.SetKeyword) {
      return true;
    }
    let idToken = false;
    while (isModifierKind(token())) {
      idToken = true;
      nextToken();
    }
    if (token() === SyntaxKind.OpenBracketToken) {
      return true;
    }
    if (isLiteralPropertyName()) {
      idToken = true;
      nextToken();
    }
    if (idToken) {
      return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.QuestionToken || token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || canParseSemicolon();
    }
    return false;
  }
  function parseTypeMember() {
    if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
      return parseSignatureMember(SyntaxKind.CallSignature);
    }
    if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
      return parseSignatureMember(SyntaxKind.ConstructSignature);
    }
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const modifiers = parseModifiers(
      /*allowDecorators*/
      false
    );
    if (parseContextualModifier(SyntaxKind.GetKeyword)) {
      return parseAccessorDeclaration(pos, hasJSDoc, modifiers, SyntaxKind.GetAccessor, 4 /* Type */);
    }
    if (parseContextualModifier(SyntaxKind.SetKeyword)) {
      return parseAccessorDeclaration(pos, hasJSDoc, modifiers, SyntaxKind.SetAccessor, 4 /* Type */);
    }
    if (isIndexSignature()) {
      return parseIndexSignatureDeclaration(pos, hasJSDoc, modifiers);
    }
    return parsePropertyOrMethodSignature(pos, hasJSDoc, modifiers);
  }
  function nextTokenIsOpenParenOrLessThan() {
    nextToken();
    return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
  }
  function nextTokenIsDot() {
    return nextToken() === SyntaxKind.DotToken;
  }
  function nextTokenIsOpenParenOrLessThanOrDot() {
    switch (nextToken()) {
      case SyntaxKind.OpenParenToken:
      case SyntaxKind.LessThanToken:
      case SyntaxKind.DotToken:
        return true;
    }
    return false;
  }
  function parseTypeLiteral() {
    const pos = getNodePos();
    return finishNode(factory.createTypeLiteralNode(parseObjectTypeMembers()), pos);
  }
  function parseObjectTypeMembers() {
    let members;
    if (parseExpected(SyntaxKind.OpenBraceToken)) {
      members = parseList(4 /* TypeMembers */, parseTypeMember);
      parseExpected(SyntaxKind.CloseBraceToken);
    } else {
      members = createMissingList();
    }
    return members;
  }
  function isStartOfMappedType() {
    nextToken();
    if (token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
      return nextToken() === SyntaxKind.ReadonlyKeyword;
    }
    if (token() === SyntaxKind.ReadonlyKeyword) {
      nextToken();
    }
    return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === SyntaxKind.InKeyword;
  }
  function parseMappedTypeParameter() {
    const pos = getNodePos();
    const name = parseIdentifierName();
    parseExpected(SyntaxKind.InKeyword);
    const type = parseType();
    return finishNode(factory.createTypeParameterDeclaration(
      /*modifiers*/
      void 0,
      name,
      type,
      /*defaultType*/
      void 0
    ), pos);
  }
  function parseMappedType() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.OpenBraceToken);
    let readonlyToken;
    if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
      readonlyToken = parseTokenNode();
      if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) {
        parseExpected(SyntaxKind.ReadonlyKeyword);
      }
    }
    parseExpected(SyntaxKind.OpenBracketToken);
    const typeParameter = parseMappedTypeParameter();
    const nameType = parseOptional(SyntaxKind.AsKeyword) ? parseType() : void 0;
    parseExpected(SyntaxKind.CloseBracketToken);
    let questionToken;
    if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
      questionToken = parseTokenNode();
      if (questionToken.kind !== SyntaxKind.QuestionToken) {
        parseExpected(SyntaxKind.QuestionToken);
      }
    }
    const type = parseTypeAnnotation();
    parseSemicolon();
    const members = parseList(4 /* TypeMembers */, parseTypeMember);
    parseExpected(SyntaxKind.CloseBraceToken);
    return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type, members), pos);
  }
  function parseTupleElementType() {
    const pos = getNodePos();
    if (parseOptional(SyntaxKind.DotDotDotToken)) {
      return finishNode(factory.createRestTypeNode(parseType()), pos);
    }
    const type = parseType();
    if (isJSDocNullableType(type) && type.pos === type.type.pos) {
      const node = factory.createOptionalTypeNode(type.type);
      setTextRange(node, type);
      node.flags = type.flags;
      return node;
    }
    return type;
  }
  function isNextTokenColonOrQuestionColon() {
    return nextToken() === SyntaxKind.ColonToken || token() === SyntaxKind.QuestionToken && nextToken() === SyntaxKind.ColonToken;
  }
  function isTupleElementName() {
    if (token() === SyntaxKind.DotDotDotToken) {
      return tokenIsIdentifierOrKeyword(nextToken()) && isNextTokenColonOrQuestionColon();
    }
    return tokenIsIdentifierOrKeyword(token()) && isNextTokenColonOrQuestionColon();
  }
  function parseTupleElementNameOrTupleElementType() {
    if (lookAhead(isTupleElementName)) {
      const pos = getNodePos();
      const hasJSDoc = hasPrecedingJSDocComment();
      const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
      const name = parseIdentifierName();
      const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
      parseExpected(SyntaxKind.ColonToken);
      const type = parseTupleElementType();
      const node = factory.createNamedTupleMember(dotDotDotToken, name, questionToken, type);
      return withJSDoc(finishNode(node, pos), hasJSDoc);
    }
    return parseTupleElementType();
  }
  function parseTupleType() {
    const pos = getNodePos();
    return finishNode(
      factory.createTupleTypeNode(
        parseBracketedList(21 /* TupleElementTypes */, parseTupleElementNameOrTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken)
      ),
      pos
    );
  }
  function parseParenthesizedType() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.OpenParenToken);
    const type = parseType();
    parseExpected(SyntaxKind.CloseParenToken);
    return finishNode(factory.createParenthesizedType(type), pos);
  }
  function parseModifiersForConstructorType() {
    let modifiers;
    if (token() === SyntaxKind.AbstractKeyword) {
      const pos = getNodePos();
      nextToken();
      const modifier = finishNode(factoryCreateToken(SyntaxKind.AbstractKeyword), pos);
      modifiers = createNodeArray([modifier], pos);
    }
    return modifiers;
  }
  function parseFunctionOrConstructorType() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const modifiers = parseModifiersForConstructorType();
    const isConstructorType = parseOptional(SyntaxKind.NewKeyword);
    Debug.assert(!modifiers || isConstructorType, "Per isStartOfFunctionOrConstructorType, a function type cannot have modifiers.");
    const typeParameters = parseTypeParameters();
    const parameters = parseParameters(4 /* Type */);
    const type = parseReturnType(
      SyntaxKind.EqualsGreaterThanToken,
      /*isType*/
      false
    );
    const node = isConstructorType ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, type) : factory.createFunctionTypeNode(typeParameters, parameters, type);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseKeywordAndNoDot() {
    const node = parseTokenNode();
    return token() === SyntaxKind.DotToken ? void 0 : node;
  }
  function parseLiteralTypeNode(negative) {
    const pos = getNodePos();
    if (negative) {
      nextToken();
    }
    let expression = token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ? parseTokenNode() : parseLiteralLikeNode(token());
    if (negative) {
      expression = finishNode(factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, expression), pos);
    }
    return finishNode(factory.createLiteralTypeNode(expression), pos);
  }
  function isStartOfTypeOfImportType() {
    nextToken();
    return token() === SyntaxKind.ImportKeyword;
  }
  function parseImportType() {
    sourceFlags |= NodeFlags.PossiblyContainsDynamicImport;
    const pos = getNodePos();
    const isTypeOf = parseOptional(SyntaxKind.TypeOfKeyword);
    parseExpected(SyntaxKind.ImportKeyword);
    parseExpected(SyntaxKind.OpenParenToken);
    const type = parseType();
    let attributes;
    if (parseOptional(SyntaxKind.CommaToken)) {
      const openBracePosition = scanner.getTokenStart();
      parseExpected(SyntaxKind.OpenBraceToken);
      const currentToken2 = token();
      if (currentToken2 === SyntaxKind.WithKeyword || currentToken2 === SyntaxKind.AssertKeyword) {
        nextToken();
      } else {
        parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.WithKeyword));
      }
      parseExpected(SyntaxKind.ColonToken);
      attributes = parseImportAttributes(
        currentToken2,
        /*skipKeyword*/
        true
      );
      if (!parseExpected(SyntaxKind.CloseBraceToken)) {
        const lastError = lastOrUndefined(parseDiagnostics);
        if (lastError && lastError.code === Diagnostics._0_expected.code) {
          addRelatedInfo(
            lastError,
            createDetachedDiagnostic(fileName, sourceText, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}")
          );
        }
      }
    }
    parseExpected(SyntaxKind.CloseParenToken);
    const qualifier = parseOptional(SyntaxKind.DotToken) ? parseEntityNameOfTypeReference() : void 0;
    const typeArguments = parseTypeArgumentsOfTypeReference();
    return finishNode(factory.createImportTypeNode(type, attributes, qualifier, typeArguments, isTypeOf), pos);
  }
  function nextTokenIsNumericOrBigIntLiteral() {
    nextToken();
    return token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral;
  }
  function parseNonArrayType() {
    switch (token()) {
      case SyntaxKind.AnyKeyword:
      case SyntaxKind.UnknownKeyword:
      case SyntaxKind.StringKeyword:
      case SyntaxKind.NumberKeyword:
      case SyntaxKind.BigIntKeyword:
      case SyntaxKind.SymbolKeyword:
      case SyntaxKind.BooleanKeyword:
      case SyntaxKind.UndefinedKeyword:
      case SyntaxKind.NeverKeyword:
      case SyntaxKind.ObjectKeyword:
        return tryParse(parseKeywordAndNoDot) || parseTypeReference();
      case SyntaxKind.AsteriskEqualsToken:
        scanner.reScanAsteriskEqualsToken();
      // falls through
      case SyntaxKind.AsteriskToken:
        return parseJSDocAllType();
      case SyntaxKind.QuestionQuestionToken:
        scanner.reScanQuestionToken();
      // falls through
      case SyntaxKind.QuestionToken:
        return parseJSDocUnknownOrNullableType();
      case SyntaxKind.FunctionKeyword:
        return parseJSDocFunctionType();
      case SyntaxKind.ExclamationToken:
        return parseJSDocNonNullableType();
      case SyntaxKind.NoSubstitutionTemplateLiteral:
      case SyntaxKind.StringLiteral:
      case SyntaxKind.NumericLiteral:
      case SyntaxKind.BigIntLiteral:
      case SyntaxKind.TrueKeyword:
      case SyntaxKind.FalseKeyword:
      case SyntaxKind.NullKeyword:
        return parseLiteralTypeNode();
      case SyntaxKind.MinusToken:
        return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(
          /*negative*/
          true
        ) : parseTypeReference();
      case SyntaxKind.VoidKeyword:
        return parseTokenNode();
      case SyntaxKind.ThisKeyword: {
        const thisKeyword = parseThisTypeNode();
        if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
          return parseThisTypePredicate(thisKeyword);
        } else {
          return thisKeyword;
        }
      }
      case SyntaxKind.TypeOfKeyword:
        return lookAhead(isStartOfTypeOfImportType) ? parseImportType() : parseTypeQuery();
      case SyntaxKind.OpenBraceToken:
        return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral();
      case SyntaxKind.OpenBracketToken:
        return parseTupleType();
      case SyntaxKind.OpenParenToken:
        return parseParenthesizedType();
      case SyntaxKind.ImportKeyword:
        return parseImportType();
      case SyntaxKind.AssertsKeyword:
        return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() : parseTypeReference();
      case SyntaxKind.TemplateHead:
        return parseTemplateType();
      default:
        return parseTypeReference();
    }
  }
  function isStartOfType(inStartOfParameter) {
    switch (token()) {
      case SyntaxKind.AnyKeyword:
      case SyntaxKind.UnknownKeyword:
      case SyntaxKind.StringKeyword:
      case SyntaxKind.NumberKeyword:
      case SyntaxKind.BigIntKeyword:
      case SyntaxKind.BooleanKeyword:
      case SyntaxKind.ReadonlyKeyword:
      case SyntaxKind.SymbolKeyword:
      case SyntaxKind.UniqueKeyword:
      case SyntaxKind.VoidKeyword:
      case SyntaxKind.UndefinedKeyword:
      case SyntaxKind.NullKeyword:
      case SyntaxKind.ThisKeyword:
      case SyntaxKind.TypeOfKeyword:
      case SyntaxKind.NeverKeyword:
      case SyntaxKind.OpenBraceToken:
      case SyntaxKind.OpenBracketToken:
      case SyntaxKind.LessThanToken:
      case SyntaxKind.BarToken:
      case SyntaxKind.AmpersandToken:
      case SyntaxKind.NewKeyword:
      case SyntaxKind.StringLiteral:
      case SyntaxKind.NumericLiteral:
      case SyntaxKind.BigIntLiteral:
      case SyntaxKind.TrueKeyword:
      case SyntaxKind.FalseKeyword:
      case SyntaxKind.ObjectKeyword:
      case SyntaxKind.AsteriskToken:
      case SyntaxKind.QuestionToken:
      case SyntaxKind.ExclamationToken:
      case SyntaxKind.DotDotDotToken:
      case SyntaxKind.InferKeyword:
      case SyntaxKind.ImportKeyword:
      case SyntaxKind.AssertsKeyword:
      case SyntaxKind.NoSubstitutionTemplateLiteral:
      case SyntaxKind.TemplateHead:
        return true;
      case SyntaxKind.FunctionKeyword:
        return !inStartOfParameter;
      case SyntaxKind.MinusToken:
        return !inStartOfParameter && lookAhead(nextTokenIsNumericOrBigIntLiteral);
      case SyntaxKind.OpenParenToken:
        return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
      default:
        return isIdentifier();
    }
  }
  function isStartOfParenthesizedOrFunctionType() {
    nextToken();
    return token() === SyntaxKind.CloseParenToken || isStartOfParameter(
      /*isJSDocParameter*/
      false
    ) || isStartOfType();
  }
  function parsePostfixTypeOrHigher() {
    const pos = getNodePos();
    let type = parseNonArrayType();
    while (!scanner.hasPrecedingLineBreak()) {
      switch (token()) {
        case SyntaxKind.ExclamationToken:
          nextToken();
          type = finishNode(factory.createJSDocNonNullableType(
            type,
            /*postfix*/
            true
          ), pos);
          break;
        case SyntaxKind.QuestionToken:
          if (lookAhead(nextTokenIsStartOfType)) {
            return type;
          }
          nextToken();
          type = finishNode(factory.createJSDocNullableType(
            type,
            /*postfix*/
            true
          ), pos);
          break;
        case SyntaxKind.OpenBracketToken:
          parseExpected(SyntaxKind.OpenBracketToken);
          if (isStartOfType()) {
            const indexType = parseType();
            parseExpected(SyntaxKind.CloseBracketToken);
            type = finishNode(factory.createIndexedAccessTypeNode(type, indexType), pos);
          } else {
            parseExpected(SyntaxKind.CloseBracketToken);
            type = finishNode(factory.createArrayTypeNode(type), pos);
          }
          break;
        default:
          return type;
      }
    }
    return type;
  }
  function parseTypeOperator(operator) {
    const pos = getNodePos();
    parseExpected(operator);
    return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos);
  }
  function tryParseConstraintOfInferType() {
    if (parseOptional(SyntaxKind.ExtendsKeyword)) {
      const constraint = disallowConditionalTypesAnd(parseType);
      if (inDisallowConditionalTypesContext() || token() !== SyntaxKind.QuestionToken) {
        return constraint;
      }
    }
  }
  function parseTypeParameterOfInferType() {
    const pos = getNodePos();
    const name = parseIdentifier();
    const constraint = tryParse(tryParseConstraintOfInferType);
    const node = factory.createTypeParameterDeclaration(
      /*modifiers*/
      void 0,
      name,
      constraint
    );
    return finishNode(node, pos);
  }
  function parseInferType() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.InferKeyword);
    return finishNode(factory.createInferTypeNode(parseTypeParameterOfInferType()), pos);
  }
  function parseTypeOperatorOrHigher() {
    const operator = token();
    switch (operator) {
      case SyntaxKind.KeyOfKeyword:
      case SyntaxKind.UniqueKeyword:
      case SyntaxKind.ReadonlyKeyword:
        return parseTypeOperator(operator);
      case SyntaxKind.InferKeyword:
        return parseInferType();
    }
    return allowConditionalTypesAnd(parsePostfixTypeOrHigher);
  }
  function parseFunctionOrConstructorTypeToError(isInUnionType) {
    if (isStartOfFunctionTypeOrConstructorType()) {
      const type = parseFunctionOrConstructorType();
      let diagnostic;
      if (isFunctionTypeNode(type)) {
        diagnostic = isInUnionType ? Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_a_union_type : Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
      } else {
        diagnostic = isInUnionType ? Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_a_union_type : Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
      }
      parseErrorAtRange(type, diagnostic);
      return type;
    }
    return void 0;
  }
  function parseUnionOrIntersectionType(operator, parseConstituentType, createTypeNode) {
    const pos = getNodePos();
    const isUnionType = operator === SyntaxKind.BarToken;
    const hasLeadingOperator = parseOptional(operator);
    let type = hasLeadingOperator && parseFunctionOrConstructorTypeToError(isUnionType) || parseConstituentType();
    if (token() === operator || hasLeadingOperator) {
      const types = [type];
      while (parseOptional(operator)) {
        types.push(parseFunctionOrConstructorTypeToError(isUnionType) || parseConstituentType());
      }
      type = finishNode(createTypeNode(createNodeArray(types, pos)), pos);
    }
    return type;
  }
  function parseIntersectionTypeOrHigher() {
    return parseUnionOrIntersectionType(SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode);
  }
  function parseUnionTypeOrHigher() {
    return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode);
  }
  function nextTokenIsNewKeyword() {
    nextToken();
    return token() === SyntaxKind.NewKeyword;
  }
  function isStartOfFunctionTypeOrConstructorType() {
    if (token() === SyntaxKind.LessThanToken) {
      return true;
    }
    if (token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) {
      return true;
    }
    return token() === SyntaxKind.NewKeyword || token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword);
  }
  function skipParameterStart() {
    if (isModifierKind(token())) {
      parseModifiers(
        /*allowDecorators*/
        false
      );
    }
    if (isIdentifier() || token() === SyntaxKind.ThisKeyword) {
      nextToken();
      return true;
    }
    if (token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken) {
      const previousErrorCount = parseDiagnostics.length;
      parseIdentifierOrPattern();
      return previousErrorCount === parseDiagnostics.length;
    }
    return false;
  }
  function isUnambiguouslyStartOfFunctionType() {
    nextToken();
    if (token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.DotDotDotToken) {
      return true;
    }
    if (skipParameterStart()) {
      if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.QuestionToken || token() === SyntaxKind.EqualsToken) {
        return true;
      }
      if (token() === SyntaxKind.CloseParenToken) {
        nextToken();
        if (token() === SyntaxKind.EqualsGreaterThanToken) {
          return true;
        }
      }
    }
    return false;
  }
  function parseTypeOrTypePredicate() {
    const pos = getNodePos();
    const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix);
    const type = parseType();
    if (typePredicateVariable) {
      return finishNode(factory.createTypePredicateNode(
        /*assertsModifier*/
        void 0,
        typePredicateVariable,
        type
      ), pos);
    } else {
      return type;
    }
  }
  function parseTypePredicatePrefix() {
    const id = parseIdentifier();
    if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
      nextToken();
      return id;
    }
  }
  function parseAssertsTypePredicate() {
    const pos = getNodePos();
    const assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword);
    const parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier();
    const type = parseOptional(SyntaxKind.IsKeyword) ? parseType() : void 0;
    return finishNode(factory.createTypePredicateNode(assertsModifier, parameterName, type), pos);
  }
  function parseType() {
    if (contextFlags & NodeFlags.TypeExcludesFlags) {
      return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseType);
    }
    if (isStartOfFunctionTypeOrConstructorType()) {
      return parseFunctionOrConstructorType();
    }
    const pos = getNodePos();
    const type = parseUnionTypeOrHigher();
    if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
      const extendsType = disallowConditionalTypesAnd(parseType);
      parseExpected(SyntaxKind.QuestionToken);
      const trueType = allowConditionalTypesAnd(parseType);
      parseExpected(SyntaxKind.ColonToken);
      const falseType = allowConditionalTypesAnd(parseType);
      return finishNode(factory.createConditionalTypeNode(type, extendsType, trueType, falseType), pos);
    }
    return type;
  }
  function parseTypeAnnotation() {
    return parseOptional(SyntaxKind.ColonToken) ? parseType() : void 0;
  }
  function isStartOfLeftHandSideExpression() {
    switch (token()) {
      case SyntaxKind.ThisKeyword:
      case SyntaxKind.SuperKeyword:
      case SyntaxKind.NullKeyword:
      case SyntaxKind.TrueKeyword:
      case SyntaxKind.FalseKeyword:
      case SyntaxKind.NumericLiteral:
      case SyntaxKind.BigIntLiteral:
      case SyntaxKind.StringLiteral:
      case SyntaxKind.NoSubstitutionTemplateLiteral:
      case SyntaxKind.TemplateHead:
      case SyntaxKind.OpenParenToken:
      case SyntaxKind.OpenBracketToken:
      case SyntaxKind.OpenBraceToken:
      case SyntaxKind.FunctionKeyword:
      case SyntaxKind.ClassKeyword:
      case SyntaxKind.NewKeyword:
      case SyntaxKind.SlashToken:
      case SyntaxKind.SlashEqualsToken:
      case SyntaxKind.Identifier:
        return true;
      case SyntaxKind.ImportKeyword:
        return lookAhead(nextTokenIsOpenParenOrLessThanOrDot);
      default:
        return isIdentifier();
    }
  }
  function isStartOfExpression() {
    if (isStartOfLeftHandSideExpression()) {
      return true;
    }
    switch (token()) {
      case SyntaxKind.PlusToken:
      case SyntaxKind.MinusToken:
      case SyntaxKind.TildeToken:
      case SyntaxKind.ExclamationToken:
      case SyntaxKind.DeleteKeyword:
      case SyntaxKind.TypeOfKeyword:
      case SyntaxKind.VoidKeyword:
      case SyntaxKind.PlusPlusToken:
      case SyntaxKind.MinusMinusToken:
      case SyntaxKind.LessThanToken:
      case SyntaxKind.AwaitKeyword:
      case SyntaxKind.YieldKeyword:
      case SyntaxKind.PrivateIdentifier:
      case SyntaxKind.AtToken:
        return true;
      default:
        if (isBinaryOperator()) {
          return true;
        }
        return isIdentifier();
    }
  }
  function isStartOfExpressionStatement() {
    return token() !== SyntaxKind.OpenBraceToken && token() !== SyntaxKind.FunctionKeyword && token() !== SyntaxKind.ClassKeyword && token() !== SyntaxKind.AtToken && isStartOfExpression();
  }
  function parseExpression() {
    const saveDecoratorContext = inDecoratorContext();
    if (saveDecoratorContext) {
      setDecoratorContext(
        /*val*/
        false
      );
    }
    const pos = getNodePos();
    let expr = parseAssignmentExpressionOrHigher(
      /*allowReturnTypeInArrowFunction*/
      true
    );
    let operatorToken;
    while (operatorToken = parseOptionalToken(SyntaxKind.CommaToken)) {
      expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher(
        /*allowReturnTypeInArrowFunction*/
        true
      ), pos);
    }
    if (saveDecoratorContext) {
      setDecoratorContext(
        /*val*/
        true
      );
    }
    return expr;
  }
  function parseInitializer() {
    return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher(
      /*allowReturnTypeInArrowFunction*/
      true
    ) : void 0;
  }
  function parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction) {
    if (isYieldExpression()) {
      return parseYieldExpression();
    }
    const arrowExpression = tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) || tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction);
    if (arrowExpression) {
      return arrowExpression;
    }
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
    if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
      return parseSimpleArrowFunctionExpression(
        pos,
        expr,
        allowReturnTypeInArrowFunction,
        hasJSDoc,
        /*asyncModifier*/
        void 0
      );
    }
    if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
      return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction), pos);
    }
    return parseConditionalExpressionRest(expr, pos, allowReturnTypeInArrowFunction);
  }
  function isYieldExpression() {
    if (token() === SyntaxKind.YieldKeyword) {
      if (inYieldContext()) {
        return true;
      }
      return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
    }
    return false;
  }
  function nextTokenIsIdentifierOnSameLine() {
    nextToken();
    return !scanner.hasPrecedingLineBreak() && isIdentifier();
  }
  function parseYieldExpression() {
    const pos = getNodePos();
    nextToken();
    if (!scanner.hasPrecedingLineBreak() && (token() === SyntaxKind.AsteriskToken || isStartOfExpression())) {
      return finishNode(
        factory.createYieldExpression(
          parseOptionalToken(SyntaxKind.AsteriskToken),
          parseAssignmentExpressionOrHigher(
            /*allowReturnTypeInArrowFunction*/
            true
          )
        ),
        pos
      );
    } else {
      return finishNode(factory.createYieldExpression(
        /*asteriskToken*/
        void 0,
        /*expression*/
        void 0
      ), pos);
    }
  }
  function parseSimpleArrowFunctionExpression(pos, identifier, allowReturnTypeInArrowFunction, hasJSDoc, asyncModifier) {
    Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
    const parameter = factory.createParameterDeclaration(
      /*modifiers*/
      void 0,
      /*dotDotDotToken*/
      void 0,
      identifier,
      /*questionToken*/
      void 0,
      /*type*/
      void 0,
      /*initializer*/
      void 0
    );
    finishNode(parameter, identifier.pos);
    const parameters = createNodeArray([parameter], parameter.pos, parameter.end);
    const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
    const body = parseArrowFunctionExpressionBody(
      /*isAsync*/
      !!asyncModifier,
      allowReturnTypeInArrowFunction
    );
    const node = factory.createArrowFunction(
      asyncModifier,
      /*typeParameters*/
      void 0,
      parameters,
      /*type*/
      void 0,
      equalsGreaterThanToken,
      body
    );
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) {
    const triState = isParenthesizedArrowFunctionExpression();
    if (triState === 0 /* False */) {
      return void 0;
    }
    return triState === 1 /* True */ ? parseParenthesizedArrowFunctionExpression(
      /*allowAmbiguity*/
      true,
      /*allowReturnTypeInArrowFunction*/
      true
    ) : tryParse(() => parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction));
  }
  function isParenthesizedArrowFunctionExpression() {
    if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.AsyncKeyword) {
      return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
    }
    if (token() === SyntaxKind.EqualsGreaterThanToken) {
      return 1 /* True */;
    }
    return 0 /* False */;
  }
  function isParenthesizedArrowFunctionExpressionWorker() {
    if (token() === SyntaxKind.AsyncKeyword) {
      nextToken();
      if (scanner.hasPrecedingLineBreak()) {
        return 0 /* False */;
      }
      if (token() !== SyntaxKind.OpenParenToken && token() !== SyntaxKind.LessThanToken) {
        return 0 /* False */;
      }
    }
    const first = token();
    const second = nextToken();
    if (first === SyntaxKind.OpenParenToken) {
      if (second === SyntaxKind.CloseParenToken) {
        const third = nextToken();
        switch (third) {
          case SyntaxKind.EqualsGreaterThanToken:
          case SyntaxKind.ColonToken:
          case SyntaxKind.OpenBraceToken:
            return 1 /* True */;
          default:
            return 0 /* False */;
        }
      }
      if (second === SyntaxKind.OpenBracketToken || second === SyntaxKind.OpenBraceToken) {
        return 2 /* Unknown */;
      }
      if (second === SyntaxKind.DotDotDotToken) {
        return 1 /* True */;
      }
      if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) {
        if (nextToken() === SyntaxKind.AsKeyword) {
          return 0 /* False */;
        }
        return 1 /* True */;
      }
      if (!isIdentifier() && second !== SyntaxKind.ThisKeyword) {
        return 0 /* False */;
      }
      switch (nextToken()) {
        case SyntaxKind.ColonToken:
          return 1 /* True */;
        case SyntaxKind.QuestionToken:
          nextToken();
          if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken) {
            return 1 /* True */;
          }
          return 0 /* False */;
        case SyntaxKind.CommaToken:
        case SyntaxKind.EqualsToken:
        case SyntaxKind.CloseParenToken:
          return 2 /* Unknown */;
      }
      return 0 /* False */;
    } else {
      Debug.assert(first === SyntaxKind.LessThanToken);
      if (!isIdentifier() && token() !== SyntaxKind.ConstKeyword) {
        return 0 /* False */;
      }
      if (languageVariant === LanguageVariant.JSX) {
        const isArrowFunctionInJsx = lookAhead(() => {
          parseOptional(SyntaxKind.ConstKeyword);
          const third = nextToken();
          if (third === SyntaxKind.ExtendsKeyword) {
            const fourth = nextToken();
            switch (fourth) {
              case SyntaxKind.EqualsToken:
              case SyntaxKind.GreaterThanToken:
              case SyntaxKind.SlashToken:
                return false;
              default:
                return true;
            }
          } else if (third === SyntaxKind.CommaToken || third === SyntaxKind.EqualsToken) {
            return true;
          }
          return false;
        });
        if (isArrowFunctionInJsx) {
          return 1 /* True */;
        }
        return 0 /* False */;
      }
      return 2 /* Unknown */;
    }
  }
  function parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) {
    const tokenPos = scanner.getTokenStart();
    if (notParenthesizedArrow?.has(tokenPos)) {
      return void 0;
    }
    const result = parseParenthesizedArrowFunctionExpression(
      /*allowAmbiguity*/
      false,
      allowReturnTypeInArrowFunction
    );
    if (!result) {
      (notParenthesizedArrow || (notParenthesizedArrow = /* @__PURE__ */ new Set())).add(tokenPos);
    }
    return result;
  }
  function tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction) {
    if (token() === SyntaxKind.AsyncKeyword) {
      if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === 1 /* True */) {
        const pos = getNodePos();
        const hasJSDoc = hasPrecedingJSDocComment();
        const asyncModifier = parseModifiersForArrowFunction();
        const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
        return parseSimpleArrowFunctionExpression(pos, expr, allowReturnTypeInArrowFunction, hasJSDoc, asyncModifier);
      }
    }
    return void 0;
  }
  function isUnParenthesizedAsyncArrowFunctionWorker() {
    if (token() === SyntaxKind.AsyncKeyword) {
      nextToken();
      if (scanner.hasPrecedingLineBreak() || token() === SyntaxKind.EqualsGreaterThanToken) {
        return 0 /* False */;
      }
      const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
      if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
        return 1 /* True */;
      }
    }
    return 0 /* False */;
  }
  function parseParenthesizedArrowFunctionExpression(allowAmbiguity, allowReturnTypeInArrowFunction) {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const modifiers = parseModifiersForArrowFunction();
    const isAsync = some(modifiers, isAsyncModifier) ? 2 /* Await */ : 0 /* None */;
    const typeParameters = parseTypeParameters();
    let parameters;
    if (!parseExpected(SyntaxKind.OpenParenToken)) {
      if (!allowAmbiguity) {
        return void 0;
      }
      parameters = createMissingList();
    } else {
      if (!allowAmbiguity) {
        const maybeParameters = parseParametersWorker(isAsync, allowAmbiguity);
        if (!maybeParameters) {
          return void 0;
        }
        parameters = maybeParameters;
      } else {
        parameters = parseParametersWorker(isAsync, allowAmbiguity);
      }
      if (!parseExpected(SyntaxKind.CloseParenToken) && !allowAmbiguity) {
        return void 0;
      }
    }
    const hasReturnColon = token() === SyntaxKind.ColonToken;
    const type = parseReturnType(
      SyntaxKind.ColonToken,
      /*isType*/
      false
    );
    if (type && !allowAmbiguity && typeHasArrowFunctionBlockingParseError(type)) {
      return void 0;
    }
    let unwrappedType = type;
    while (unwrappedType?.kind === SyntaxKind.ParenthesizedType) {
      unwrappedType = unwrappedType.type;
    }
    const hasJSDocFunctionType = unwrappedType && isJSDocFunctionType(unwrappedType);
    if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) {
      return void 0;
    }
    const lastToken = token();
    const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
    const body = lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier), allowReturnTypeInArrowFunction) : parseIdentifier();
    if (!allowReturnTypeInArrowFunction && hasReturnColon) {
      if (token() !== SyntaxKind.ColonToken) {
        return void 0;
      }
    }
    const node = factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseArrowFunctionExpressionBody(isAsync, allowReturnTypeInArrowFunction) {
    if (token() === SyntaxKind.OpenBraceToken) {
      return parseFunctionBlock(isAsync ? 2 /* Await */ : 0 /* None */);
    }
    if (token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.FunctionKeyword && token() !== SyntaxKind.ClassKeyword && isStartOfStatement() && !isStartOfExpressionStatement()) {
      return parseFunctionBlock(16 /* IgnoreMissingOpenBrace */ | (isAsync ? 2 /* Await */ : 0 /* None */));
    }
    const savedTopLevel = topLevel;
    topLevel = false;
    const node = isAsync ? doInAwaitContext(() => parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction)) : doOutsideOfAwaitContext(() => parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction));
    topLevel = savedTopLevel;
    return node;
  }
  function parseConditionalExpressionRest(leftOperand, pos, allowReturnTypeInArrowFunction) {
    const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
    if (!questionToken) {
      return leftOperand;
    }
    let colonToken;
    return finishNode(
      factory.createConditionalExpression(
        leftOperand,
        questionToken,
        doOutsideOfContext(disallowInAndDecoratorContext, () => parseAssignmentExpressionOrHigher(
          /*allowReturnTypeInArrowFunction*/
          false
        )),
        colonToken = parseExpectedToken(SyntaxKind.ColonToken),
        nodeIsPresent(colonToken) ? parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction) : createMissingNode(
          SyntaxKind.Identifier,
          /*reportAtCurrentPosition*/
          false,
          Diagnostics._0_expected,
          tokenToString(SyntaxKind.ColonToken)
        )
      ),
      pos
    );
  }
  function parseBinaryExpressionOrHigher(precedence) {
    const pos = getNodePos();
    const leftOperand = parseUnaryExpressionOrHigher();
    return parseBinaryExpressionRest(precedence, leftOperand, pos);
  }
  function isInOrOfKeyword(t) {
    return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword;
  }
  function parseBinaryExpressionRest(precedence, leftOperand, pos) {
    while (true) {
      reScanGreaterToken();
      const newPrecedence = getBinaryOperatorPrecedence(token());
      const consumeCurrentOperator = token() === SyntaxKind.AsteriskAsteriskToken ? newPrecedence >= precedence : newPrecedence > precedence;
      if (!consumeCurrentOperator) {
        break;
      }
      if (token() === SyntaxKind.InKeyword && inDisallowInContext()) {
        break;
      }
      if (token() === SyntaxKind.AsKeyword || token() === SyntaxKind.SatisfiesKeyword) {
        if (scanner.hasPrecedingLineBreak()) {
          break;
        } else {
          const keywordKind = token();
          nextToken();
          leftOperand = keywordKind === SyntaxKind.SatisfiesKeyword ? makeSatisfiesExpression(leftOperand, parseType()) : makeAsExpression(leftOperand, parseType());
        }
      } else {
        leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence), pos);
      }
    }
    return leftOperand;
  }
  function isBinaryOperator() {
    if (inDisallowInContext() && token() === SyntaxKind.InKeyword) {
      return false;
    }
    return getBinaryOperatorPrecedence(token()) > 0;
  }
  function makeSatisfiesExpression(left, right) {
    return finishNode(factory.createSatisfiesExpression(left, right), left.pos);
  }
  function makeBinaryExpression(left, operatorToken, right, pos) {
    return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos);
  }
  function makeAsExpression(left, right) {
    return finishNode(factory.createAsExpression(left, right), left.pos);
  }
  function parsePrefixUnaryExpression() {
    const pos = getNodePos();
    return finishNode(factory.createPrefixUnaryExpression(token(), nextTokenAnd(parseSimpleUnaryExpression)), pos);
  }
  function parseDeleteExpression() {
    const pos = getNodePos();
    return finishNode(factory.createDeleteExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
  }
  function parseTypeOfExpression() {
    const pos = getNodePos();
    return finishNode(factory.createTypeOfExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
  }
  function parseVoidExpression() {
    const pos = getNodePos();
    return finishNode(factory.createVoidExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
  }
  function isAwaitExpression() {
    if (token() === SyntaxKind.AwaitKeyword) {
      if (inAwaitContext()) {
        return true;
      }
      return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
    }
    return false;
  }
  function parseAwaitExpression() {
    const pos = getNodePos();
    return finishNode(factory.createAwaitExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
  }
  function parseUnaryExpressionOrHigher() {
    if (isUpdateExpression()) {
      const pos = getNodePos();
      const updateExpression = parseUpdateExpression();
      return token() === SyntaxKind.AsteriskAsteriskToken ? parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) : updateExpression;
    }
    const unaryOperator = token();
    const simpleUnaryExpression = parseSimpleUnaryExpression();
    if (token() === SyntaxKind.AsteriskAsteriskToken) {
      const pos = skipTrivia(sourceText, simpleUnaryExpression.pos);
      const { end } = simpleUnaryExpression;
      if (simpleUnaryExpression.kind === SyntaxKind.TypeAssertionExpression) {
        parseErrorAt(pos, end, Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses);
      } else {
        Debug.assert(isKeywordOrPunctuation(unaryOperator));
        parseErrorAt(pos, end, Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator));
      }
    }
    return simpleUnaryExpression;
  }
  function parseSimpleUnaryExpression() {
    switch (token()) {
      case SyntaxKind.PlusToken:
      case SyntaxKind.MinusToken:
      case SyntaxKind.TildeToken:
      case SyntaxKind.ExclamationToken:
        return parsePrefixUnaryExpression();
      case SyntaxKind.DeleteKeyword:
        return parseDeleteExpression();
      case SyntaxKind.TypeOfKeyword:
        return parseTypeOfExpression();
      case SyntaxKind.VoidKeyword:
        return parseVoidExpression();
      case SyntaxKind.LessThanToken:
        if (languageVariant === LanguageVariant.JSX) {
          return parseJsxElementOrSelfClosingElementOrFragment(
            /*inExpressionContext*/
            true,
            /*topInvalidNodePosition*/
            void 0,
            /*openingTag*/
            void 0,
            /*mustBeUnary*/
            true
          );
        }
        return parseTypeAssertion();
      case SyntaxKind.AwaitKeyword:
        if (isAwaitExpression()) {
          return parseAwaitExpression();
        }
      // falls through
      default:
        return parseUpdateExpression();
    }
  }
  function isUpdateExpression() {
    switch (token()) {
      case SyntaxKind.PlusToken:
      case SyntaxKind.MinusToken:
      case SyntaxKind.TildeToken:
      case SyntaxKind.ExclamationToken:
      case SyntaxKind.DeleteKeyword:
      case SyntaxKind.TypeOfKeyword:
      case SyntaxKind.VoidKeyword:
      case SyntaxKind.AwaitKeyword:
        return false;
      case SyntaxKind.LessThanToken:
        if (languageVariant !== LanguageVariant.JSX) {
          return false;
        }
      // We are in JSX context and the token is part of JSXElement.
      // falls through
      default:
        return true;
    }
  }
  function parseUpdateExpression() {
    if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
      const pos = getNodePos();
      return finishNode(factory.createPrefixUnaryExpression(token(), nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos);
    } else if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) {
      return parseJsxElementOrSelfClosingElementOrFragment(
        /*inExpressionContext*/
        true
      );
    }
    const expression = parseLeftHandSideExpressionOrHigher();
    Debug.assert(isLeftHandSideExpression(expression));
    if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) {
      const operator = token();
      nextToken();
      return finishNode(factory.createPostfixUnaryExpression(expression, operator), expression.pos);
    }
    return expression;
  }
  function parseLeftHandSideExpressionOrHigher() {
    const pos = getNodePos();
    let expression;
    if (token() === SyntaxKind.ImportKeyword) {
      if (lookAhead(nextTokenIsOpenParenOrLessThan)) {
        sourceFlags |= NodeFlags.PossiblyContainsDynamicImport;
        expression = parseTokenNode();
      } else if (lookAhead(nextTokenIsDot)) {
        nextToken();
        nextToken();
        expression = finishNode(factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), pos);
        sourceFlags |= NodeFlags.PossiblyContainsImportMeta;
      } else {
        expression = parseMemberExpressionOrHigher();
      }
    } else {
      expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
    }
    return parseCallExpressionRest(pos, expression);
  }
  function parseMemberExpressionOrHigher() {
    const pos = getNodePos();
    const expression = parsePrimaryExpression();
    return parseMemberExpressionRest(
      pos,
      expression,
      /*allowOptionalChain*/
      true
    );
  }
  function parseSuperExpression() {
    const pos = getNodePos();
    let expression = parseTokenNode();
    if (token() === SyntaxKind.LessThanToken) {
      const startPos = getNodePos();
      const typeArguments = tryParse(parseTypeArgumentsInExpression);
      if (typeArguments !== void 0) {
        parseErrorAt(startPos, getNodePos(), Diagnostics.super_may_not_use_type_arguments);
        if (!isTemplateStartOfTaggedTemplate()) {
          expression = factory.createExpressionWithTypeArguments(expression, typeArguments);
        }
      }
    }
    if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken || token() === SyntaxKind.OpenBracketToken) {
      return expression;
    }
    parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
    return finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(
      /*allowIdentifierNames*/
      true,
      /*allowPrivateIdentifiers*/
      true,
      /*allowUnicodeEscapeSequenceInIdentifierName*/
      true
    )), pos);
  }
  function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext, topInvalidNodePosition, openingTag, mustBeUnary = false) {
    const pos = getNodePos();
    const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext);
    let result;
    if (opening.kind === SyntaxKind.JsxOpeningElement) {
      let children = parseJsxChildren(opening);
      let closingElement;
      const lastChild = children[children.length - 1];
      if (lastChild?.kind === SyntaxKind.JsxElement && !tagNamesAreEquivalent(lastChild.openingElement.tagName, lastChild.closingElement.tagName) && tagNamesAreEquivalent(opening.tagName, lastChild.closingElement.tagName)) {
        const end = lastChild.children.end;
        const newLast = finishNode(
          factory.createJsxElement(
            lastChild.openingElement,
            lastChild.children,
            finishNode(factory.createJsxClosingElement(finishNode(factoryCreateIdentifier(""), end, end)), end, end)
          ),
          lastChild.openingElement.pos,
          end
        );
        children = createNodeArray([...children.slice(0, children.length - 1), newLast], children.pos, end);
        closingElement = lastChild.closingElement;
      } else {
        closingElement = parseJsxClosingElement(opening, inExpressionContext);
        if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) {
          if (openingTag && isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName)) {
            parseErrorAtRange(opening.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.tagName));
          } else {
            parseErrorAtRange(closingElement.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName));
          }
        }
      }
      result = finishNode(factory.createJsxElement(opening, children, closingElement), pos);
    } else if (opening.kind === SyntaxKind.JsxOpeningFragment) {
      result = finishNode(factory.createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos);
    } else {
      Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement);
      result = opening;
    }
    if (!mustBeUnary && inExpressionContext && token() === SyntaxKind.LessThanToken) {
      const topBadPos = typeof topInvalidNodePosition === "undefined" ? result.pos : topInvalidNodePosition;
      const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(
        /*inExpressionContext*/
        true,
        topBadPos
      ));
      if (invalidElement) {
        const operatorToken = createMissingNode(
          SyntaxKind.CommaToken,
          /*reportAtCurrentPosition*/
          false
        );
        setTextRangePosWidth(operatorToken, invalidElement.pos, 0);
        parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics.JSX_expressions_must_have_one_parent_element);
        return finishNode(factory.createBinaryExpression(result, operatorToken, invalidElement), pos);
      }
    }
    return result;
  }
  function parseJsxText() {
    const pos = getNodePos();
    const node = factory.createJsxText(scanner.getTokenValue(), currentToken === SyntaxKind.JsxTextAllWhiteSpaces);
    currentToken = scanner.scanJsxToken();
    return finishNode(node, pos);
  }
  function parseJsxChild(openingTag, token2) {
    switch (token2) {
      case SyntaxKind.EndOfFileToken:
        if (isJsxOpeningFragment(openingTag)) {
          parseErrorAtRange(openingTag, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag);
        } else {
          const tag = openingTag.tagName;
          const start = Math.min(skipTrivia(sourceText, tag.pos), tag.end);
          parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName));
        }
        return void 0;
      case SyntaxKind.LessThanSlashToken:
      case SyntaxKind.ConflictMarkerTrivia:
        return void 0;
      case SyntaxKind.JsxText:
      case SyntaxKind.JsxTextAllWhiteSpaces:
        return parseJsxText();
      case SyntaxKind.OpenBraceToken:
        return parseJsxExpression(
          /*inExpressionContext*/
          false
        );
      case SyntaxKind.LessThanToken:
        return parseJsxElementOrSelfClosingElementOrFragment(
          /*inExpressionContext*/
          false,
          /*topInvalidNodePosition*/
          void 0,
          openingTag
        );
      default:
        return Debug.assertNever(token2);
    }
  }
  function parseJsxChildren(openingTag) {
    const list = [];
    const listPos = getNodePos();
    const saveParsingContext = parsingContext;
    parsingContext |= 1 << 14 /* JsxChildren */;
    while (true) {
      const child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken());
      if (!child) break;
      list.push(child);
      if (isJsxOpeningElement(openingTag) && child?.kind === SyntaxKind.JsxElement && !tagNamesAreEquivalent(child.openingElement.tagName, child.closingElement.tagName) && tagNamesAreEquivalent(openingTag.tagName, child.closingElement.tagName)) {
        break;
      }
    }
    parsingContext = saveParsingContext;
    return createNodeArray(list, listPos);
  }
  function parseJsxAttributes() {
    const pos = getNodePos();
    return finishNode(factory.createJsxAttributes(parseList(13 /* JsxAttributes */, parseJsxAttribute)), pos);
  }
  function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext) {
    const pos = getNodePos();
    parseExpected(SyntaxKind.LessThanToken);
    if (token() === SyntaxKind.GreaterThanToken) {
      scanJsxText();
      return finishNode(factory.createJsxOpeningFragment(), pos);
    }
    const tagName = parseJsxElementName();
    const typeArguments = (contextFlags & NodeFlags.JavaScriptFile) === 0 ? tryParseTypeArguments() : void 0;
    const attributes = parseJsxAttributes();
    let node;
    if (token() === SyntaxKind.GreaterThanToken) {
      scanJsxText();
      node = factory.createJsxOpeningElement(tagName, typeArguments, attributes);
    } else {
      parseExpected(SyntaxKind.SlashToken);
      if (parseExpected(
        SyntaxKind.GreaterThanToken,
        /*diagnosticMessage*/
        void 0,
        /*shouldAdvance*/
        false
      )) {
        if (inExpressionContext) {
          nextToken();
        } else {
          scanJsxText();
        }
      }
      node = factory.createJsxSelfClosingElement(tagName, typeArguments, attributes);
    }
    return finishNode(node, pos);
  }
  function parseJsxElementName() {
    const pos = getNodePos();
    const initialExpression = parseJsxTagName();
    if (isJsxNamespacedName(initialExpression)) {
      return initialExpression;
    }
    let expression = initialExpression;
    while (parseOptional(SyntaxKind.DotToken)) {
      expression = finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(
        /*allowIdentifierNames*/
        true,
        /*allowPrivateIdentifiers*/
        false,
        /*allowUnicodeEscapeSequenceInIdentifierName*/
        false
      )), pos);
    }
    return expression;
  }
  function parseJsxTagName() {
    const pos = getNodePos();
    scanJsxIdentifier();
    const isThis = token() === SyntaxKind.ThisKeyword;
    const tagName = parseIdentifierNameErrorOnUnicodeEscapeSequence();
    if (parseOptional(SyntaxKind.ColonToken)) {
      scanJsxIdentifier();
      return finishNode(factory.createJsxNamespacedName(tagName, parseIdentifierNameErrorOnUnicodeEscapeSequence()), pos);
    }
    return isThis ? finishNode(factory.createToken(SyntaxKind.ThisKeyword), pos) : tagName;
  }
  function parseJsxExpression(inExpressionContext) {
    const pos = getNodePos();
    if (!parseExpected(SyntaxKind.OpenBraceToken)) {
      return void 0;
    }
    let dotDotDotToken;
    let expression;
    if (token() !== SyntaxKind.CloseBraceToken) {
      if (!inExpressionContext) {
        dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
      }
      expression = parseExpression();
    }
    if (inExpressionContext) {
      parseExpected(SyntaxKind.CloseBraceToken);
    } else {
      if (parseExpected(
        SyntaxKind.CloseBraceToken,
        /*diagnosticMessage*/
        void 0,
        /*shouldAdvance*/
        false
      )) {
        scanJsxText();
      }
    }
    return finishNode(factory.createJsxExpression(dotDotDotToken, expression), pos);
  }
  function parseJsxAttribute() {
    if (token() === SyntaxKind.OpenBraceToken) {
      return parseJsxSpreadAttribute();
    }
    const pos = getNodePos();
    return finishNode(factory.createJsxAttribute(parseJsxAttributeName(), parseJsxAttributeValue()), pos);
  }
  function parseJsxAttributeValue() {
    if (token() === SyntaxKind.EqualsToken) {
      if (scanJsxAttributeValue() === SyntaxKind.StringLiteral) {
        return parseLiteralNode();
      }
      if (token() === SyntaxKind.OpenBraceToken) {
        return parseJsxExpression(
          /*inExpressionContext*/
          true
        );
      }
      if (token() === SyntaxKind.LessThanToken) {
        return parseJsxElementOrSelfClosingElementOrFragment(
          /*inExpressionContext*/
          true
        );
      }
      parseErrorAtCurrentToken(Diagnostics.or_JSX_element_expected);
    }
    return void 0;
  }
  function parseJsxAttributeName() {
    const pos = getNodePos();
    scanJsxIdentifier();
    const attrName = parseIdentifierNameErrorOnUnicodeEscapeSequence();
    if (parseOptional(SyntaxKind.ColonToken)) {
      scanJsxIdentifier();
      return finishNode(factory.createJsxNamespacedName(attrName, parseIdentifierNameErrorOnUnicodeEscapeSequence()), pos);
    }
    return attrName;
  }
  function parseJsxSpreadAttribute() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.OpenBraceToken);
    parseExpected(SyntaxKind.DotDotDotToken);
    const expression = parseExpression();
    parseExpected(SyntaxKind.CloseBraceToken);
    return finishNode(factory.createJsxSpreadAttribute(expression), pos);
  }
  function parseJsxClosingElement(open, inExpressionContext) {
    const pos = getNodePos();
    parseExpected(SyntaxKind.LessThanSlashToken);
    const tagName = parseJsxElementName();
    if (parseExpected(
      SyntaxKind.GreaterThanToken,
      /*diagnosticMessage*/
      void 0,
      /*shouldAdvance*/
      false
    )) {
      if (inExpressionContext || !tagNamesAreEquivalent(open.tagName, tagName)) {
        nextToken();
      } else {
        scanJsxText();
      }
    }
    return finishNode(factory.createJsxClosingElement(tagName), pos);
  }
  function parseJsxClosingFragment(inExpressionContext) {
    const pos = getNodePos();
    parseExpected(SyntaxKind.LessThanSlashToken);
    if (parseExpected(
      SyntaxKind.GreaterThanToken,
      Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment,
      /*shouldAdvance*/
      false
    )) {
      if (inExpressionContext) {
        nextToken();
      } else {
        scanJsxText();
      }
    }
    return finishNode(factory.createJsxJsxClosingFragment(), pos);
  }
  function parseTypeAssertion() {
    Debug.assert(languageVariant !== LanguageVariant.JSX, "Type assertions should never be parsed in JSX; they should be parsed as comparisons or JSX elements/fragments.");
    const pos = getNodePos();
    parseExpected(SyntaxKind.LessThanToken);
    const type = parseType();
    parseExpected(SyntaxKind.GreaterThanToken);
    const expression = parseSimpleUnaryExpression();
    return finishNode(factory.createTypeAssertion(type, expression), pos);
  }
  function nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate() {
    nextToken();
    return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBracketToken || isTemplateStartOfTaggedTemplate();
  }
  function isStartOfOptionalPropertyOrElementAccessChain() {
    return token() === SyntaxKind.QuestionDotToken && lookAhead(nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate);
  }
  function tryReparseOptionalChain(node) {
    if (node.flags & NodeFlags.OptionalChain) {
      return true;
    }
    if (isNonNullExpression(node)) {
      let expr = node.expression;
      while (isNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) {
        expr = expr.expression;
      }
      if (expr.flags & NodeFlags.OptionalChain) {
        while (isNonNullExpression(node)) {
          node.flags |= NodeFlags.OptionalChain;
          node = node.expression;
        }
        return true;
      }
    }
    return false;
  }
  function parsePropertyAccessExpressionRest(pos, expression, questionDotToken) {
    const name = parseRightSideOfDot(
      /*allowIdentifierNames*/
      true,
      /*allowPrivateIdentifiers*/
      true,
      /*allowUnicodeEscapeSequenceInIdentifierName*/
      true
    );
    const isOptionalChain = questionDotToken || tryReparseOptionalChain(expression);
    const propertyAccess = isOptionalChain ? factoryCreatePropertyAccessChain(expression, questionDotToken, name) : factoryCreatePropertyAccessExpression(expression, name);
    if (isOptionalChain && isPrivateIdentifier(propertyAccess.name)) {
      parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers);
    }
    if (isExpressionWithTypeArguments(expression) && expression.typeArguments) {
      const pos2 = expression.typeArguments.pos - 1;
      const end = skipTrivia(sourceText, expression.typeArguments.end) + 1;
      parseErrorAt(pos2, end, Diagnostics.An_instantiation_expression_cannot_be_followed_by_a_property_access);
    }
    return finishNode(propertyAccess, pos);
  }
  function parseElementAccessExpressionRest(pos, expression, questionDotToken) {
    let argumentExpression;
    if (token() === SyntaxKind.CloseBracketToken) {
      argumentExpression = createMissingNode(
        SyntaxKind.Identifier,
        /*reportAtCurrentPosition*/
        true,
        Diagnostics.An_element_access_expression_should_take_an_argument
      );
    } else {
      const argument = allowInAnd(parseExpression);
      if (isStringOrNumericLiteralLike(argument)) {
        argument.text = internIdentifier(argument.text);
      }
      argumentExpression = argument;
    }
    parseExpected(SyntaxKind.CloseBracketToken);
    const indexedAccess = questionDotToken || tryReparseOptionalChain(expression) ? factoryCreateElementAccessChain(expression, questionDotToken, argumentExpression) : factoryCreateElementAccessExpression(expression, argumentExpression);
    return finishNode(indexedAccess, pos);
  }
  function parseMemberExpressionRest(pos, expression, allowOptionalChain) {
    while (true) {
      let questionDotToken;
      let isPropertyAccess = false;
      if (allowOptionalChain && isStartOfOptionalPropertyOrElementAccessChain()) {
        questionDotToken = parseExpectedToken(SyntaxKind.QuestionDotToken);
        isPropertyAccess = tokenIsIdentifierOrKeyword(token());
      } else {
        isPropertyAccess = parseOptional(SyntaxKind.DotToken);
      }
      if (isPropertyAccess) {
        expression = parsePropertyAccessExpressionRest(pos, expression, questionDotToken);
        continue;
      }
      if ((questionDotToken || !inDecoratorContext()) && parseOptional(SyntaxKind.OpenBracketToken)) {
        expression = parseElementAccessExpressionRest(pos, expression, questionDotToken);
        continue;
      }
      if (isTemplateStartOfTaggedTemplate()) {
        expression = !questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments ? parseTaggedTemplateRest(pos, expression.expression, questionDotToken, expression.typeArguments) : parseTaggedTemplateRest(
          pos,
          expression,
          questionDotToken,
          /*typeArguments*/
          void 0
        );
        continue;
      }
      if (!questionDotToken) {
        if (token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
          nextToken();
          expression = finishNode(factory.createNonNullExpression(expression), pos);
          continue;
        }
        const typeArguments = tryParse(parseTypeArgumentsInExpression);
        if (typeArguments) {
          expression = finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos);
          continue;
        }
      }
      return expression;
    }
  }
  function isTemplateStartOfTaggedTemplate() {
    return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead;
  }
  function parseTaggedTemplateRest(pos, tag, questionDotToken, typeArguments) {
    const tagExpression = factory.createTaggedTemplateExpression(
      tag,
      typeArguments,
      token() === SyntaxKind.NoSubstitutionTemplateLiteral ? (reScanTemplateToken(
        /*isTaggedTemplate*/
        true
      ), parseLiteralNode()) : parseTemplateExpression(
        /*isTaggedTemplate*/
        true
      )
    );
    if (questionDotToken || tag.flags & NodeFlags.OptionalChain) {
      tagExpression.flags |= NodeFlags.OptionalChain;
    }
    tagExpression.questionDotToken = questionDotToken;
    return finishNode(tagExpression, pos);
  }
  function parseCallExpressionRest(pos, expression) {
    while (true) {
      expression = parseMemberExpressionRest(
        pos,
        expression,
        /*allowOptionalChain*/
        true
      );
      let typeArguments;
      const questionDotToken = parseOptionalToken(SyntaxKind.QuestionDotToken);
      if (questionDotToken) {
        typeArguments = tryParse(parseTypeArgumentsInExpression);
        if (isTemplateStartOfTaggedTemplate()) {
          expression = parseTaggedTemplateRest(pos, expression, questionDotToken, typeArguments);
          continue;
        }
      }
      if (typeArguments || token() === SyntaxKind.OpenParenToken) {
        if (!questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments) {
          typeArguments = expression.typeArguments;
          expression = expression.expression;
        }
        const argumentList = parseArgumentList();
        const callExpr = questionDotToken || tryReparseOptionalChain(expression) ? factoryCreateCallChain(expression, questionDotToken, typeArguments, argumentList) : factoryCreateCallExpression(expression, typeArguments, argumentList);
        expression = finishNode(callExpr, pos);
        continue;
      }
      if (questionDotToken) {
        const name = createMissingNode(
          SyntaxKind.Identifier,
          /*reportAtCurrentPosition*/
          false,
          Diagnostics.Identifier_expected
        );
        expression = finishNode(factoryCreatePropertyAccessChain(expression, questionDotToken, name), pos);
      }
      break;
    }
    return expression;
  }
  function parseArgumentList() {
    parseExpected(SyntaxKind.OpenParenToken);
    const result = parseDelimitedList(11 /* ArgumentExpressions */, parseArgumentExpression);
    parseExpected(SyntaxKind.CloseParenToken);
    return result;
  }
  function parseTypeArgumentsInExpression() {
    if ((contextFlags & NodeFlags.JavaScriptFile) !== 0) {
      return void 0;
    }
    if (reScanLessThanToken() !== SyntaxKind.LessThanToken) {
      return void 0;
    }
    nextToken();
    const typeArguments = parseDelimitedList(20 /* TypeArguments */, parseType);
    if (reScanGreaterToken() !== SyntaxKind.GreaterThanToken) {
      return void 0;
    }
    nextToken();
    return typeArguments && canFollowTypeArgumentsInExpression() ? typeArguments : void 0;
  }
  function canFollowTypeArgumentsInExpression() {
    switch (token()) {
      // These tokens can follow a type argument list in a call expression.
      case SyntaxKind.OpenParenToken:
      // foo<x>(
      case SyntaxKind.NoSubstitutionTemplateLiteral:
      // foo<T> `...`
      case SyntaxKind.TemplateHead:
        return true;
      // A type argument list followed by `<` never makes sense, and a type argument list followed
      // by `>` is ambiguous with a (re-scanned) `>>` operator, so we disqualify both. Also, in
      // this context, `+` and `-` are unary operators, not binary operators.
      case SyntaxKind.LessThanToken:
      case SyntaxKind.GreaterThanToken:
      case SyntaxKind.PlusToken:
      case SyntaxKind.MinusToken:
        return false;
    }
    return scanner.hasPrecedingLineBreak() || isBinaryOperator() || !isStartOfExpression();
  }
  function parsePrimaryExpression() {
    switch (token()) {
      case SyntaxKind.NoSubstitutionTemplateLiteral:
        if (scanner.getTokenFlags() & TokenFlags.IsInvalid) {
          reScanTemplateToken(
            /*isTaggedTemplate*/
            false
          );
        }
      // falls through
      case SyntaxKind.NumericLiteral:
      case SyntaxKind.BigIntLiteral:
      case SyntaxKind.StringLiteral:
        return parseLiteralNode();
      case SyntaxKind.ThisKeyword:
      case SyntaxKind.SuperKeyword:
      case SyntaxKind.NullKeyword:
      case SyntaxKind.TrueKeyword:
      case SyntaxKind.FalseKeyword:
        return parseTokenNode();
      case SyntaxKind.OpenParenToken:
        return parseParenthesizedExpression();
      case SyntaxKind.OpenBracketToken:
        return parseArrayLiteralExpression();
      case SyntaxKind.OpenBraceToken:
        return parseObjectLiteralExpression();
      case SyntaxKind.AsyncKeyword:
        if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
          break;
        }
        return parseFunctionExpression();
      case SyntaxKind.AtToken:
        return parseDecoratedExpression();
      case SyntaxKind.ClassKeyword:
        return parseClassExpression();
      case SyntaxKind.FunctionKeyword:
        return parseFunctionExpression();
      case SyntaxKind.NewKeyword:
        return parseNewExpressionOrNewDotTarget();
      case SyntaxKind.SlashToken:
      case SyntaxKind.SlashEqualsToken:
        if (reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
          return parseLiteralNode();
        }
        break;
      case SyntaxKind.TemplateHead:
        return parseTemplateExpression(
          /*isTaggedTemplate*/
          false
        );
      case SyntaxKind.PrivateIdentifier:
        return parsePrivateIdentifier();
    }
    return parseIdentifier(Diagnostics.Expression_expected);
  }
  function parseParenthesizedExpression() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.OpenParenToken);
    const expression = allowInAnd(parseExpression);
    parseExpected(SyntaxKind.CloseParenToken);
    return withJSDoc(finishNode(factoryCreateParenthesizedExpression(expression), pos), hasJSDoc);
  }
  function parseSpreadElement() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.DotDotDotToken);
    const expression = parseAssignmentExpressionOrHigher(
      /*allowReturnTypeInArrowFunction*/
      true
    );
    return finishNode(factory.createSpreadElement(expression), pos);
  }
  function parseArgumentOrArrayLiteralElement() {
    return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() : token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) : parseAssignmentExpressionOrHigher(
      /*allowReturnTypeInArrowFunction*/
      true
    );
  }
  function parseArgumentExpression() {
    return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
  }
  function parseArrayLiteralExpression() {
    const pos = getNodePos();
    const openBracketPosition = scanner.getTokenStart();
    const openBracketParsed = parseExpected(SyntaxKind.OpenBracketToken);
    const multiLine = scanner.hasPrecedingLineBreak();
    const elements = parseDelimitedList(15 /* ArrayLiteralMembers */, parseArgumentOrArrayLiteralElement);
    parseExpectedMatchingBrackets(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, openBracketParsed, openBracketPosition);
    return finishNode(factoryCreateArrayLiteralExpression(elements, multiLine), pos);
  }
  function parseObjectLiteralElement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    if (parseOptionalToken(SyntaxKind.DotDotDotToken)) {
      const expression = parseAssignmentExpressionOrHigher(
        /*allowReturnTypeInArrowFunction*/
        true
      );
      return withJSDoc(finishNode(factory.createSpreadAssignment(expression), pos), hasJSDoc);
    }
    const modifiers = parseModifiers(
      /*allowDecorators*/
      true
    );
    if (parseContextualModifier(SyntaxKind.GetKeyword)) {
      return parseAccessorDeclaration(pos, hasJSDoc, modifiers, SyntaxKind.GetAccessor, 0 /* None */);
    }
    if (parseContextualModifier(SyntaxKind.SetKeyword)) {
      return parseAccessorDeclaration(pos, hasJSDoc, modifiers, SyntaxKind.SetAccessor, 0 /* None */);
    }
    const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
    const tokenIsIdentifier = isIdentifier();
    const name = parsePropertyName();
    const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
    const exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken);
    if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
      return parseMethodDeclaration(pos, hasJSDoc, modifiers, asteriskToken, name, questionToken, exclamationToken);
    }
    let node;
    const isShorthandPropertyAssignment = tokenIsIdentifier && token() !== SyntaxKind.ColonToken;
    if (isShorthandPropertyAssignment) {
      const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken);
      const objectAssignmentInitializer = equalsToken ? allowInAnd(() => parseAssignmentExpressionOrHigher(
        /*allowReturnTypeInArrowFunction*/
        true
      )) : void 0;
      node = factory.createShorthandPropertyAssignment(name, objectAssignmentInitializer);
      node.equalsToken = equalsToken;
    } else {
      parseExpected(SyntaxKind.ColonToken);
      const initializer = allowInAnd(() => parseAssignmentExpressionOrHigher(
        /*allowReturnTypeInArrowFunction*/
        true
      ));
      node = factory.createPropertyAssignment(name, initializer);
    }
    node.modifiers = modifiers;
    node.questionToken = questionToken;
    node.exclamationToken = exclamationToken;
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseObjectLiteralExpression() {
    const pos = getNodePos();
    const openBracePosition = scanner.getTokenStart();
    const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken);
    const multiLine = scanner.hasPrecedingLineBreak();
    const properties = parseDelimitedList(
      12 /* ObjectLiteralMembers */,
      parseObjectLiteralElement,
      /*considerSemicolonAsDelimiter*/
      true
    );
    parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition);
    return finishNode(factoryCreateObjectLiteralExpression(properties, multiLine), pos);
  }
  function parseFunctionExpression() {
    const savedDecoratorContext = inDecoratorContext();
    setDecoratorContext(
      /*val*/
      false
    );
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const modifiers = parseModifiers(
      /*allowDecorators*/
      false
    );
    parseExpected(SyntaxKind.FunctionKeyword);
    const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
    const isGenerator = asteriskToken ? 1 /* Yield */ : 0 /* None */;
    const isAsync = some(modifiers, isAsyncModifier) ? 2 /* Await */ : 0 /* None */;
    const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) : isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) : isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) : parseOptionalBindingIdentifier();
    const typeParameters = parseTypeParameters();
    const parameters = parseParameters(isGenerator | isAsync);
    const type = parseReturnType(
      SyntaxKind.ColonToken,
      /*isType*/
      false
    );
    const body = parseFunctionBlock(isGenerator | isAsync);
    setDecoratorContext(savedDecoratorContext);
    const node = factory.createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseOptionalBindingIdentifier() {
    return isBindingIdentifier() ? parseBindingIdentifier() : void 0;
  }
  function parseNewExpressionOrNewDotTarget() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.NewKeyword);
    if (parseOptional(SyntaxKind.DotToken)) {
      const name = parseIdentifierName();
      return finishNode(factory.createMetaProperty(SyntaxKind.NewKeyword, name), pos);
    }
    const expressionPos = getNodePos();
    let expression = parseMemberExpressionRest(
      expressionPos,
      parsePrimaryExpression(),
      /*allowOptionalChain*/
      false
    );
    let typeArguments;
    if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) {
      typeArguments = expression.typeArguments;
      expression = expression.expression;
    }
    if (token() === SyntaxKind.QuestionDotToken) {
      parseErrorAtCurrentToken(Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, getTextOfNodeFromSourceText(sourceText, expression));
    }
    const argumentList = token() === SyntaxKind.OpenParenToken ? parseArgumentList() : void 0;
    return finishNode(factoryCreateNewExpression(expression, typeArguments, argumentList), pos);
  }
  function parseBlock(ignoreMissingOpenBrace, diagnosticMessage) {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const openBracePosition = scanner.getTokenStart();
    const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage);
    if (openBraceParsed || ignoreMissingOpenBrace) {
      const multiLine = scanner.hasPrecedingLineBreak();
      const statements = parseList(1 /* BlockStatements */, parseStatement);
      parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition);
      const result = withJSDoc(finishNode(factoryCreateBlock(statements, multiLine), pos), hasJSDoc);
      if (token() === SyntaxKind.EqualsToken) {
        parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected_This_follows_a_block_of_statements_so_if_you_intended_to_write_a_destructuring_assignment_you_might_need_to_wrap_the_whole_assignment_in_parentheses);
        nextToken();
      }
      return result;
    } else {
      const statements = createMissingList();
      return withJSDoc(finishNode(factoryCreateBlock(
        statements,
        /*multiLine*/
        void 0
      ), pos), hasJSDoc);
    }
  }
  function parseFunctionBlock(flags, diagnosticMessage) {
    const savedYieldContext = inYieldContext();
    setYieldContext(!!(flags & 1 /* Yield */));
    const savedAwaitContext = inAwaitContext();
    setAwaitContext(!!(flags & 2 /* Await */));
    const savedTopLevel = topLevel;
    topLevel = false;
    const saveDecoratorContext = inDecoratorContext();
    if (saveDecoratorContext) {
      setDecoratorContext(
        /*val*/
        false
      );
    }
    const block = parseBlock(!!(flags & 16 /* IgnoreMissingOpenBrace */), diagnosticMessage);
    if (saveDecoratorContext) {
      setDecoratorContext(
        /*val*/
        true
      );
    }
    topLevel = savedTopLevel;
    setYieldContext(savedYieldContext);
    setAwaitContext(savedAwaitContext);
    return block;
  }
  function parseEmptyStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.SemicolonToken);
    return withJSDoc(finishNode(factory.createEmptyStatement(), pos), hasJSDoc);
  }
  function parseIfStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.IfKeyword);
    const openParenPosition = scanner.getTokenStart();
    const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
    const expression = allowInAnd(parseExpression);
    parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
    const thenStatement = parseStatement();
    const elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : void 0;
    return withJSDoc(finishNode(factoryCreateIfStatement(expression, thenStatement, elseStatement), pos), hasJSDoc);
  }
  function parseDoStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.DoKeyword);
    const statement = parseStatement();
    parseExpected(SyntaxKind.WhileKeyword);
    const openParenPosition = scanner.getTokenStart();
    const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
    const expression = allowInAnd(parseExpression);
    parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
    parseOptional(SyntaxKind.SemicolonToken);
    return withJSDoc(finishNode(factory.createDoStatement(statement, expression), pos), hasJSDoc);
  }
  function parseWhileStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.WhileKeyword);
    const openParenPosition = scanner.getTokenStart();
    const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
    const expression = allowInAnd(parseExpression);
    parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
    const statement = parseStatement();
    return withJSDoc(finishNode(factoryCreateWhileStatement(expression, statement), pos), hasJSDoc);
  }
  function parseForOrForInOrForOfStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.ForKeyword);
    const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword);
    parseExpected(SyntaxKind.OpenParenToken);
    let initializer;
    if (token() !== SyntaxKind.SemicolonToken) {
      if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword || token() === SyntaxKind.UsingKeyword && lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLineDisallowOf) || token() === SyntaxKind.AwaitKeyword && lookAhead(nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLineDisallowOf)) {
        initializer = parseVariableDeclarationList(
          /*inForStatementInitializer*/
          true
        );
      } else {
        initializer = disallowInAnd(parseExpression);
      }
    }
    let node;
    if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) {
      const expression = allowInAnd(() => parseAssignmentExpressionOrHigher(
        /*allowReturnTypeInArrowFunction*/
        true
      ));
      parseExpected(SyntaxKind.CloseParenToken);
      node = factoryCreateForOfStatement(awaitToken, initializer, expression, parseStatement());
    } else if (parseOptional(SyntaxKind.InKeyword)) {
      const expression = allowInAnd(parseExpression);
      parseExpected(SyntaxKind.CloseParenToken);
      node = factory.createForInStatement(initializer, expression, parseStatement());
    } else {
      parseExpected(SyntaxKind.SemicolonToken);
      const condition = token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.CloseParenToken ? allowInAnd(parseExpression) : void 0;
      parseExpected(SyntaxKind.SemicolonToken);
      const incrementor = token() !== SyntaxKind.CloseParenToken ? allowInAnd(parseExpression) : void 0;
      parseExpected(SyntaxKind.CloseParenToken);
      node = factoryCreateForStatement(initializer, condition, incrementor, parseStatement());
    }
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseBreakOrContinueStatement(kind) {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword);
    const label = canParseSemicolon() ? void 0 : parseIdentifier();
    parseSemicolon();
    const node = kind === SyntaxKind.BreakStatement ? factory.createBreakStatement(label) : factory.createContinueStatement(label);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseReturnStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.ReturnKeyword);
    const expression = canParseSemicolon() ? void 0 : allowInAnd(parseExpression);
    parseSemicolon();
    return withJSDoc(finishNode(factory.createReturnStatement(expression), pos), hasJSDoc);
  }
  function parseWithStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.WithKeyword);
    const openParenPosition = scanner.getTokenStart();
    const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
    const expression = allowInAnd(parseExpression);
    parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
    const statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement);
    return withJSDoc(finishNode(factory.createWithStatement(expression, statement), pos), hasJSDoc);
  }
  function parseCaseClause() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.CaseKeyword);
    const expression = allowInAnd(parseExpression);
    parseExpected(SyntaxKind.ColonToken);
    const statements = parseList(3 /* SwitchClauseStatements */, parseStatement);
    return withJSDoc(finishNode(factory.createCaseClause(expression, statements), pos), hasJSDoc);
  }
  function parseDefaultClause() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.DefaultKeyword);
    parseExpected(SyntaxKind.ColonToken);
    const statements = parseList(3 /* SwitchClauseStatements */, parseStatement);
    return finishNode(factory.createDefaultClause(statements), pos);
  }
  function parseCaseOrDefaultClause() {
    return token() === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause();
  }
  function parseCaseBlock() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.OpenBraceToken);
    const clauses = parseList(2 /* SwitchClauses */, parseCaseOrDefaultClause);
    parseExpected(SyntaxKind.CloseBraceToken);
    return finishNode(factory.createCaseBlock(clauses), pos);
  }
  function parseSwitchStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.SwitchKeyword);
    parseExpected(SyntaxKind.OpenParenToken);
    const expression = allowInAnd(parseExpression);
    parseExpected(SyntaxKind.CloseParenToken);
    const caseBlock = parseCaseBlock();
    return withJSDoc(finishNode(factory.createSwitchStatement(expression, caseBlock), pos), hasJSDoc);
  }
  function parseThrowStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.ThrowKeyword);
    let expression = scanner.hasPrecedingLineBreak() ? void 0 : allowInAnd(parseExpression);
    if (expression === void 0) {
      identifierCount++;
      expression = finishNode(factoryCreateIdentifier(""), getNodePos());
    }
    if (!tryParseSemicolon()) {
      parseErrorForMissingSemicolonAfter(expression);
    }
    return withJSDoc(finishNode(factory.createThrowStatement(expression), pos), hasJSDoc);
  }
  function parseTryStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.TryKeyword);
    const tryBlock = parseBlock(
      /*ignoreMissingOpenBrace*/
      false
    );
    const catchClause = token() === SyntaxKind.CatchKeyword ? parseCatchClause() : void 0;
    let finallyBlock;
    if (!catchClause || token() === SyntaxKind.FinallyKeyword) {
      parseExpected(SyntaxKind.FinallyKeyword, Diagnostics.catch_or_finally_expected);
      finallyBlock = parseBlock(
        /*ignoreMissingOpenBrace*/
        false
      );
    }
    return withJSDoc(finishNode(factory.createTryStatement(tryBlock, catchClause, finallyBlock), pos), hasJSDoc);
  }
  function parseCatchClause() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.CatchKeyword);
    let variableDeclaration;
    if (parseOptional(SyntaxKind.OpenParenToken)) {
      variableDeclaration = parseVariableDeclaration();
      parseExpected(SyntaxKind.CloseParenToken);
    } else {
      variableDeclaration = void 0;
    }
    const block = parseBlock(
      /*ignoreMissingOpenBrace*/
      false
    );
    return finishNode(factory.createCatchClause(variableDeclaration, block), pos);
  }
  function parseDebuggerStatement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    parseExpected(SyntaxKind.DebuggerKeyword);
    parseSemicolon();
    return withJSDoc(finishNode(factory.createDebuggerStatement(), pos), hasJSDoc);
  }
  function parseExpressionOrLabeledStatement() {
    const pos = getNodePos();
    let hasJSDoc = hasPrecedingJSDocComment();
    let node;
    const hasParen = token() === SyntaxKind.OpenParenToken;
    const expression = allowInAnd(parseExpression);
    if (isIdentifierNode(expression) && parseOptional(SyntaxKind.ColonToken)) {
      node = factory.createLabeledStatement(expression, parseStatement());
    } else {
      if (!tryParseSemicolon()) {
        parseErrorForMissingSemicolonAfter(expression);
      }
      node = factoryCreateExpressionStatement(expression);
      if (hasParen) {
        hasJSDoc = false;
      }
    }
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function nextTokenIsIdentifierOrKeywordOnSameLine() {
    nextToken();
    return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak();
  }
  function nextTokenIsClassKeywordOnSameLine() {
    nextToken();
    return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak();
  }
  function nextTokenIsFunctionKeywordOnSameLine() {
    nextToken();
    return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
  }
  function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() {
    nextToken();
    return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak();
  }
  function isDeclaration() {
    while (true) {
      switch (token()) {
        case SyntaxKind.VarKeyword:
        case SyntaxKind.LetKeyword:
        case SyntaxKind.ConstKeyword:
        case SyntaxKind.FunctionKeyword:
        case SyntaxKind.ClassKeyword:
        case SyntaxKind.EnumKeyword:
          return true;
        case SyntaxKind.UsingKeyword:
          return isUsingDeclaration();
        case SyntaxKind.AwaitKeyword:
          return isAwaitUsingDeclaration();
        // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers;
        // however, an identifier cannot be followed by another identifier on the same line. This is what we
        // count on to parse out the respective declarations. For instance, we exploit this to say that
        //
        //    namespace n
        //
        // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees
        //
        //    namespace
        //    n
        //
        // as the identifier 'namespace' on one line followed by the identifier 'n' on another.
        // We need to look one token ahead to see if it permissible to try parsing a declaration.
        //
        // *Note*: 'interface' is actually a strict mode reserved word. So while
        //
        //   "use strict"
        //   interface
        //   I {}
        //
        // could be legal, it would add complexity for very little gain.
        case SyntaxKind.InterfaceKeyword:
        case SyntaxKind.TypeKeyword:
          return nextTokenIsIdentifierOnSameLine();
        case SyntaxKind.ModuleKeyword:
        case SyntaxKind.NamespaceKeyword:
          return nextTokenIsIdentifierOrStringLiteralOnSameLine();
        case SyntaxKind.AbstractKeyword:
        case SyntaxKind.AccessorKeyword:
        case SyntaxKind.AsyncKeyword:
        case SyntaxKind.DeclareKeyword:
        case SyntaxKind.PrivateKeyword:
        case SyntaxKind.ProtectedKeyword:
        case SyntaxKind.PublicKeyword:
        case SyntaxKind.ReadonlyKeyword:
          const previousToken = token();
          nextToken();
          if (scanner.hasPrecedingLineBreak()) {
            return false;
          }
          if (previousToken === SyntaxKind.DeclareKeyword && token() === SyntaxKind.TypeKeyword) {
            return true;
          }
          continue;
        case SyntaxKind.GlobalKeyword:
          nextToken();
          return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.Identifier || token() === SyntaxKind.ExportKeyword;
        case SyntaxKind.ImportKeyword:
          nextToken();
          return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token());
        case SyntaxKind.ExportKeyword:
          let currentToken2 = nextToken();
          if (currentToken2 === SyntaxKind.TypeKeyword) {
            currentToken2 = lookAhead(nextToken);
          }
          if (currentToken2 === SyntaxKind.EqualsToken || currentToken2 === SyntaxKind.AsteriskToken || currentToken2 === SyntaxKind.OpenBraceToken || currentToken2 === SyntaxKind.DefaultKeyword || currentToken2 === SyntaxKind.AsKeyword || currentToken2 === SyntaxKind.AtToken) {
            return true;
          }
          continue;
        case SyntaxKind.StaticKeyword:
          nextToken();
          continue;
        default:
          return false;
      }
    }
  }
  function isStartOfDeclaration() {
    return lookAhead(isDeclaration);
  }
  function isStartOfStatement() {
    switch (token()) {
      case SyntaxKind.AtToken:
      case SyntaxKind.SemicolonToken:
      case SyntaxKind.OpenBraceToken:
      case SyntaxKind.VarKeyword:
      case SyntaxKind.LetKeyword:
      case SyntaxKind.UsingKeyword:
      case SyntaxKind.FunctionKeyword:
      case SyntaxKind.ClassKeyword:
      case SyntaxKind.EnumKeyword:
      case SyntaxKind.IfKeyword:
      case SyntaxKind.DoKeyword:
      case SyntaxKind.WhileKeyword:
      case SyntaxKind.ForKeyword:
      case SyntaxKind.ContinueKeyword:
      case SyntaxKind.BreakKeyword:
      case SyntaxKind.ReturnKeyword:
      case SyntaxKind.WithKeyword:
      case SyntaxKind.SwitchKeyword:
      case SyntaxKind.ThrowKeyword:
      case SyntaxKind.TryKeyword:
      case SyntaxKind.DebuggerKeyword:
      // 'catch' and 'finally' do not actually indicate that the code is part of a statement,
      // however, we say they are here so that we may gracefully parse them and error later.
      // falls through
      case SyntaxKind.CatchKeyword:
      case SyntaxKind.FinallyKeyword:
        return true;
      case SyntaxKind.ImportKeyword:
        return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot);
      case SyntaxKind.ConstKeyword:
      case SyntaxKind.ExportKeyword:
        return isStartOfDeclaration();
      case SyntaxKind.AsyncKeyword:
      case SyntaxKind.DeclareKeyword:
      case SyntaxKind.InterfaceKeyword:
      case SyntaxKind.ModuleKeyword:
      case SyntaxKind.NamespaceKeyword:
      case SyntaxKind.TypeKeyword:
      case SyntaxKind.GlobalKeyword:
        return true;
      case SyntaxKind.AccessorKeyword:
      case SyntaxKind.PublicKeyword:
      case SyntaxKind.PrivateKeyword:
      case SyntaxKind.ProtectedKeyword:
      case SyntaxKind.StaticKeyword:
      case SyntaxKind.ReadonlyKeyword:
        return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
      default:
        return isStartOfExpression();
    }
  }
  function nextTokenIsBindingIdentifierOrStartOfDestructuring() {
    nextToken();
    return isBindingIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken;
  }
  function isLetDeclaration() {
    return lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuring);
  }
  function nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLineDisallowOf() {
    return nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLine(
      /*disallowOf*/
      true
    );
  }
  function nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLine(disallowOf) {
    nextToken();
    if (disallowOf && token() === SyntaxKind.OfKeyword) return false;
    return (isBindingIdentifier() || token() === SyntaxKind.OpenBraceToken) && !scanner.hasPrecedingLineBreak();
  }
  function isUsingDeclaration() {
    return lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLine);
  }
  function nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLineDisallowOf() {
    return nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLine(
      /*disallowOf*/
      true
    );
  }
  function nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLine(disallowOf) {
    if (nextToken() === SyntaxKind.UsingKeyword) {
      return nextTokenIsBindingIdentifierOrStartOfDestructuringOnSameLine(disallowOf);
    }
    return false;
  }
  function isAwaitUsingDeclaration() {
    return lookAhead(nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLine);
  }
  function parseStatement() {
    switch (token()) {
      case SyntaxKind.SemicolonToken:
        return parseEmptyStatement();
      case SyntaxKind.OpenBraceToken:
        return parseBlock(
          /*ignoreMissingOpenBrace*/
          false
        );
      case SyntaxKind.VarKeyword:
        return parseVariableStatement(
          getNodePos(),
          hasPrecedingJSDocComment(),
          /*modifiers*/
          void 0
        );
      case SyntaxKind.LetKeyword:
        if (isLetDeclaration()) {
          return parseVariableStatement(
            getNodePos(),
            hasPrecedingJSDocComment(),
            /*modifiers*/
            void 0
          );
        }
        break;
      case SyntaxKind.AwaitKeyword:
        if (isAwaitUsingDeclaration()) {
          return parseVariableStatement(
            getNodePos(),
            hasPrecedingJSDocComment(),
            /*modifiers*/
            void 0
          );
        }
        break;
      case SyntaxKind.UsingKeyword:
        if (isUsingDeclaration()) {
          return parseVariableStatement(
            getNodePos(),
            hasPrecedingJSDocComment(),
            /*modifiers*/
            void 0
          );
        }
        break;
      case SyntaxKind.FunctionKeyword:
        return parseFunctionDeclaration(
          getNodePos(),
          hasPrecedingJSDocComment(),
          /*modifiers*/
          void 0
        );
      case SyntaxKind.ClassKeyword:
        return parseClassDeclaration(
          getNodePos(),
          hasPrecedingJSDocComment(),
          /*modifiers*/
          void 0
        );
      case SyntaxKind.IfKeyword:
        return parseIfStatement();
      case SyntaxKind.DoKeyword:
        return parseDoStatement();
      case SyntaxKind.WhileKeyword:
        return parseWhileStatement();
      case SyntaxKind.ForKeyword:
        return parseForOrForInOrForOfStatement();
      case SyntaxKind.ContinueKeyword:
        return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);
      case SyntaxKind.BreakKeyword:
        return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);
      case SyntaxKind.ReturnKeyword:
        return parseReturnStatement();
      case SyntaxKind.WithKeyword:
        return parseWithStatement();
      case SyntaxKind.SwitchKeyword:
        return parseSwitchStatement();
      case SyntaxKind.ThrowKeyword:
        return parseThrowStatement();
      case SyntaxKind.TryKeyword:
      // Include 'catch' and 'finally' for error recovery.
      // falls through
      case SyntaxKind.CatchKeyword:
      case SyntaxKind.FinallyKeyword:
        return parseTryStatement();
      case SyntaxKind.DebuggerKeyword:
        return parseDebuggerStatement();
      case SyntaxKind.AtToken:
        return parseDeclaration();
      case SyntaxKind.AsyncKeyword:
      case SyntaxKind.InterfaceKeyword:
      case SyntaxKind.TypeKeyword:
      case SyntaxKind.ModuleKeyword:
      case SyntaxKind.NamespaceKeyword:
      case SyntaxKind.DeclareKeyword:
      case SyntaxKind.ConstKeyword:
      case SyntaxKind.EnumKeyword:
      case SyntaxKind.ExportKeyword:
      case SyntaxKind.ImportKeyword:
      case SyntaxKind.PrivateKeyword:
      case SyntaxKind.ProtectedKeyword:
      case SyntaxKind.PublicKeyword:
      case SyntaxKind.AbstractKeyword:
      case SyntaxKind.AccessorKeyword:
      case SyntaxKind.StaticKeyword:
      case SyntaxKind.ReadonlyKeyword:
      case SyntaxKind.GlobalKeyword:
        if (isStartOfDeclaration()) {
          return parseDeclaration();
        }
        break;
    }
    return parseExpressionOrLabeledStatement();
  }
  function isDeclareModifier(modifier) {
    return modifier.kind === SyntaxKind.DeclareKeyword;
  }
  function parseDeclaration() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const modifiers = parseModifiers(
      /*allowDecorators*/
      true
    );
    const isAmbient = some(modifiers, isDeclareModifier);
    if (isAmbient) {
      const node = tryReuseAmbientDeclaration(pos);
      if (node) {
        return node;
      }
      for (const m of modifiers) {
        m.flags |= NodeFlags.Ambient;
      }
      return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, modifiers));
    } else {
      return parseDeclarationWorker(pos, hasJSDoc, modifiers);
    }
  }
  function tryReuseAmbientDeclaration(pos) {
    return doInsideOfContext(NodeFlags.Ambient, () => {
      const node = currentNode(parsingContext, pos);
      if (node) {
        return consumeNode(node);
      }
    });
  }
  function parseDeclarationWorker(pos, hasJSDoc, modifiersIn) {
    switch (token()) {
      case SyntaxKind.VarKeyword:
      case SyntaxKind.LetKeyword:
      case SyntaxKind.ConstKeyword:
      case SyntaxKind.UsingKeyword:
      case SyntaxKind.AwaitKeyword:
        return parseVariableStatement(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.FunctionKeyword:
        return parseFunctionDeclaration(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.ClassKeyword:
        return parseClassDeclaration(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.InterfaceKeyword:
        return parseInterfaceDeclaration(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.TypeKeyword:
        return parseTypeAliasDeclaration(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.EnumKeyword:
        return parseEnumDeclaration(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.GlobalKeyword:
      case SyntaxKind.ModuleKeyword:
      case SyntaxKind.NamespaceKeyword:
        return parseModuleDeclaration(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.ImportKeyword:
        return parseImportDeclarationOrImportEqualsDeclaration(pos, hasJSDoc, modifiersIn);
      case SyntaxKind.ExportKeyword:
        nextToken();
        switch (token()) {
          case SyntaxKind.DefaultKeyword:
          case SyntaxKind.EqualsToken:
            return parseExportAssignment(pos, hasJSDoc, modifiersIn);
          case SyntaxKind.AsKeyword:
            return parseNamespaceExportDeclaration(pos, hasJSDoc, modifiersIn);
          default:
            return parseExportDeclaration(pos, hasJSDoc, modifiersIn);
        }
      default:
        if (modifiersIn) {
          const missing = createMissingNode(
            SyntaxKind.MissingDeclaration,
            /*reportAtCurrentPosition*/
            true,
            Diagnostics.Declaration_expected
          );
          setTextRangePos(missing, pos);
          missing.modifiers = modifiersIn;
          return missing;
        }
        return void 0;
    }
  }
  function nextTokenIsStringLiteral() {
    return nextToken() === SyntaxKind.StringLiteral;
  }
  function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
    nextToken();
    return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral);
  }
  function parseFunctionBlockOrSemicolon(flags, diagnosticMessage) {
    if (token() !== SyntaxKind.OpenBraceToken) {
      if (flags & 4 /* Type */) {
        parseTypeMemberSemicolon();
        return;
      }
      if (canParseSemicolon()) {
        parseSemicolon();
        return;
      }
    }
    return parseFunctionBlock(flags, diagnosticMessage);
  }
  function parseArrayBindingElement() {
    const pos = getNodePos();
    if (token() === SyntaxKind.CommaToken) {
      return finishNode(factory.createOmittedExpression(), pos);
    }
    const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
    const name = parseIdentifierOrPattern();
    const initializer = parseInitializer();
    return finishNode(factory.createBindingElement(
      dotDotDotToken,
      /*propertyName*/
      void 0,
      name,
      initializer
    ), pos);
  }
  function parseObjectBindingElement() {
    const pos = getNodePos();
    const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
    const tokenIsIdentifier = isBindingIdentifier();
    let propertyName = parsePropertyName();
    let name;
    if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) {
      name = propertyName;
      propertyName = void 0;
    } else {
      parseExpected(SyntaxKind.ColonToken);
      name = parseIdentifierOrPattern();
    }
    const initializer = parseInitializer();
    return finishNode(factory.createBindingElement(dotDotDotToken, propertyName, name, initializer), pos);
  }
  function parseObjectBindingPattern() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.OpenBraceToken);
    const elements = allowInAnd(() => parseDelimitedList(9 /* ObjectBindingElements */, parseObjectBindingElement));
    parseExpected(SyntaxKind.CloseBraceToken);
    return finishNode(factory.createObjectBindingPattern(elements), pos);
  }
  function parseArrayBindingPattern() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.OpenBracketToken);
    const elements = allowInAnd(() => parseDelimitedList(10 /* ArrayBindingElements */, parseArrayBindingElement));
    parseExpected(SyntaxKind.CloseBracketToken);
    return finishNode(factory.createArrayBindingPattern(elements), pos);
  }
  function isBindingIdentifierOrPrivateIdentifierOrPattern() {
    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.PrivateIdentifier || isBindingIdentifier();
  }
  function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage) {
    if (token() === SyntaxKind.OpenBracketToken) {
      return parseArrayBindingPattern();
    }
    if (token() === SyntaxKind.OpenBraceToken) {
      return parseObjectBindingPattern();
    }
    return parseBindingIdentifier(privateIdentifierDiagnosticMessage);
  }
  function parseVariableDeclarationAllowExclamation() {
    return parseVariableDeclaration(
      /*allowExclamation*/
      true
    );
  }
  function parseVariableDeclaration(allowExclamation) {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations);
    let exclamationToken;
    if (allowExclamation && name.kind === SyntaxKind.Identifier && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
      exclamationToken = parseTokenNode();
    }
    const type = parseTypeAnnotation();
    const initializer = isInOrOfKeyword(token()) ? void 0 : parseInitializer();
    const node = factoryCreateVariableDeclaration(name, exclamationToken, type, initializer);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseVariableDeclarationList(inForStatementInitializer) {
    const pos = getNodePos();
    let flags = 0;
    switch (token()) {
      case SyntaxKind.VarKeyword:
        break;
      case SyntaxKind.LetKeyword:
        flags |= NodeFlags.Let;
        break;
      case SyntaxKind.ConstKeyword:
        flags |= NodeFlags.Const;
        break;
      case SyntaxKind.UsingKeyword:
        flags |= NodeFlags.Using;
        break;
      case SyntaxKind.AwaitKeyword:
        Debug.assert(isAwaitUsingDeclaration());
        flags |= NodeFlags.AwaitUsing;
        nextToken();
        break;
      default:
        Debug.fail();
    }
    nextToken();
    let declarations;
    if (token() === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) {
      declarations = createMissingList();
    } else {
      const savedDisallowIn = inDisallowInContext();
      setDisallowInContext(inForStatementInitializer);
      declarations = parseDelimitedList(
        8 /* VariableDeclarations */,
        inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation
      );
      setDisallowInContext(savedDisallowIn);
    }
    return finishNode(factoryCreateVariableDeclarationList(declarations, flags), pos);
  }
  function canFollowContextualOfKeyword() {
    return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken;
  }
  function parseVariableStatement(pos, hasJSDoc, modifiers) {
    const declarationList = parseVariableDeclarationList(
      /*inForStatementInitializer*/
      false
    );
    parseSemicolon();
    const node = factoryCreateVariableStatement(modifiers, declarationList);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseFunctionDeclaration(pos, hasJSDoc, modifiers) {
    const savedAwaitContext = inAwaitContext();
    const modifierFlags = modifiersToFlags(modifiers);
    parseExpected(SyntaxKind.FunctionKeyword);
    const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
    const name = modifierFlags & ModifierFlags.Default ? parseOptionalBindingIdentifier() : parseBindingIdentifier();
    const isGenerator = asteriskToken ? 1 /* Yield */ : 0 /* None */;
    const isAsync = modifierFlags & ModifierFlags.Async ? 2 /* Await */ : 0 /* None */;
    const typeParameters = parseTypeParameters();
    if (modifierFlags & ModifierFlags.Export) setAwaitContext(
      /*value*/
      true
    );
    const parameters = parseParameters(isGenerator | isAsync);
    const type = parseReturnType(
      SyntaxKind.ColonToken,
      /*isType*/
      false
    );
    const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected);
    setAwaitContext(savedAwaitContext);
    const node = factory.createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseConstructorName() {
    if (token() === SyntaxKind.ConstructorKeyword) {
      return parseExpected(SyntaxKind.ConstructorKeyword);
    }
    if (token() === SyntaxKind.StringLiteral && lookAhead(nextToken) === SyntaxKind.OpenParenToken) {
      return tryParse(() => {
        const literalNode = parseLiteralNode();
        return literalNode.text === "constructor" ? literalNode : void 0;
      });
    }
  }
  function tryParseConstructorDeclaration(pos, hasJSDoc, modifiers) {
    return tryParse(() => {
      if (parseConstructorName()) {
        const typeParameters = parseTypeParameters();
        const parameters = parseParameters(0 /* None */);
        const type = parseReturnType(
          SyntaxKind.ColonToken,
          /*isType*/
          false
        );
        const body = parseFunctionBlockOrSemicolon(0 /* None */, Diagnostics.or_expected);
        const node = factory.createConstructorDeclaration(modifiers, parameters, body);
        node.typeParameters = typeParameters;
        node.type = type;
        return withJSDoc(finishNode(node, pos), hasJSDoc);
      }
    });
  }
  function parseMethodDeclaration(pos, hasJSDoc, modifiers, asteriskToken, name, questionToken, exclamationToken, diagnosticMessage) {
    const isGenerator = asteriskToken ? 1 /* Yield */ : 0 /* None */;
    const isAsync = some(modifiers, isAsyncModifier) ? 2 /* Await */ : 0 /* None */;
    const typeParameters = parseTypeParameters();
    const parameters = parseParameters(isGenerator | isAsync);
    const type = parseReturnType(
      SyntaxKind.ColonToken,
      /*isType*/
      false
    );
    const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage);
    const node = factory.createMethodDeclaration(
      modifiers,
      asteriskToken,
      name,
      questionToken,
      typeParameters,
      parameters,
      type,
      body
    );
    node.exclamationToken = exclamationToken;
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parsePropertyDeclaration(pos, hasJSDoc, modifiers, name, questionToken) {
    const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(SyntaxKind.ExclamationToken) : void 0;
    const type = parseTypeAnnotation();
    const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer);
    parseSemicolonAfterPropertyName(name, type, initializer);
    const node = factory.createPropertyDeclaration(
      modifiers,
      name,
      questionToken || exclamationToken,
      type,
      initializer
    );
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parsePropertyOrMethodDeclaration(pos, hasJSDoc, modifiers) {
    const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
    const name = parsePropertyName();
    const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
    if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
      return parseMethodDeclaration(
        pos,
        hasJSDoc,
        modifiers,
        asteriskToken,
        name,
        questionToken,
        /*exclamationToken*/
        void 0,
        Diagnostics.or_expected
      );
    }
    return parsePropertyDeclaration(pos, hasJSDoc, modifiers, name, questionToken);
  }
  function parseAccessorDeclaration(pos, hasJSDoc, modifiers, kind, flags) {
    const name = parsePropertyName();
    const typeParameters = parseTypeParameters();
    const parameters = parseParameters(0 /* None */);
    const type = parseReturnType(
      SyntaxKind.ColonToken,
      /*isType*/
      false
    );
    const body = parseFunctionBlockOrSemicolon(flags);
    const node = kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(modifiers, name, parameters, type, body) : factory.createSetAccessorDeclaration(modifiers, name, parameters, body);
    node.typeParameters = typeParameters;
    if (isSetAccessorDeclaration(node)) node.type = type;
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function isClassMemberStart() {
    let idToken;
    if (token() === SyntaxKind.AtToken) {
      return true;
    }
    while (isModifierKind(token())) {
      idToken = token();
      if (isClassMemberModifier(idToken)) {
        return true;
      }
      nextToken();
    }
    if (token() === SyntaxKind.AsteriskToken) {
      return true;
    }
    if (isLiteralPropertyName()) {
      idToken = token();
      nextToken();
    }
    if (token() === SyntaxKind.OpenBracketToken) {
      return true;
    }
    if (idToken !== void 0) {
      if (!isKeyword(idToken) || idToken === SyntaxKind.SetKeyword || idToken === SyntaxKind.GetKeyword) {
        return true;
      }
      switch (token()) {
        case SyntaxKind.OpenParenToken:
        // Method declaration
        case SyntaxKind.LessThanToken:
        // Generic Method declaration
        case SyntaxKind.ExclamationToken:
        // Non-null assertion on property name
        case SyntaxKind.ColonToken:
        // Type Annotation for declaration
        case SyntaxKind.EqualsToken:
        // Initializer for declaration
        case SyntaxKind.QuestionToken:
          return true;
        default:
          return canParseSemicolon();
      }
    }
    return false;
  }
  function parseClassStaticBlockDeclaration(pos, hasJSDoc, modifiers) {
    parseExpectedToken(SyntaxKind.StaticKeyword);
    const body = parseClassStaticBlockBody();
    const node = withJSDoc(finishNode(factory.createClassStaticBlockDeclaration(body), pos), hasJSDoc);
    node.modifiers = modifiers;
    return node;
  }
  function parseClassStaticBlockBody() {
    const savedYieldContext = inYieldContext();
    const savedAwaitContext = inAwaitContext();
    setYieldContext(false);
    setAwaitContext(true);
    const body = parseBlock(
      /*ignoreMissingOpenBrace*/
      false
    );
    setYieldContext(savedYieldContext);
    setAwaitContext(savedAwaitContext);
    return body;
  }
  function parseDecoratorExpression() {
    if (inAwaitContext() && token() === SyntaxKind.AwaitKeyword) {
      const pos = getNodePos();
      const awaitExpression = parseIdentifier(Diagnostics.Expression_expected);
      nextToken();
      const memberExpression = parseMemberExpressionRest(
        pos,
        awaitExpression,
        /*allowOptionalChain*/
        true
      );
      return parseCallExpressionRest(pos, memberExpression);
    }
    return parseLeftHandSideExpressionOrHigher();
  }
  function tryParseDecorator() {
    const pos = getNodePos();
    if (!parseOptional(SyntaxKind.AtToken)) {
      return void 0;
    }
    const expression = doInDecoratorContext(parseDecoratorExpression);
    return finishNode(factory.createDecorator(expression), pos);
  }
  function tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock) {
    const pos = getNodePos();
    const kind = token();
    if (token() === SyntaxKind.ConstKeyword && permitConstAsModifier) {
      if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) {
        return void 0;
      }
    } else if (stopOnStartOfClassStaticBlock && token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) {
      return void 0;
    } else if (hasSeenStaticModifier && token() === SyntaxKind.StaticKeyword) {
      return void 0;
    } else {
      if (!parseAnyContextualModifier()) {
        return void 0;
      }
    }
    return finishNode(factoryCreateToken(kind), pos);
  }
  function parseModifiers(allowDecorators, permitConstAsModifier, stopOnStartOfClassStaticBlock) {
    const pos = getNodePos();
    let list;
    let decorator, modifier, hasSeenStaticModifier = false, hasLeadingModifier = false, hasTrailingDecorator = false;
    if (allowDecorators && token() === SyntaxKind.AtToken) {
      while (decorator = tryParseDecorator()) {
        list = append(list, decorator);
      }
    }
    while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock)) {
      if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStaticModifier = true;
      list = append(list, modifier);
      hasLeadingModifier = true;
    }
    if (hasLeadingModifier && allowDecorators && token() === SyntaxKind.AtToken) {
      while (decorator = tryParseDecorator()) {
        list = append(list, decorator);
        hasTrailingDecorator = true;
      }
    }
    if (hasTrailingDecorator) {
      while (modifier = tryParseModifier(hasSeenStaticModifier, permitConstAsModifier, stopOnStartOfClassStaticBlock)) {
        if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStaticModifier = true;
        list = append(list, modifier);
      }
    }
    return list && createNodeArray(list, pos);
  }
  function parseModifiersForArrowFunction() {
    let modifiers;
    if (token() === SyntaxKind.AsyncKeyword) {
      const pos = getNodePos();
      nextToken();
      const modifier = finishNode(factoryCreateToken(SyntaxKind.AsyncKeyword), pos);
      modifiers = createNodeArray([modifier], pos);
    }
    return modifiers;
  }
  function parseClassElement() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    if (token() === SyntaxKind.SemicolonToken) {
      nextToken();
      return withJSDoc(finishNode(factory.createSemicolonClassElement(), pos), hasJSDoc);
    }
    const modifiers = parseModifiers(
      /*allowDecorators*/
      true,
      /*permitConstAsModifier*/
      true,
      /*stopOnStartOfClassStaticBlock*/
      true
    );
    if (token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) {
      return parseClassStaticBlockDeclaration(pos, hasJSDoc, modifiers);
    }
    if (parseContextualModifier(SyntaxKind.GetKeyword)) {
      return parseAccessorDeclaration(pos, hasJSDoc, modifiers, SyntaxKind.GetAccessor, 0 /* None */);
    }
    if (parseContextualModifier(SyntaxKind.SetKeyword)) {
      return parseAccessorDeclaration(pos, hasJSDoc, modifiers, SyntaxKind.SetAccessor, 0 /* None */);
    }
    if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) {
      const constructorDeclaration = tryParseConstructorDeclaration(pos, hasJSDoc, modifiers);
      if (constructorDeclaration) {
        return constructorDeclaration;
      }
    }
    if (isIndexSignature()) {
      return parseIndexSignatureDeclaration(pos, hasJSDoc, modifiers);
    }
    if (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBracketToken) {
      const isAmbient = some(modifiers, isDeclareModifier);
      if (isAmbient) {
        for (const m of modifiers) {
          m.flags |= NodeFlags.Ambient;
        }
        return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, modifiers));
      } else {
        return parsePropertyOrMethodDeclaration(pos, hasJSDoc, modifiers);
      }
    }
    if (modifiers) {
      const name = createMissingNode(
        SyntaxKind.Identifier,
        /*reportAtCurrentPosition*/
        true,
        Diagnostics.Declaration_expected
      );
      return parsePropertyDeclaration(
        pos,
        hasJSDoc,
        modifiers,
        name,
        /*questionToken*/
        void 0
      );
    }
    return Debug.fail("Should not have attempted to parse class member declaration.");
  }
  function parseDecoratedExpression() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const modifiers = parseModifiers(
      /*allowDecorators*/
      true
    );
    if (token() === SyntaxKind.ClassKeyword) {
      return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassExpression);
    }
    const missing = createMissingNode(
      SyntaxKind.MissingDeclaration,
      /*reportAtCurrentPosition*/
      true,
      Diagnostics.Expression_expected
    );
    setTextRangePos(missing, pos);
    missing.modifiers = modifiers;
    return missing;
  }
  function parseClassExpression() {
    return parseClassDeclarationOrExpression(
      getNodePos(),
      hasPrecedingJSDocComment(),
      /*modifiers*/
      void 0,
      SyntaxKind.ClassExpression
    );
  }
  function parseClassDeclaration(pos, hasJSDoc, modifiers) {
    return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassDeclaration);
  }
  function parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, kind) {
    const savedAwaitContext = inAwaitContext();
    parseExpected(SyntaxKind.ClassKeyword);
    const name = parseNameOfClassDeclarationOrExpression();
    const typeParameters = parseTypeParameters();
    if (some(modifiers, isExportModifier)) setAwaitContext(
      /*value*/
      true
    );
    const heritageClauses = parseHeritageClauses();
    let members;
    if (parseExpected(SyntaxKind.OpenBraceToken)) {
      members = parseClassMembers();
      parseExpected(SyntaxKind.CloseBraceToken);
    } else {
      members = createMissingList();
    }
    setAwaitContext(savedAwaitContext);
    const node = kind === SyntaxKind.ClassDeclaration ? factory.createClassDeclaration(modifiers, name, typeParameters, heritageClauses, members) : factory.createClassExpression(modifiers, name, typeParameters, heritageClauses, members);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseNameOfClassDeclarationOrExpression() {
    return isBindingIdentifier() && !isImplementsClause() ? createIdentifier(isBindingIdentifier()) : void 0;
  }
  function isImplementsClause() {
    return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword);
  }
  function parseHeritageClauses() {
    if (isHeritageClause()) {
      return parseList(22 /* HeritageClauses */, parseHeritageClause);
    }
    return void 0;
  }
  function parseHeritageClause() {
    const pos = getNodePos();
    const tok = token();
    Debug.assert(tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword);
    nextToken();
    const types = parseDelimitedList(7 /* HeritageClauseElement */, parseExpressionWithTypeArguments);
    return finishNode(factory.createHeritageClause(tok, types), pos);
  }
  function parseExpressionWithTypeArguments() {
    const pos = getNodePos();
    const expression = parseLeftHandSideExpressionOrHigher();
    if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) {
      return expression;
    }
    const typeArguments = tryParseTypeArguments();
    return finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos);
  }
  function tryParseTypeArguments() {
    return token() === SyntaxKind.LessThanToken ? parseBracketedList(20 /* TypeArguments */, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken) : void 0;
  }
  function isHeritageClause() {
    return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
  }
  function parseClassMembers() {
    return parseList(5 /* ClassMembers */, parseClassElement);
  }
  function parseInterfaceDeclaration(pos, hasJSDoc, modifiers) {
    parseExpected(SyntaxKind.InterfaceKeyword);
    const name = parseIdentifier();
    const typeParameters = parseTypeParameters();
    const heritageClauses = parseHeritageClauses();
    const members = parseObjectTypeMembers();
    const node = factory.createInterfaceDeclaration(modifiers, name, typeParameters, heritageClauses, members);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseTypeAliasDeclaration(pos, hasJSDoc, modifiers) {
    parseExpected(SyntaxKind.TypeKeyword);
    if (scanner.hasPrecedingLineBreak()) {
      parseErrorAtCurrentToken(Diagnostics.Line_break_not_permitted_here);
    }
    const name = parseIdentifier();
    const typeParameters = parseTypeParameters();
    parseExpected(SyntaxKind.EqualsToken);
    const type = token() === SyntaxKind.IntrinsicKeyword && tryParse(parseKeywordAndNoDot) || parseType();
    parseSemicolon();
    const node = factory.createTypeAliasDeclaration(modifiers, name, typeParameters, type);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseEnumMember() {
    const pos = getNodePos();
    const hasJSDoc = hasPrecedingJSDocComment();
    const name = parsePropertyName();
    const initializer = allowInAnd(parseInitializer);
    return withJSDoc(finishNode(factory.createEnumMember(name, initializer), pos), hasJSDoc);
  }
  function parseEnumDeclaration(pos, hasJSDoc, modifiers) {
    parseExpected(SyntaxKind.EnumKeyword);
    const name = parseIdentifier();
    let members;
    if (parseExpected(SyntaxKind.OpenBraceToken)) {
      members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(6 /* EnumMembers */, parseEnumMember));
      parseExpected(SyntaxKind.CloseBraceToken);
    } else {
      members = createMissingList();
    }
    const node = factory.createEnumDeclaration(modifiers, name, members);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseModuleBlock() {
    const pos = getNodePos();
    let statements;
    if (parseExpected(SyntaxKind.OpenBraceToken)) {
      statements = parseList(1 /* BlockStatements */, parseStatement);
      parseExpected(SyntaxKind.CloseBraceToken);
    } else {
      statements = createMissingList();
    }
    return finishNode(factory.createModuleBlock(statements), pos);
  }
  function parseModuleOrNamespaceDeclaration(pos, hasJSDoc, modifiers, flags) {
    const namespaceFlag = flags & NodeFlags.Namespace;
    const name = flags & NodeFlags.NestedNamespace ? parseIdentifierName() : parseIdentifier();
    const body = parseOptional(SyntaxKind.DotToken) ? parseModuleOrNamespaceDeclaration(
      getNodePos(),
      /*hasJSDoc*/
      false,
      /*modifiers*/
      void 0,
      NodeFlags.NestedNamespace | namespaceFlag
    ) : parseModuleBlock();
    const node = factory.createModuleDeclaration(modifiers, name, body, flags);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseAmbientExternalModuleDeclaration(pos, hasJSDoc, modifiersIn) {
    let flags = 0;
    let name;
    if (token() === SyntaxKind.GlobalKeyword) {
      name = parseIdentifier();
      flags |= NodeFlags.GlobalAugmentation;
    } else {
      name = parseLiteralNode();
      name.text = internIdentifier(name.text);
    }
    let body;
    if (token() === SyntaxKind.OpenBraceToken) {
      body = parseModuleBlock();
    } else {
      parseSemicolon();
    }
    const node = factory.createModuleDeclaration(modifiersIn, name, body, flags);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseModuleDeclaration(pos, hasJSDoc, modifiersIn) {
    let flags = 0;
    if (token() === SyntaxKind.GlobalKeyword) {
      return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, modifiersIn);
    } else if (parseOptional(SyntaxKind.NamespaceKeyword)) {
      flags |= NodeFlags.Namespace;
    } else {
      parseExpected(SyntaxKind.ModuleKeyword);
      if (token() === SyntaxKind.StringLiteral) {
        return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, modifiersIn);
      }
    }
    return parseModuleOrNamespaceDeclaration(pos, hasJSDoc, modifiersIn, flags);
  }
  function isExternalModuleReference2() {
    return token() === SyntaxKind.RequireKeyword && lookAhead(nextTokenIsOpenParen);
  }
  function nextTokenIsOpenParen() {
    return nextToken() === SyntaxKind.OpenParenToken;
  }
  function nextTokenIsOpenBrace() {
    return nextToken() === SyntaxKind.OpenBraceToken;
  }
  function nextTokenIsSlash() {
    return nextToken() === SyntaxKind.SlashToken;
  }
  function parseNamespaceExportDeclaration(pos, hasJSDoc, modifiers) {
    parseExpected(SyntaxKind.AsKeyword);
    parseExpected(SyntaxKind.NamespaceKeyword);
    const name = parseIdentifier();
    parseSemicolon();
    const node = factory.createNamespaceExportDeclaration(name);
    node.modifiers = modifiers;
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseImportDeclarationOrImportEqualsDeclaration(pos, hasJSDoc, modifiers) {
    parseExpected(SyntaxKind.ImportKeyword);
    const afterImportPos = scanner.getTokenFullStart();
    let identifier;
    if (isIdentifier()) {
      identifier = parseIdentifier();
    }
    let isTypeOnly = false;
    if (token() !== SyntaxKind.FromKeyword && identifier?.escapedText === "type" && (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration())) {
      isTypeOnly = true;
      identifier = isIdentifier() ? parseIdentifier() : void 0;
    }
    if (identifier && !tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration()) {
      return parseImportEqualsDeclaration(pos, hasJSDoc, modifiers, identifier, isTypeOnly);
    }
    let importClause;
    if (identifier || // import id
    token() === SyntaxKind.AsteriskToken || // import *
    token() === SyntaxKind.OpenBraceToken) {
      importClause = parseImportClause(identifier, afterImportPos, isTypeOnly);
      parseExpected(SyntaxKind.FromKeyword);
    }
    const moduleSpecifier = parseModuleSpecifier();
    const currentToken2 = token();
    let attributes;
    if ((currentToken2 === SyntaxKind.WithKeyword || currentToken2 === SyntaxKind.AssertKeyword) && !scanner.hasPrecedingLineBreak()) {
      attributes = parseImportAttributes(currentToken2);
    }
    parseSemicolon();
    const node = factory.createImportDeclaration(modifiers, importClause, moduleSpecifier, attributes);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseImportAttribute() {
    const pos = getNodePos();
    const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral);
    parseExpected(SyntaxKind.ColonToken);
    const value = parseAssignmentExpressionOrHigher(
      /*allowReturnTypeInArrowFunction*/
      true
    );
    return finishNode(factory.createImportAttribute(name, value), pos);
  }
  function parseImportAttributes(token2, skipKeyword) {
    const pos = getNodePos();
    if (!skipKeyword) {
      parseExpected(token2);
    }
    const openBracePosition = scanner.getTokenStart();
    if (parseExpected(SyntaxKind.OpenBraceToken)) {
      const multiLine = scanner.hasPrecedingLineBreak();
      const elements = parseDelimitedList(
        24 /* ImportAttributes */,
        parseImportAttribute,
        /*considerSemicolonAsDelimiter*/
        true
      );
      if (!parseExpected(SyntaxKind.CloseBraceToken)) {
        const lastError = lastOrUndefined(parseDiagnostics);
        if (lastError && lastError.code === Diagnostics._0_expected.code) {
          addRelatedInfo(
            lastError,
            createDetachedDiagnostic(fileName, sourceText, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}")
          );
        }
      }
      return finishNode(factory.createImportAttributes(elements, multiLine, token2), pos);
    } else {
      const elements = createNodeArray(
        [],
        getNodePos(),
        /*end*/
        void 0,
        /*hasTrailingComma*/
        false
      );
      return finishNode(factory.createImportAttributes(
        elements,
        /*multiLine*/
        false,
        token2
      ), pos);
    }
  }
  function tokenAfterImportDefinitelyProducesImportDeclaration() {
    return token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBraceToken;
  }
  function tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration() {
    return token() === SyntaxKind.CommaToken || token() === SyntaxKind.FromKeyword;
  }
  function parseImportEqualsDeclaration(pos, hasJSDoc, modifiers, identifier, isTypeOnly) {
    parseExpected(SyntaxKind.EqualsToken);
    const moduleReference = parseModuleReference();
    parseSemicolon();
    const node = factory.createImportEqualsDeclaration(modifiers, isTypeOnly, identifier, moduleReference);
    const finished = withJSDoc(finishNode(node, pos), hasJSDoc);
    return finished;
  }
  function parseImportClause(identifier, pos, isTypeOnly) {
    let namedBindings;
    if (!identifier || parseOptional(SyntaxKind.CommaToken)) {
      namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
    }
    return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings), pos);
  }
  function parseModuleReference() {
    return isExternalModuleReference2() ? parseExternalModuleReference() : parseEntityName(
      /*allowReservedWords*/
      false
    );
  }
  function parseExternalModuleReference() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.RequireKeyword);
    parseExpected(SyntaxKind.OpenParenToken);
    const expression = parseModuleSpecifier();
    parseExpected(SyntaxKind.CloseParenToken);
    return finishNode(factory.createExternalModuleReference(expression), pos);
  }
  function parseModuleSpecifier() {
    if (token() === SyntaxKind.StringLiteral) {
      const result = parseLiteralNode();
      result.text = internIdentifier(result.text);
      return result;
    } else {
      return parseExpression();
    }
  }
  function parseNamespaceImport() {
    const pos = getNodePos();
    parseExpected(SyntaxKind.AsteriskToken);
    parseExpected(SyntaxKind.AsKeyword);
    const name = parseIdentifier();
    return finishNode(factory.createNamespaceImport(name), pos);
  }
  function parseNamedImportsOrExports(kind) {
    const pos = getNodePos();
    const node = kind === SyntaxKind.NamedImports ? factory.createNamedImports(parseBracketedList(23 /* ImportOrExportSpecifiers */, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) : factory.createNamedExports(parseBracketedList(23 /* ImportOrExportSpecifiers */, parseExportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken));
    return finishNode(node, pos);
  }
  function parseExportSpecifier() {
    const hasJSDoc = hasPrecedingJSDocComment();
    return withJSDoc(parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier), hasJSDoc);
  }
  function parseImportSpecifier() {
    return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier);
  }
  function parseImportOrExportSpecifier(kind) {
    const pos = getNodePos();
    let checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
    let checkIdentifierStart = scanner.getTokenStart();
    let checkIdentifierEnd = scanner.getTokenEnd();
    let isTypeOnly = false;
    let propertyName;
    let canParseAsKeyword = true;
    let name = parseIdentifierName();
    if (name.escapedText === "type") {
      if (token() === SyntaxKind.AsKeyword) {
        const firstAs = parseIdentifierName();
        if (token() === SyntaxKind.AsKeyword) {
          const secondAs = parseIdentifierName();
          if (tokenIsIdentifierOrKeyword(token())) {
            isTypeOnly = true;
            propertyName = firstAs;
            name = parseNameWithKeywordCheck();
            canParseAsKeyword = false;
          } else {
            propertyName = name;
            name = secondAs;
            canParseAsKeyword = false;
          }
        } else if (tokenIsIdentifierOrKeyword(token())) {
          propertyName = name;
          canParseAsKeyword = false;
          name = parseNameWithKeywordCheck();
        } else {
          isTypeOnly = true;
          name = firstAs;
        }
      } else if (tokenIsIdentifierOrKeyword(token())) {
        isTypeOnly = true;
        name = parseNameWithKeywordCheck();
      }
    }
    if (canParseAsKeyword && token() === SyntaxKind.AsKeyword) {
      propertyName = name;
      parseExpected(SyntaxKind.AsKeyword);
      name = parseNameWithKeywordCheck();
    }
    if (kind === SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) {
      parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected);
    }
    const node = kind === SyntaxKind.ImportSpecifier ? factory.createImportSpecifier(isTypeOnly, propertyName, name) : factory.createExportSpecifier(isTypeOnly, propertyName, name);
    return finishNode(node, pos);
    function parseNameWithKeywordCheck() {
      checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
      checkIdentifierStart = scanner.getTokenStart();
      checkIdentifierEnd = scanner.getTokenEnd();
      return parseIdentifierName();
    }
  }
  function parseNamespaceExport(pos) {
    return finishNode(factory.createNamespaceExport(parseIdentifierName()), pos);
  }
  function parseExportDeclaration(pos, hasJSDoc, modifiers) {
    const savedAwaitContext = inAwaitContext();
    setAwaitContext(
      /*value*/
      true
    );
    let exportClause;
    let moduleSpecifier;
    let attributes;
    const isTypeOnly = parseOptional(SyntaxKind.TypeKeyword);
    const namespaceExportPos = getNodePos();
    if (parseOptional(SyntaxKind.AsteriskToken)) {
      if (parseOptional(SyntaxKind.AsKeyword)) {
        exportClause = parseNamespaceExport(namespaceExportPos);
      }
      parseExpected(SyntaxKind.FromKeyword);
      moduleSpecifier = parseModuleSpecifier();
    } else {
      exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports);
      if (token() === SyntaxKind.FromKeyword || token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak()) {
        parseExpected(SyntaxKind.FromKeyword);
        moduleSpecifier = parseModuleSpecifier();
      }
    }
    const currentToken2 = token();
    if (moduleSpecifier && (currentToken2 === SyntaxKind.WithKeyword || currentToken2 === SyntaxKind.AssertKeyword) && !scanner.hasPrecedingLineBreak()) {
      attributes = parseImportAttributes(currentToken2);
    }
    parseSemicolon();
    setAwaitContext(savedAwaitContext);
    const node = factory.createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, attributes);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  function parseExportAssignment(pos, hasJSDoc, modifiers) {
    const savedAwaitContext = inAwaitContext();
    setAwaitContext(
      /*value*/
      true
    );
    let isExportEquals;
    if (parseOptional(SyntaxKind.EqualsToken)) {
      isExportEquals = true;
    } else {
      parseExpected(SyntaxKind.DefaultKeyword);
    }
    const expression = parseAssignmentExpressionOrHigher(
      /*allowReturnTypeInArrowFunction*/
      true
    );
    parseSemicolon();
    setAwaitContext(savedAwaitContext);
    const node = factory.createExportAssignment(modifiers, isExportEquals, expression);
    return withJSDoc(finishNode(node, pos), hasJSDoc);
  }
  let ParsingContext;
  ((ParsingContext2) => {
    ParsingContext2[ParsingContext2["SourceElements"] = 0] = "SourceElements";
    ParsingContext2[ParsingContext2["BlockStatements"] = 1] = "BlockStatements";
    ParsingContext2[ParsingContext2["SwitchClauses"] = 2] = "SwitchClauses";
    ParsingContext2[ParsingContext2["SwitchClauseStatements"] = 3] = "SwitchClauseStatements";
    ParsingContext2[ParsingContext2["TypeMembers"] = 4] = "TypeMembers";
    ParsingContext2[ParsingContext2["ClassMembers"] = 5] = "ClassMembers";
    ParsingContext2[ParsingContext2["EnumMembers"] = 6] = "EnumMembers";
    ParsingContext2[ParsingContext2["HeritageClauseElement"] = 7] = "HeritageClauseElement";
    ParsingContext2[ParsingContext2["VariableDeclarations"] = 8] = "VariableDeclarations";
    ParsingContext2[ParsingContext2["ObjectBindingElements"] = 9] = "ObjectBindingElements";
    ParsingContext2[ParsingContext2["ArrayBindingElements"] = 10] = "ArrayBindingElements";
    ParsingContext2[ParsingContext2["ArgumentExpressions"] = 11] = "ArgumentExpressions";
    ParsingContext2[ParsingContext2["ObjectLiteralMembers"] = 12] = "ObjectLiteralMembers";
    ParsingContext2[ParsingContext2["JsxAttributes"] = 13] = "JsxAttributes";
    ParsingContext2[ParsingContext2["JsxChildren"] = 14] = "JsxChildren";
    ParsingContext2[ParsingContext2["ArrayLiteralMembers"] = 15] = "ArrayLiteralMembers";
    ParsingContext2[ParsingContext2["Parameters"] = 16] = "Parameters";
    ParsingContext2[ParsingContext2["JSDocParameters"] = 17] = "JSDocParameters";
    ParsingContext2[ParsingContext2["RestProperties"] = 18] = "RestProperties";
    ParsingContext2[ParsingContext2["TypeParameters"] = 19] = "TypeParameters";
    ParsingContext2[ParsingContext2["TypeArguments"] = 20] = "TypeArguments";
    ParsingContext2[ParsingContext2["TupleElementTypes"] = 21] = "TupleElementTypes";
    ParsingContext2[ParsingContext2["HeritageClauses"] = 22] = "HeritageClauses";
    ParsingContext2[ParsingContext2["ImportOrExportSpecifiers"] = 23] = "ImportOrExportSpecifiers";
    ParsingContext2[ParsingContext2["ImportAttributes"] = 24] = "ImportAttributes";
    ParsingContext2[ParsingContext2["JSDocComment"] = 25] = "JSDocComment";
    ParsingContext2[ParsingContext2["Count"] = 26] = "Count";
  })(ParsingContext || (ParsingContext = {}));
  let Tristate;
  ((Tristate2) => {
    Tristate2[Tristate2["False"] = 0] = "False";
    Tristate2[Tristate2["True"] = 1] = "True";
    Tristate2[Tristate2["Unknown"] = 2] = "Unknown";
  })(Tristate || (Tristate = {}));
  let JSDocParser;
  ((JSDocParser2) => {
    function parseJSDocTypeExpressionForTests2(content, start, length) {
      initializeState(
        "file.js",
        content,
        ScriptTarget.Latest,
        /*syntaxCursor*/
        void 0,
        ScriptKind.JS,
        JSDocParsingMode.ParseAll
      );
      scanner.setText(content, start, length);
      currentToken = scanner.scan();
      const jsDocTypeExpression = parseJSDocTypeExpression();
      const sourceFile = createSourceFile2(
        "file.js",
        ScriptTarget.Latest,
        ScriptKind.JS,
        /*isDeclarationFile*/
        false,
        [],
        factoryCreateToken(SyntaxKind.EndOfFileToken),
        NodeFlags.None,
        noop
      );
      const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
      if (jsDocDiagnostics) {
        sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
      }
      clearState();
      return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : void 0;
    }
    JSDocParser2.parseJSDocTypeExpressionForTests = parseJSDocTypeExpressionForTests2;
    function parseJSDocTypeExpression(mayOmitBraces) {
      const pos = getNodePos();
      const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken);
      const type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType);
      if (!mayOmitBraces || hasBrace) {
        parseExpectedJSDoc(SyntaxKind.CloseBraceToken);
      }
      const result = factory.createJSDocTypeExpression(type);
      fixupParentReferences(result);
      return finishNode(result, pos);
    }
    JSDocParser2.parseJSDocTypeExpression = parseJSDocTypeExpression;
    function parseJSDocNameReference() {
      const pos = getNodePos();
      const hasBrace = parseOptional(SyntaxKind.OpenBraceToken);
      const p2 = getNodePos();
      let entityName = parseEntityName(
        /*allowReservedWords*/
        false
      );
      while (token() === SyntaxKind.PrivateIdentifier) {
        reScanHashToken();
        nextTokenJSDoc();
        entityName = finishNode(factory.createJSDocMemberName(entityName, parseIdentifier()), p2);
      }
      if (hasBrace) {
        parseExpectedJSDoc(SyntaxKind.CloseBraceToken);
      }
      const result = factory.createJSDocNameReference(entityName);
      fixupParentReferences(result);
      return finishNode(result, pos);
    }
    JSDocParser2.parseJSDocNameReference = parseJSDocNameReference;
    function parseIsolatedJSDocComment2(content, start, length) {
      initializeState(
        "",
        content,
        ScriptTarget.Latest,
        /*syntaxCursor*/
        void 0,
        ScriptKind.JS,
        JSDocParsingMode.ParseAll
      );
      const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
      const sourceFile = { languageVariant: LanguageVariant.Standard, text: content };
      const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
      clearState();
      return jsDoc ? { jsDoc, diagnostics } : void 0;
    }
    JSDocParser2.parseIsolatedJSDocComment = parseIsolatedJSDocComment2;
    function parseJSDocComment(parent, start, length) {
      const saveToken = currentToken;
      const saveParseDiagnosticsLength = parseDiagnostics.length;
      const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
      const comment = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
      setParent(comment, parent);
      if (contextFlags & NodeFlags.JavaScriptFile) {
        if (!jsDocDiagnostics) {
          jsDocDiagnostics = [];
        }
        jsDocDiagnostics.push(...parseDiagnostics);
      }
      currentToken = saveToken;
      parseDiagnostics.length = saveParseDiagnosticsLength;
      parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
      return comment;
    }
    JSDocParser2.parseJSDocComment = parseJSDocComment;
    let JSDocState;
    ((JSDocState2) => {
      JSDocState2[JSDocState2["BeginningOfLine"] = 0] = "BeginningOfLine";
      JSDocState2[JSDocState2["SawAsterisk"] = 1] = "SawAsterisk";
      JSDocState2[JSDocState2["SavingComments"] = 2] = "SavingComments";
      JSDocState2[JSDocState2["SavingBackticks"] = 3] = "SavingBackticks";
    })(JSDocState || (JSDocState = {}));
    let PropertyLikeParse;
    ((PropertyLikeParse2) => {
      PropertyLikeParse2[PropertyLikeParse2["Property"] = 1] = "Property";
      PropertyLikeParse2[PropertyLikeParse2["Parameter"] = 2] = "Parameter";
      PropertyLikeParse2[PropertyLikeParse2["CallbackParameter"] = 4] = "CallbackParameter";
    })(PropertyLikeParse || (PropertyLikeParse = {}));
    function parseJSDocCommentWorker(start = 0, length) {
      const content = sourceText;
      const end = length === void 0 ? content.length : start + length;
      length = end - start;
      Debug.assert(start >= 0);
      Debug.assert(start <= end);
      Debug.assert(end <= content.length);
      if (!isJSDocLikeText(content, start)) {
        return void 0;
      }
      let tags;
      let tagsPos;
      let tagsEnd;
      let linkEnd;
      let commentsPos;
      let comments = [];
      const parts = [];
      const saveParsingContext = parsingContext;
      parsingContext |= 1 << 25 /* JSDocComment */;
      const result = scanner.scanRange(start + 3, length - 5, doJSDocScan);
      parsingContext = saveParsingContext;
      return result;
      function doJSDocScan() {
        let state = 1 /* SawAsterisk */;
        let margin;
        let indent = start - (content.lastIndexOf("\n", start) + 1) + 4;
        function pushComment(text) {
          if (!margin) {
            margin = indent;
          }
          comments.push(text);
          indent += text.length;
        }
        nextTokenJSDoc();
        while (parseOptionalJsdoc(SyntaxKind.WhitespaceTrivia)) ;
        if (parseOptionalJsdoc(SyntaxKind.NewLineTrivia)) {
          state = 0 /* BeginningOfLine */;
          indent = 0;
        }
        loop:
          while (true) {
            switch (token()) {
              case SyntaxKind.AtToken:
                removeTrailingWhitespace(comments);
                if (!commentsPos) commentsPos = getNodePos();
                addTag(parseTag(indent));
                state = 0 /* BeginningOfLine */;
                margin = void 0;
                break;
              case SyntaxKind.NewLineTrivia:
                comments.push(scanner.getTokenText());
                state = 0 /* BeginningOfLine */;
                indent = 0;
                break;
              case SyntaxKind.AsteriskToken:
                const asterisk = scanner.getTokenText();
                if (state === 1 /* SawAsterisk */) {
                  state = 2 /* SavingComments */;
                  pushComment(asterisk);
                } else {
                  Debug.assert(state === 0 /* BeginningOfLine */);
                  state = 1 /* SawAsterisk */;
                  indent += asterisk.length;
                }
                break;
              case SyntaxKind.WhitespaceTrivia:
                Debug.assert(state !== 2 /* SavingComments */, "whitespace shouldn't come from the scanner while saving top-level comment text");
                const whitespace = scanner.getTokenText();
                if (margin !== void 0 && indent + whitespace.length > margin) {
                  comments.push(whitespace.slice(margin - indent));
                }
                indent += whitespace.length;
                break;
              case SyntaxKind.EndOfFileToken:
                break loop;
              case SyntaxKind.JSDocCommentTextToken:
                state = 2 /* SavingComments */;
                pushComment(scanner.getTokenValue());
                break;
              case SyntaxKind.OpenBraceToken:
                state = 2 /* SavingComments */;
                const commentEnd = scanner.getTokenFullStart();
                const linkStart = scanner.getTokenEnd() - 1;
                const link = parseJSDocLink(linkStart);
                if (link) {
                  if (!linkEnd) {
                    removeLeadingNewlines(comments);
                  }
                  parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? start, commentEnd));
                  parts.push(link);
                  comments = [];
                  linkEnd = scanner.getTokenEnd();
                  break;
                }
              // fallthrough if it's not a {@link sequence
              default:
                state = 2 /* SavingComments */;
                pushComment(scanner.getTokenText());
                break;
            }
            if (state === 2 /* SavingComments */) {
              nextJSDocCommentTextToken(
                /*inBackticks*/
                false
              );
            } else {
              nextTokenJSDoc();
            }
          }
        const trimmedComments = comments.join("").trimEnd();
        if (parts.length && trimmedComments.length) {
          parts.push(finishNode(factory.createJSDocText(trimmedComments), linkEnd ?? start, commentsPos));
        }
        if (parts.length && tags) Debug.assertIsDefined(commentsPos, "having parsed tags implies that the end of the comment span should be set");
        const tagsArray = tags && createNodeArray(tags, tagsPos, tagsEnd);
        return finishNode(factory.createJSDocComment(parts.length ? createNodeArray(parts, start, commentsPos) : trimmedComments.length ? trimmedComments : void 0, tagsArray), start, end);
      }
      function removeLeadingNewlines(comments2) {
        while (comments2.length && (comments2[0] === "\n" || comments2[0] === "\r")) {
          comments2.shift();
        }
      }
      function removeTrailingWhitespace(comments2) {
        while (comments2.length) {
          const trimmed = comments2[comments2.length - 1].trimEnd();
          if (trimmed === "") {
            comments2.pop();
          } else if (trimmed.length < comments2[comments2.length - 1].length) {
            comments2[comments2.length - 1] = trimmed;
            break;
          } else {
            break;
          }
        }
      }
      function isNextNonwhitespaceTokenEndOfFile() {
        while (true) {
          nextTokenJSDoc();
          if (token() === SyntaxKind.EndOfFileToken) {
            return true;
          }
          if (!(token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia)) {
            return false;
          }
        }
      }
      function skipWhitespace() {
        if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
          if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) {
            return;
          }
        }
        while (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
          nextTokenJSDoc();
        }
      }
      function skipWhitespaceOrAsterisk() {
        if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
          if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) {
            return "";
          }
        }
        let precedingLineBreak = scanner.hasPrecedingLineBreak();
        let seenLineBreak = false;
        let indentText = "";
        while (precedingLineBreak && token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
          indentText += scanner.getTokenText();
          if (token() === SyntaxKind.NewLineTrivia) {
            precedingLineBreak = true;
            seenLineBreak = true;
            indentText = "";
          } else if (token() === SyntaxKind.AsteriskToken) {
            precedingLineBreak = false;
          }
          nextTokenJSDoc();
        }
        return seenLineBreak ? indentText : "";
      }
      function parseTag(margin) {
        Debug.assert(token() === SyntaxKind.AtToken);
        const start2 = scanner.getTokenStart();
        nextTokenJSDoc();
        const tagName = parseJSDocIdentifierName(
          /*message*/
          void 0
        );
        const indentText = skipWhitespaceOrAsterisk();
        let tag;
        switch (tagName.escapedText) {
          case "author":
            tag = parseAuthorTag(start2, tagName, margin, indentText);
            break;
          case "implements":
            tag = parseImplementsTag(start2, tagName, margin, indentText);
            break;
          case "augments":
          case "extends":
            tag = parseAugmentsTag(start2, tagName, margin, indentText);
            break;
          case "class":
          case "constructor":
            tag = parseSimpleTag(start2, factory.createJSDocClassTag, tagName, margin, indentText);
            break;
          case "public":
            tag = parseSimpleTag(start2, factory.createJSDocPublicTag, tagName, margin, indentText);
            break;
          case "private":
            tag = parseSimpleTag(start2, factory.createJSDocPrivateTag, tagName, margin, indentText);
            break;
          case "protected":
            tag = parseSimpleTag(start2, factory.createJSDocProtectedTag, tagName, margin, indentText);
            break;
          case "readonly":
            tag = parseSimpleTag(start2, factory.createJSDocReadonlyTag, tagName, margin, indentText);
            break;
          case "override":
            tag = parseSimpleTag(start2, factory.createJSDocOverrideTag, tagName, margin, indentText);
            break;
          case "deprecated":
            hasDeprecatedTag = true;
            tag = parseSimpleTag(start2, factory.createJSDocDeprecatedTag, tagName, margin, indentText);
            break;
          case "this":
            tag = parseThisTag(start2, tagName, margin, indentText);
            break;
          case "enum":
            tag = parseEnumTag(start2, tagName, margin, indentText);
            break;
          case "arg":
          case "argument":
          case "param":
            return parseParameterOrPropertyTag(start2, tagName, 2 /* Parameter */, margin);
          case "return":
          case "returns":
            tag = parseReturnTag(start2, tagName, margin, indentText);
            break;
          case "template":
            tag = parseTemplateTag(start2, tagName, margin, indentText);
            break;
          case "type":
            tag = parseTypeTag(start2, tagName, margin, indentText);
            break;
          case "typedef":
            tag = parseTypedefTag(start2, tagName, margin, indentText);
            break;
          case "callback":
            tag = parseCallbackTag(start2, tagName, margin, indentText);
            break;
          case "overload":
            tag = parseOverloadTag(start2, tagName, margin, indentText);
            break;
          case "satisfies":
            tag = parseSatisfiesTag(start2, tagName, margin, indentText);
            break;
          case "see":
            tag = parseSeeTag(start2, tagName, margin, indentText);
            break;
          case "exception":
          case "throws":
            tag = parseThrowsTag(start2, tagName, margin, indentText);
            break;
          default:
            tag = parseUnknownTag(start2, tagName, margin, indentText);
            break;
        }
        return tag;
      }
      function parseTrailingTagComments(pos, end2, margin, indentText) {
        if (!indentText) {
          margin += end2 - pos;
        }
        return parseTagComments(margin, indentText.slice(margin));
      }
      function parseTagComments(indent, initialMargin) {
        const commentsPos2 = getNodePos();
        let comments2 = [];
        const parts2 = [];
        let linkEnd2;
        let state = 0 /* BeginningOfLine */;
        let margin;
        function pushComment(text) {
          if (!margin) {
            margin = indent;
          }
          comments2.push(text);
          indent += text.length;
        }
        if (initialMargin !== void 0) {
          if (initialMargin !== "") {
            pushComment(initialMargin);
          }
          state = 1 /* SawAsterisk */;
        }
        let tok = token();
        loop:
          while (true) {
            switch (tok) {
              case SyntaxKind.NewLineTrivia:
                state = 0 /* BeginningOfLine */;
                comments2.push(scanner.getTokenText());
                indent = 0;
                break;
              case SyntaxKind.AtToken:
                scanner.resetTokenState(scanner.getTokenEnd() - 1);
                break loop;
              case SyntaxKind.EndOfFileToken:
                break loop;
              case SyntaxKind.WhitespaceTrivia:
                Debug.assert(state !== 2 /* SavingComments */ && state !== 3 /* SavingBackticks */, "whitespace shouldn't come from the scanner while saving comment text");
                const whitespace = scanner.getTokenText();
                if (margin !== void 0 && indent + whitespace.length > margin) {
                  comments2.push(whitespace.slice(margin - indent));
                  state = 2 /* SavingComments */;
                }
                indent += whitespace.length;
                break;
              case SyntaxKind.OpenBraceToken:
                state = 2 /* SavingComments */;
                const commentEnd = scanner.getTokenFullStart();
                const linkStart = scanner.getTokenEnd() - 1;
                const link = parseJSDocLink(linkStart);
                if (link) {
                  parts2.push(finishNode(factory.createJSDocText(comments2.join("")), linkEnd2 ?? commentsPos2, commentEnd));
                  parts2.push(link);
                  comments2 = [];
                  linkEnd2 = scanner.getTokenEnd();
                } else {
                  pushComment(scanner.getTokenText());
                }
                break;
              case SyntaxKind.BacktickToken:
                if (state === 3 /* SavingBackticks */) {
                  state = 2 /* SavingComments */;
                } else {
                  state = 3 /* SavingBackticks */;
                }
                pushComment(scanner.getTokenText());
                break;
              case SyntaxKind.JSDocCommentTextToken:
                if (state !== 3 /* SavingBackticks */) {
                  state = 2 /* SavingComments */;
                }
                pushComment(scanner.getTokenValue());
                break;
              case SyntaxKind.AsteriskToken:
                if (state === 0 /* BeginningOfLine */) {
                  state = 1 /* SawAsterisk */;
                  indent += 1;
                  break;
                }
              // record the * as a comment
              // falls through
              default:
                if (state !== 3 /* SavingBackticks */) {
                  state = 2 /* SavingComments */;
                }
                pushComment(scanner.getTokenText());
                break;
            }
            if (state === 2 /* SavingComments */ || state === 3 /* SavingBackticks */) {
              tok = nextJSDocCommentTextToken(state === 3 /* SavingBackticks */);
            } else {
              tok = nextTokenJSDoc();
            }
          }
        removeLeadingNewlines(comments2);
        const trimmedComments = comments2.join("").trimEnd();
        if (parts2.length) {
          if (trimmedComments.length) {
            parts2.push(finishNode(factory.createJSDocText(trimmedComments), linkEnd2 ?? commentsPos2));
          }
          return createNodeArray(parts2, commentsPos2, scanner.getTokenEnd());
        } else if (trimmedComments.length) {
          return trimmedComments;
        }
      }
      function parseJSDocLink(start2) {
        const linkType = tryParse(parseJSDocLinkPrefix);
        if (!linkType) {
          return void 0;
        }
        nextTokenJSDoc();
        skipWhitespace();
        const p2 = getNodePos();
        let name = tokenIsIdentifierOrKeyword(token()) ? parseEntityName(
          /*allowReservedWords*/
          true
        ) : void 0;
        if (name) {
          while (token() === SyntaxKind.PrivateIdentifier) {
            reScanHashToken();
            nextTokenJSDoc();
            name = finishNode(factory.createJSDocMemberName(name, parseIdentifier()), p2);
          }
        }
        const text = [];
        while (token() !== SyntaxKind.CloseBraceToken && token() !== SyntaxKind.NewLineTrivia && token() !== SyntaxKind.EndOfFileToken) {
          text.push(scanner.getTokenText());
          nextTokenJSDoc();
        }
        const create = linkType === "link" ? factory.createJSDocLink : linkType === "linkcode" ? factory.createJSDocLinkCode : factory.createJSDocLinkPlain;
        return finishNode(create(name, text.join("")), start2, scanner.getTokenEnd());
      }
      function parseJSDocLinkPrefix() {
        skipWhitespaceOrAsterisk();
        if (token() === SyntaxKind.OpenBraceToken && nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc())) {
          const kind = scanner.getTokenValue();
          if (isJSDocLinkTag(kind)) return kind;
        }
      }
      function isJSDocLinkTag(kind) {
        return kind === "link" || kind === "linkcode" || kind === "linkplain";
      }
      function parseUnknownTag(start2, tagName, indent, indentText) {
        return finishNode(factory.createJSDocUnknownTag(tagName, parseTrailingTagComments(start2, getNodePos(), indent, indentText)), start2);
      }
      function addTag(tag) {
        if (!tag) {
          return;
        }
        if (!tags) {
          tags = [tag];
          tagsPos = tag.pos;
        } else {
          tags.push(tag);
        }
        tagsEnd = tag.end;
      }
      function tryParseTypeExpression() {
        skipWhitespaceOrAsterisk();
        return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : void 0;
      }
      function parseBracketNameInPropertyAndParamTag() {
        const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken);
        if (isBracketed) {
          skipWhitespace();
        }
        const isBackquoted = parseOptionalJsdoc(SyntaxKind.BacktickToken);
        const name = parseJSDocEntityName();
        if (isBackquoted) {
          parseExpectedTokenJSDoc(SyntaxKind.BacktickToken);
        }
        if (isBracketed) {
          skipWhitespace();
          if (parseOptionalToken(SyntaxKind.EqualsToken)) {
            parseExpression();
          }
          parseExpected(SyntaxKind.CloseBracketToken);
        }
        return { name, isBracketed };
      }
      function isObjectOrObjectArrayTypeReference(node) {
        switch (node.kind) {
          case SyntaxKind.ObjectKeyword:
            return true;
          case SyntaxKind.ArrayType:
            return isObjectOrObjectArrayTypeReference(node.elementType);
          default:
            return isTypeReferenceNode(node) && isIdentifierNode(node.typeName) && node.typeName.escapedText === "Object" && !node.typeArguments;
        }
      }
      function parseParameterOrPropertyTag(start2, tagName, target, indent) {
        let typeExpression = tryParseTypeExpression();
        let isNameFirst = !typeExpression;
        skipWhitespaceOrAsterisk();
        const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
        const indentText = skipWhitespaceOrAsterisk();
        if (isNameFirst && !lookAhead(parseJSDocLinkPrefix)) {
          typeExpression = tryParseTypeExpression();
        }
        const comment = parseTrailingTagComments(start2, getNodePos(), indent, indentText);
        const nestedTypeLiteral = parseNestedTypeLiteral(typeExpression, name, target, indent);
        if (nestedTypeLiteral) {
          typeExpression = nestedTypeLiteral;
          isNameFirst = true;
        }
        const result2 = target === 1 /* Property */ ? factory.createJSDocPropertyTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment) : factory.createJSDocParameterTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment);
        return finishNode(result2, start2);
      }
      function parseNestedTypeLiteral(typeExpression, name, target, indent) {
        if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
          const pos = getNodePos();
          let child;
          let children;
          while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) {
            if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) {
              children = append(children, child);
            } else if (child.kind === SyntaxKind.JSDocTemplateTag) {
              parseErrorAtRange(child.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag);
            }
          }
          if (children) {
            const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), pos);
            return finishNode(factory.createJSDocTypeExpression(literal), pos);
          }
        }
      }
      function parseReturnTag(start2, tagName, indent, indentText) {
        if (some(tags, isJSDocReturnTag)) {
          parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText));
        }
        const typeExpression = tryParseTypeExpression();
        return finishNode(factory.createJSDocReturnTag(tagName, typeExpression, parseTrailingTagComments(start2, getNodePos(), indent, indentText)), start2);
      }
      function parseTypeTag(start2, tagName, indent, indentText) {
        if (some(tags, isJSDocTypeTag)) {
          parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText));
        }
        const typeExpression = parseJSDocTypeExpression(
          /*mayOmitBraces*/
          true
        );
        const comments2 = indent !== void 0 && indentText !== void 0 ? parseTrailingTagComments(start2, getNodePos(), indent, indentText) : void 0;
        return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments2), start2);
      }
      function parseSeeTag(start2, tagName, indent, indentText) {
        const isMarkdownOrJSDocLink = token() === SyntaxKind.OpenBracketToken || lookAhead(() => nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc()) && isJSDocLinkTag(scanner.getTokenValue()));
        const nameExpression = isMarkdownOrJSDocLink ? void 0 : parseJSDocNameReference();
        const comments2 = indent !== void 0 && indentText !== void 0 ? parseTrailingTagComments(start2, getNodePos(), indent, indentText) : void 0;
        return finishNode(factory.createJSDocSeeTag(tagName, nameExpression, comments2), start2);
      }
      function parseThrowsTag(start2, tagName, indent, indentText) {
        const typeExpression = tryParseTypeExpression();
        const comment = parseTrailingTagComments(start2, getNodePos(), indent, indentText);
        return finishNode(factory.createJSDocThrowsTag(tagName, typeExpression, comment), start2);
      }
      function parseAuthorTag(start2, tagName, indent, indentText) {
        const commentStart = getNodePos();
        const textOnly = parseAuthorNameAndEmail();
        let commentEnd = scanner.getTokenFullStart();
        const comments2 = parseTrailingTagComments(start2, commentEnd, indent, indentText);
        if (!comments2) {
          commentEnd = scanner.getTokenFullStart();
        }
        const allParts = typeof comments2 !== "string" ? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments2), commentStart) : textOnly.text + comments2;
        return finishNode(factory.createJSDocAuthorTag(tagName, allParts), start2);
      }
      function parseAuthorNameAndEmail() {
        const comments2 = [];
        let inEmail = false;
        let token2 = scanner.getToken();
        while (token2 !== SyntaxKind.EndOfFileToken && token2 !== SyntaxKind.NewLineTrivia) {
          if (token2 === SyntaxKind.LessThanToken) {
            inEmail = true;
          } else if (token2 === SyntaxKind.AtToken && !inEmail) {
            break;
          } else if (token2 === SyntaxKind.GreaterThanToken && inEmail) {
            comments2.push(scanner.getTokenText());
            scanner.resetTokenState(scanner.getTokenEnd());
            break;
          }
          comments2.push(scanner.getTokenText());
          token2 = nextTokenJSDoc();
        }
        return factory.createJSDocText(comments2.join(""));
      }
      function parseImplementsTag(start2, tagName, margin, indentText) {
        const className = parseExpressionWithTypeArgumentsForAugments();
        return finishNode(factory.createJSDocImplementsTag(tagName, className, parseTrailingTagComments(start2, getNodePos(), margin, indentText)), start2);
      }
      function parseAugmentsTag(start2, tagName, margin, indentText) {
        const className = parseExpressionWithTypeArgumentsForAugments();
        return finishNode(factory.createJSDocAugmentsTag(tagName, className, parseTrailingTagComments(start2, getNodePos(), margin, indentText)), start2);
      }
      function parseSatisfiesTag(start2, tagName, margin, indentText) {
        const typeExpression = parseJSDocTypeExpression(
          /*mayOmitBraces*/
          false
        );
        const comments2 = margin !== void 0 && indentText !== void 0 ? parseTrailingTagComments(start2, getNodePos(), margin, indentText) : void 0;
        return finishNode(factory.createJSDocSatisfiesTag(tagName, typeExpression, comments2), start2);
      }
      function parseExpressionWithTypeArgumentsForAugments() {
        const usedBrace = parseOptional(SyntaxKind.OpenBraceToken);
        const pos = getNodePos();
        const expression = parsePropertyAccessEntityNameExpression();
        scanner.setInJSDocType(true);
        const typeArguments = tryParseTypeArguments();
        scanner.setInJSDocType(false);
        const node = factory.createExpressionWithTypeArguments(expression, typeArguments);
        const res = finishNode(node, pos);
        if (usedBrace) {
          parseExpected(SyntaxKind.CloseBraceToken);
        }
        return res;
      }
      function parsePropertyAccessEntityNameExpression() {
        const pos = getNodePos();
        let node = parseJSDocIdentifierName();
        while (parseOptional(SyntaxKind.DotToken)) {
          const name = parseJSDocIdentifierName();
          node = finishNode(factoryCreatePropertyAccessExpression(node, name), pos);
        }
        return node;
      }
      function parseSimpleTag(start2, createTag, tagName, margin, indentText) {
        return finishNode(createTag(tagName, parseTrailingTagComments(start2, getNodePos(), margin, indentText)), start2);
      }
      function parseThisTag(start2, tagName, margin, indentText) {
        const typeExpression = parseJSDocTypeExpression(
          /*mayOmitBraces*/
          true
        );
        skipWhitespace();
        return finishNode(factory.createJSDocThisTag(tagName, typeExpression, parseTrailingTagComments(start2, getNodePos(), margin, indentText)), start2);
      }
      function parseEnumTag(start2, tagName, margin, indentText) {
        const typeExpression = parseJSDocTypeExpression(
          /*mayOmitBraces*/
          true
        );
        skipWhitespace();
        return finishNode(factory.createJSDocEnumTag(tagName, typeExpression, parseTrailingTagComments(start2, getNodePos(), margin, indentText)), start2);
      }
      function parseTypedefTag(start2, tagName, indent, indentText) {
        let typeExpression = tryParseTypeExpression();
        skipWhitespaceOrAsterisk();
        const fullName = parseJSDocTypeNameWithNamespace();
        skipWhitespace();
        let comment = parseTagComments(indent);
        let end2;
        if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
          let child;
          let childTypeTag;
          let jsDocPropertyTags;
          let hasChildren = false;
          while (child = tryParse(() => parseChildPropertyTag(indent))) {
            if (child.kind === SyntaxKind.JSDocTemplateTag) {
              break;
            }
            hasChildren = true;
            if (child.kind === SyntaxKind.JSDocTypeTag) {
              if (childTypeTag) {
                const lastError = parseErrorAtCurrentToken(Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags);
                if (lastError) {
                  addRelatedInfo(lastError, createDetachedDiagnostic(fileName, sourceText, 0, 0, Diagnostics.The_tag_was_first_specified_here));
                }
                break;
              } else {
                childTypeTag = child;
              }
            } else {
              jsDocPropertyTags = append(jsDocPropertyTags, child);
            }
          }
          if (hasChildren) {
            const isArrayType = typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType;
            const jsdocTypeLiteral = factory.createJSDocTypeLiteral(jsDocPropertyTags, isArrayType);
            typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? childTypeTag.typeExpression : finishNode(jsdocTypeLiteral, start2);
            end2 = typeExpression.end;
          }
        }
        end2 = end2 || comment !== void 0 ? getNodePos() : (fullName ?? typeExpression ?? tagName).end;
        if (!comment) {
          comment = parseTrailingTagComments(start2, end2, indent, indentText);
        }
        const typedefTag = factory.createJSDocTypedefTag(tagName, typeExpression, fullName, comment);
        return finishNode(typedefTag, start2, end2);
      }
      function parseJSDocTypeNameWithNamespace(nested) {
        const start2 = scanner.getTokenStart();
        if (!tokenIsIdentifierOrKeyword(token())) {
          return void 0;
        }
        const typeNameOrNamespaceName = parseJSDocIdentifierName();
        if (parseOptional(SyntaxKind.DotToken)) {
          const body = parseJSDocTypeNameWithNamespace(
            /*nested*/
            true
          );
          const jsDocNamespaceNode = factory.createModuleDeclaration(
            /*modifiers*/
            void 0,
            typeNameOrNamespaceName,
            body,
            nested ? NodeFlags.NestedNamespace : void 0
          );
          return finishNode(jsDocNamespaceNode, start2);
        }
        if (nested) {
          typeNameOrNamespaceName.flags |= NodeFlags.IdentifierIsInJSDocNamespace;
        }
        return typeNameOrNamespaceName;
      }
      function parseCallbackTagParameters(indent) {
        const pos = getNodePos();
        let child;
        let parameters;
        while (child = tryParse(() => parseChildParameterOrPropertyTag(4 /* CallbackParameter */, indent))) {
          if (child.kind === SyntaxKind.JSDocTemplateTag) {
            parseErrorAtRange(child.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag);
            break;
          }
          parameters = append(parameters, child);
        }
        return createNodeArray(parameters || [], pos);
      }
      function parseJSDocSignature(start2, indent) {
        const parameters = parseCallbackTagParameters(indent);
        const returnTag = tryParse(() => {
          if (parseOptionalJsdoc(SyntaxKind.AtToken)) {
            const tag = parseTag(indent);
            if (tag && tag.kind === SyntaxKind.JSDocReturnTag) {
              return tag;
            }
          }
        });
        return finishNode(factory.createJSDocSignature(
          /*typeParameters*/
          void 0,
          parameters,
          returnTag
        ), start2);
      }
      function parseCallbackTag(start2, tagName, indent, indentText) {
        const fullName = parseJSDocTypeNameWithNamespace();
        skipWhitespace();
        let comment = parseTagComments(indent);
        const typeExpression = parseJSDocSignature(start2, indent);
        if (!comment) {
          comment = parseTrailingTagComments(start2, getNodePos(), indent, indentText);
        }
        const end2 = comment !== void 0 ? getNodePos() : typeExpression.end;
        return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start2, end2);
      }
      function parseOverloadTag(start2, tagName, indent, indentText) {
        skipWhitespace();
        let comment = parseTagComments(indent);
        const typeExpression = parseJSDocSignature(start2, indent);
        if (!comment) {
          comment = parseTrailingTagComments(start2, getNodePos(), indent, indentText);
        }
        const end2 = comment !== void 0 ? getNodePos() : typeExpression.end;
        return finishNode(factory.createJSDocOverloadTag(tagName, typeExpression, comment), start2, end2);
      }
      function escapedTextsEqual(a, b) {
        while (!isIdentifierNode(a) || !isIdentifierNode(b)) {
          if (!isIdentifierNode(a) && !isIdentifierNode(b) && a.right.escapedText === b.right.escapedText) {
            a = a.left;
            b = b.left;
          } else {
            return false;
          }
        }
        return a.escapedText === b.escapedText;
      }
      function parseChildPropertyTag(indent) {
        return parseChildParameterOrPropertyTag(1 /* Property */, indent);
      }
      function parseChildParameterOrPropertyTag(target, indent, name) {
        let canParseTag = true;
        let seenAsterisk = false;
        while (true) {
          switch (nextTokenJSDoc()) {
            case SyntaxKind.AtToken:
              if (canParseTag) {
                const child = tryParseChildTag(target, indent);
                if (child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) && name && (isIdentifierNode(child.name) || !escapedTextsEqual(name, child.name.left))) {
                  return false;
                }
                return child;
              }
              seenAsterisk = false;
              break;
            case SyntaxKind.NewLineTrivia:
              canParseTag = true;
              seenAsterisk = false;
              break;
            case SyntaxKind.AsteriskToken:
              if (seenAsterisk) {
                canParseTag = false;
              }
              seenAsterisk = true;
              break;
            case SyntaxKind.Identifier:
              canParseTag = false;
              break;
            case SyntaxKind.EndOfFileToken:
              return false;
          }
        }
      }
      function tryParseChildTag(target, indent) {
        Debug.assert(token() === SyntaxKind.AtToken);
        const start2 = scanner.getTokenFullStart();
        nextTokenJSDoc();
        const tagName = parseJSDocIdentifierName();
        const indentText = skipWhitespaceOrAsterisk();
        let t;
        switch (tagName.escapedText) {
          case "type":
            return target === 1 /* Property */ && parseTypeTag(start2, tagName);
          case "prop":
          case "property":
            t = 1 /* Property */;
            break;
          case "arg":
          case "argument":
          case "param":
            t = 2 /* Parameter */ | 4 /* CallbackParameter */;
            break;
          case "template":
            return parseTemplateTag(start2, tagName, indent, indentText);
          default:
            return false;
        }
        if (!(target & t)) {
          return false;
        }
        return parseParameterOrPropertyTag(start2, tagName, target, indent);
      }
      function parseTemplateTagTypeParameter() {
        const typeParameterPos = getNodePos();
        const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken);
        if (isBracketed) {
          skipWhitespace();
        }
        const name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces);
        let defaultType;
        if (isBracketed) {
          skipWhitespace();
          parseExpected(SyntaxKind.EqualsToken);
          defaultType = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType);
          parseExpected(SyntaxKind.CloseBracketToken);
        }
        if (nodeIsMissing(name)) {
          return void 0;
        }
        return finishNode(factory.createTypeParameterDeclaration(
          /*modifiers*/
          void 0,
          name,
          /*constraint*/
          void 0,
          defaultType
        ), typeParameterPos);
      }
      function parseTemplateTagTypeParameters() {
        const pos = getNodePos();
        const typeParameters = [];
        do {
          skipWhitespace();
          const node = parseTemplateTagTypeParameter();
          if (node !== void 0) {
            typeParameters.push(node);
          }
          skipWhitespaceOrAsterisk();
        } while (parseOptionalJsdoc(SyntaxKind.CommaToken));
        return createNodeArray(typeParameters, pos);
      }
      function parseTemplateTag(start2, tagName, indent, indentText) {
        const constraint = token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : void 0;
        const typeParameters = parseTemplateTagTypeParameters();
        return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters, parseTrailingTagComments(start2, getNodePos(), indent, indentText)), start2);
      }
      function parseOptionalJsdoc(t) {
        if (token() === t) {
          nextTokenJSDoc();
          return true;
        }
        return false;
      }
      function parseJSDocEntityName() {
        let entity = parseJSDocIdentifierName();
        if (parseOptional(SyntaxKind.OpenBracketToken)) {
          parseExpected(SyntaxKind.CloseBracketToken);
        }
        while (parseOptional(SyntaxKind.DotToken)) {
          const name = parseJSDocIdentifierName();
          if (parseOptional(SyntaxKind.OpenBracketToken)) {
            parseExpected(SyntaxKind.CloseBracketToken);
          }
          entity = createQualifiedName(entity, name);
        }
        return entity;
      }
      function parseJSDocIdentifierName(message) {
        if (!tokenIsIdentifierOrKeyword(token())) {
          return createMissingNode(
            SyntaxKind.Identifier,
            /*reportAtCurrentPosition*/
            !message,
            message || Diagnostics.Identifier_expected
          );
        }
        identifierCount++;
        const start2 = scanner.getTokenStart();
        const end2 = scanner.getTokenEnd();
        const originalKeywordKind = token();
        const text = internIdentifier(scanner.getTokenValue());
        const result2 = finishNode(factoryCreateIdentifier(text, originalKeywordKind), start2, end2);
        nextTokenJSDoc();
        return result2;
      }
    }
  })(JSDocParser = Parser2.JSDocParser || (Parser2.JSDocParser = {}));
})(Parser || (Parser = {}));
var IncrementalParser;
((IncrementalParser2) => {
  function updateSourceFile2(sourceFile, newText, textChangeRange, aggressiveChecks) {
    aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive);
    checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
    if (textChangeRangeIsUnchanged(textChangeRange)) {
      return sourceFile;
    }
    if (sourceFile.statements.length === 0) {
      return Parser.parseSourceFile(
        sourceFile.fileName,
        newText,
        sourceFile.languageVersion,
        /*syntaxCursor*/
        void 0,
        /*setParentNodes*/
        true,
        sourceFile.scriptKind,
        sourceFile.setExternalModuleIndicator,
        sourceFile.jsDocParsingMode
      );
    }
    const incrementalSourceFile = sourceFile;
    Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
    incrementalSourceFile.hasBeenIncrementallyParsed = true;
    Parser.fixupParentReferences(incrementalSourceFile);
    const oldText = sourceFile.text;
    const syntaxCursor = createSyntaxCursor(sourceFile);
    const changeRange = extendToAffectedRange(sourceFile, textChangeRange);
    checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
    Debug.assert(changeRange.span.start <= textChangeRange.span.start);
    Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span));
    Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange)));
    const delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
    updateTokenPositionsAndMarkElements(incrementalSourceFile, changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
    const result = Parser.parseSourceFile(
      sourceFile.fileName,
      newText,
      sourceFile.languageVersion,
      syntaxCursor,
      /*setParentNodes*/
      true,
      sourceFile.scriptKind,
      sourceFile.setExternalModuleIndicator,
      sourceFile.jsDocParsingMode
    );
    result.commentDirectives = getNewCommentDirectives(
      sourceFile.commentDirectives,
      result.commentDirectives,
      changeRange.span.start,
      textSpanEnd(changeRange.span),
      delta,
      oldText,
      newText,
      aggressiveChecks
    );
    result.impliedNodeFormat = sourceFile.impliedNodeFormat;
    return result;
  }
  IncrementalParser2.updateSourceFile = updateSourceFile2;
  function getNewCommentDirectives(oldDirectives, newDirectives, changeStart, changeRangeOldEnd, delta, oldText, newText, aggressiveChecks) {
    if (!oldDirectives) return newDirectives;
    let commentDirectives;
    let addedNewlyScannedDirectives = false;
    for (const directive of oldDirectives) {
      const { range, type } = directive;
      if (range.end < changeStart) {
        commentDirectives = append(commentDirectives, directive);
      } else if (range.pos > changeRangeOldEnd) {
        addNewlyScannedDirectives();
        const updatedDirective = {
          range: { pos: range.pos + delta, end: range.end + delta },
          type
        };
        commentDirectives = append(commentDirectives, updatedDirective);
        if (aggressiveChecks) {
          Debug.assert(oldText.substring(range.pos, range.end) === newText.substring(updatedDirective.range.pos, updatedDirective.range.end));
        }
      }
    }
    addNewlyScannedDirectives();
    return commentDirectives;
    function addNewlyScannedDirectives() {
      if (addedNewlyScannedDirectives) return;
      addedNewlyScannedDirectives = true;
      if (!commentDirectives) {
        commentDirectives = newDirectives;
      } else if (newDirectives) {
        commentDirectives.push(...newDirectives);
      }
    }
  }
  function moveElementEntirelyPastChangeRange(element, isArray2, delta, oldText, newText, aggressiveChecks) {
    if (isArray2) {
      visitArray(element);
    } else {
      visitNode2(element);
    }
    return;
    function visitNode2(node) {
      let text = "";
      if (aggressiveChecks && shouldCheckNode(node)) {
        text = oldText.substring(node.pos, node.end);
      }
      if (node._children) {
        node._children = void 0;
      }
      setTextRangePosEnd(node, node.pos + delta, node.end + delta);
      if (aggressiveChecks && shouldCheckNode(node)) {
        Debug.assert(text === newText.substring(node.pos, node.end));
      }
      forEachChild(node, visitNode2, visitArray);
      if (hasJSDocNodes(node)) {
        for (const jsDocComment of node.jsDoc) {
          visitNode2(jsDocComment);
        }
      }
      checkNodePositions(node, aggressiveChecks);
    }
    function visitArray(array) {
      array._children = void 0;
      setTextRangePosEnd(array, array.pos + delta, array.end + delta);
      for (const node of array) {
        visitNode2(node);
      }
    }
  }
  function shouldCheckNode(node) {
    switch (node.kind) {
      case SyntaxKind.StringLiteral:
      case SyntaxKind.NumericLiteral:
      case SyntaxKind.Identifier:
        return true;
    }
    return false;
  }
  function adjustIntersectingElement(element, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta) {
    Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
    Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
    Debug.assert(element.pos <= element.end);
    const pos = Math.min(element.pos, changeRangeNewEnd);
    const end = element.end >= changeRangeOldEnd ? (
      // Element ends after the change range.  Always adjust the end pos.
      element.end + delta
    ) : (
      // Element ends in the change range.  The element will keep its position if
      // possible. Or Move backward to the new-end if it's in the 'Y' range.
      Math.min(element.end, changeRangeNewEnd)
    );
    Debug.assert(pos <= end);
    if (element.parent) {
      Debug.assertGreaterThanOrEqual(pos, element.parent.pos);
      Debug.assertLessThanOrEqual(end, element.parent.end);
    }
    setTextRangePosEnd(element, pos, end);
  }
  function checkNodePositions(node, aggressiveChecks) {
    if (aggressiveChecks) {
      let pos = node.pos;
      const visitNode2 = (child) => {
        Debug.assert(child.pos >= pos);
        pos = child.end;
      };
      if (hasJSDocNodes(node)) {
        for (const jsDocComment of node.jsDoc) {
          visitNode2(jsDocComment);
        }
      }
      forEachChild(node, visitNode2);
      Debug.assert(pos <= node.end);
    }
  }
  function updateTokenPositionsAndMarkElements(sourceFile, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta, oldText, newText, aggressiveChecks) {
    visitNode2(sourceFile);
    return;
    function visitNode2(child) {
      Debug.assert(child.pos <= child.end);
      if (child.pos > changeRangeOldEnd) {
        moveElementEntirelyPastChangeRange(
          child,
          /*isArray*/
          false,
          delta,
          oldText,
          newText,
          aggressiveChecks
        );
        return;
      }
      const fullEnd = child.end;
      if (fullEnd >= changeStart) {
        child.intersectsChange = true;
        child._children = void 0;
        adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
        forEachChild(child, visitNode2, visitArray);
        if (hasJSDocNodes(child)) {
          for (const jsDocComment of child.jsDoc) {
            visitNode2(jsDocComment);
          }
        }
        checkNodePositions(child, aggressiveChecks);
        return;
      }
      Debug.assert(fullEnd < changeStart);
    }
    function visitArray(array) {
      Debug.assert(array.pos <= array.end);
      if (array.pos > changeRangeOldEnd) {
        moveElementEntirelyPastChangeRange(
          array,
          /*isArray*/
          true,
          delta,
          oldText,
          newText,
          aggressiveChecks
        );
        return;
      }
      const fullEnd = array.end;
      if (fullEnd >= changeStart) {
        array.intersectsChange = true;
        array._children = void 0;
        adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
        for (const node of array) {
          visitNode2(node);
        }
        return;
      }
      Debug.assert(fullEnd < changeStart);
    }
  }
  function extendToAffectedRange(sourceFile, changeRange) {
    const maxLookahead = 1;
    let start = changeRange.span.start;
    for (let i = 0; start > 0 && i <= maxLookahead; i++) {
      const nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
      Debug.assert(nearestNode.pos <= start);
      const position = nearestNode.pos;
      start = Math.max(0, position - 1);
    }
    const finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span));
    const finalLength = changeRange.newLength + (changeRange.span.start - start);
    return createTextChangeRange(finalSpan, finalLength);
  }
  function findNearestNodeStartingBeforeOrAtPosition(sourceFile, position) {
    let bestResult = sourceFile;
    let lastNodeEntirelyBeforePosition;
    forEachChild(sourceFile, visit);
    if (lastNodeEntirelyBeforePosition) {
      const lastChildOfLastEntireNodeBeforePosition = getLastDescendant(lastNodeEntirelyBeforePosition);
      if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
        bestResult = lastChildOfLastEntireNodeBeforePosition;
      }
    }
    return bestResult;
    function getLastDescendant(node) {
      while (true) {
        const lastChild = getLastChild(node);
        if (lastChild) {
          node = lastChild;
        } else {
          return node;
        }
      }
    }
    function visit(child) {
      if (nodeIsMissing(child)) {
        return;
      }
      if (child.pos <= position) {
        if (child.pos >= bestResult.pos) {
          bestResult = child;
        }
        if (position < child.end) {
          forEachChild(child, visit);
          return true;
        } else {
          Debug.assert(child.end <= position);
          lastNodeEntirelyBeforePosition = child;
        }
      } else {
        Debug.assert(child.pos > position);
        return true;
      }
    }
  }
  function checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks) {
    const oldText = sourceFile.text;
    if (textChangeRange) {
      Debug.assert(oldText.length - textChangeRange.span.length + textChangeRange.newLength === newText.length);
      if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) {
        const oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
        const newTextPrefix = newText.substr(0, textChangeRange.span.start);
        Debug.assert(oldTextPrefix === newTextPrefix);
        const oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length);
        const newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length);
        Debug.assert(oldTextSuffix === newTextSuffix);
      }
    }
  }
  function createSyntaxCursor(sourceFile) {
    let currentArray = sourceFile.statements;
    let currentArrayIndex = 0;
    Debug.assert(currentArrayIndex < currentArray.length);
    let current = currentArray[currentArrayIndex];
    let lastQueriedPosition = -1 /* Value */;
    return {
      currentNode(position) {
        if (position !== lastQueriedPosition) {
          if (current && current.end === position && currentArrayIndex < currentArray.length - 1) {
            currentArrayIndex++;
            current = currentArray[currentArrayIndex];
          }
          if (!current || current.pos !== position) {
            findHighestListElementThatStartsAtPosition(position);
          }
        }
        lastQueriedPosition = position;
        Debug.assert(!current || current.pos === position);
        return current;
      }
    };
    function findHighestListElementThatStartsAtPosition(position) {
      currentArray = void 0;
      currentArrayIndex = -1 /* Value */;
      current = void 0;
      forEachChild(sourceFile, visitNode2, visitArray);
      return;
      function visitNode2(node) {
        if (position >= node.pos && position < node.end) {
          forEachChild(node, visitNode2, visitArray);
          return true;
        }
        return false;
      }
      function visitArray(array) {
        if (position >= array.pos && position < array.end) {
          for (let i = 0; i < array.length; i++) {
            const child = array[i];
            if (child) {
              if (child.pos === position) {
                currentArray = array;
                currentArrayIndex = i;
                current = child;
                return true;
              } else {
                if (child.pos < position && position < child.end) {
                  forEachChild(child, visitNode2, visitArray);
                  return true;
                }
              }
            }
          }
        }
        return false;
      }
    }
  }
  IncrementalParser2.createSyntaxCursor = createSyntaxCursor;
  let InvalidPosition;
  ((InvalidPosition2) => {
    InvalidPosition2[InvalidPosition2["Value"] = -1] = "Value";
  })(InvalidPosition || (InvalidPosition = {}));
})(IncrementalParser || (IncrementalParser = {}));
export function isDeclarationFileName(fileName) {
  return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions) || fileExtensionIs(fileName, Extension.Ts) && getBaseFileName(fileName).includes(".d.");
}
function parseResolutionMode(mode, pos, end, reportDiagnostic) {
  if (!mode) {
    return void 0;
  }
  if (mode === "import") {
    return ModuleKind.ESNext;
  }
  if (mode === "require") {
    return ModuleKind.CommonJS;
  }
  reportDiagnostic(pos, end - pos, Diagnostics.resolution_mode_should_be_either_require_or_import);
  return void 0;
}
export function processCommentPragmas(context, sourceText) {
  const pragmas = [];
  for (const range of getLeadingCommentRanges(sourceText, 0) || emptyArray) {
    const comment = sourceText.substring(range.pos, range.end);
    extractPragmas(pragmas, range, comment);
  }
  context.pragmas = /* @__PURE__ */ new Map();
  for (const pragma of pragmas) {
    if (context.pragmas.has(pragma.name)) {
      const currentValue = context.pragmas.get(pragma.name);
      if (currentValue instanceof Array) {
        currentValue.push(pragma.args);
      } else {
        context.pragmas.set(pragma.name, [currentValue, pragma.args]);
      }
      continue;
    }
    context.pragmas.set(pragma.name, pragma.args);
  }
}
export function processPragmasIntoFields(context, reportDiagnostic) {
  context.checkJsDirective = void 0;
  context.referencedFiles = [];
  context.typeReferenceDirectives = [];
  context.libReferenceDirectives = [];
  context.amdDependencies = [];
  context.hasNoDefaultLib = false;
  context.pragmas.forEach((entryOrList, key) => {
    switch (key) {
      case "reference": {
        const referencedFiles = context.referencedFiles;
        const typeReferenceDirectives = context.typeReferenceDirectives;
        const libReferenceDirectives = context.libReferenceDirectives;
        forEach(toArray(entryOrList), (arg) => {
          const { types, lib, path, ["resolution-mode"]: res } = arg.arguments;
          if (arg.arguments["no-default-lib"]) {
            context.hasNoDefaultLib = true;
          } else if (types) {
            const parsed = parseResolutionMode(res, types.pos, types.end, reportDiagnostic);
            typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value, ...parsed ? { resolutionMode: parsed } : {} });
          } else if (lib) {
            libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value });
          } else if (path) {
            referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value });
          } else {
            reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
          }
        });
        break;
      }
      case "amd-dependency": {
        context.amdDependencies = map(
          toArray(entryOrList),
          (x) => ({ name: x.arguments.name, path: x.arguments.path })
        );
        break;
      }
      case "amd-module": {
        if (entryOrList instanceof Array) {
          for (const entry of entryOrList) {
            if (context.moduleName) {
              reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
            }
            context.moduleName = entry.arguments.name;
          }
        } else {
          context.moduleName = entryOrList.arguments.name;
        }
        break;
      }
      case "ts-nocheck":
      case "ts-check": {
        forEach(toArray(entryOrList), (entry) => {
          if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) {
            context.checkJsDirective = {
              enabled: key === "ts-check",
              end: entry.range.end,
              pos: entry.range.pos
            };
          }
        });
        break;
      }
      case "jsx":
      case "jsxfrag":
      case "jsximportsource":
      case "jsxruntime":
        return;
      // Accessed directly
      default:
        Debug.fail("Unhandled pragma kind");
    }
  });
}
const namedArgRegExCache = /* @__PURE__ */ new Map();
function getNamedArgRegEx(name) {
  if (namedArgRegExCache.has(name)) {
    return namedArgRegExCache.get(name);
  }
  const result = new RegExp(`(\\s${name}\\s*=\\s*)(?:(?:'([^']*)')|(?:"([^"]*)"))`, "im");
  namedArgRegExCache.set(name, result);
  return result;
}
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
const singleLinePragmaRegEx = /^\/\/\/?\s*@([^\s:]+)(.*)\s*$/im;
function extractPragmas(pragmas, range, text) {
  const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text);
  if (tripleSlash) {
    const name = tripleSlash[1].toLowerCase();
    const pragma = commentPragmas[name];
    if (!pragma || !(pragma.kind & PragmaKindFlags.TripleSlashXML)) {
      return;
    }
    if (pragma.args) {
      const argument = {};
      for (const arg of pragma.args) {
        const matcher = getNamedArgRegEx(arg.name);
        const matchResult = matcher.exec(text);
        if (!matchResult && !arg.optional) {
          return;
        } else if (matchResult) {
          const value = matchResult[2] || matchResult[3];
          if (arg.captureSpan) {
            const startPos = range.pos + matchResult.index + matchResult[1].length + 1;
            argument[arg.name] = {
              value,
              pos: startPos,
              end: startPos + value.length
            };
          } else {
            argument[arg.name] = value;
          }
        }
      }
      pragmas.push({ name, args: { arguments: argument, range } });
    } else {
      pragmas.push({ name, args: { arguments: {}, range } });
    }
    return;
  }
  const singleLine = range.kind === SyntaxKind.SingleLineCommentTrivia && singleLinePragmaRegEx.exec(text);
  if (singleLine) {
    return addPragmaForMatch(pragmas, range, PragmaKindFlags.SingleLine, singleLine);
  }
  if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
    const multiLinePragmaRegEx = /@(\S+)(\s+.*)?$/gim;
    let multiLineMatch;
    while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
      addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
    }
  }
}
function addPragmaForMatch(pragmas, range, kind, match) {
  if (!match) return;
  const name = match[1].toLowerCase();
  const pragma = commentPragmas[name];
  if (!pragma || !(pragma.kind & kind)) {
    return;
  }
  const args = match[2];
  const argument = getNamedPragmaArguments(pragma, args);
  if (argument === "fail") return;
  pragmas.push({ name, args: { arguments: argument, range } });
  return;
}
function getNamedPragmaArguments(pragma, text) {
  if (!text) return {};
  if (!pragma.args) return {};
  const args = text.trim().split(/\s+/);
  const argMap = {};
  for (let i = 0; i < pragma.args.length; i++) {
    const argument = pragma.args[i];
    if (!args[i] && !argument.optional) {
      return "fail";
    }
    if (argument.captureSpan) {
      return Debug.fail("Capture spans not yet implemented for non-xml pragmas");
    }
    argMap[argument.name] = args[i];
  }
  return argMap;
}
export function tagNamesAreEquivalent(lhs, rhs) {
  if (lhs.kind !== rhs.kind) {
    return false;
  }
  if (lhs.kind === SyntaxKind.Identifier) {
    return lhs.escapedText === rhs.escapedText;
  }
  if (lhs.kind === SyntaxKind.ThisKeyword) {
    return true;
  }
  if (lhs.kind === SyntaxKind.JsxNamespacedName) {
    return lhs.namespace.escapedText === rhs.namespace.escapedText && lhs.name.escapedText === rhs.name.escapedText;
  }
  return lhs.name.escapedText === rhs.name.escapedText && tagNamesAreEquivalent(lhs.expression, rhs.expression);
}
