import inspect from "../jsutils/inspect.mjs"; import devAssert from "../jsutils/devAssert.mjs"; import { syntaxError } from "../error/syntaxError.mjs"; import { Kind } from "./kinds.mjs"; import { Location } from "./ast.mjs"; import { Source } from "./source.mjs"; import { TokenKind } from "./tokenKind.mjs"; import { DirectiveLocation } from "./directiveLocation.mjs"; import { Lexer, isPunctuatorTokenKind } from "./lexer.mjs"; /** * Configuration options to control parser behavior */ /** * Given a GraphQL source, parses it into a Document. * Throws GraphQLError if a syntax error is encountered. */ export function parse(source, options) { var parser = new Parser(source, options); return parser.parseDocument(); } /** * Given a string containing a GraphQL value (ex. `[42]`), parse the AST for * that value. * Throws GraphQLError if a syntax error is encountered. * * This is useful within tools that operate upon GraphQL Values directly and * in isolation of complete GraphQL documents. * * Consider providing the results to the utility function: valueFromAST(). */ export function parseValue(source, options) { var parser = new Parser(source, options); parser.expectToken(TokenKind.SOF); var value = parser.parseValueLiteral(false); parser.expectToken(TokenKind.EOF); return value; } /** * Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for * that type. * Throws GraphQLError if a syntax error is encountered. * * This is useful within tools that operate upon GraphQL Types directly and * in isolation of complete GraphQL documents. * * Consider providing the results to the utility function: typeFromAST(). */ export function parseType(source, options) { var parser = new Parser(source, options); parser.expectToken(TokenKind.SOF); var type = parser.parseTypeReference(); parser.expectToken(TokenKind.EOF); return type; } var Parser = /*#__PURE__*/function () { function Parser(source, options) { var sourceObj = typeof source === 'string' ? new Source(source) : source; sourceObj instanceof Source || devAssert(0, "Must provide Source. Received: ".concat(inspect(sourceObj), ".")); this._lexer = new Lexer(sourceObj); this._options = options; } /** * Converts a name lex token into a name parse node. */ var _proto = Parser.prototype; _proto.parseName = function parseName() { var token = this.expectToken(TokenKind.NAME); return { kind: Kind.NAME, value: token.value, loc: this.loc(token) }; } // Implements the parsing rules in the Document section. /** * Document : Definition+ */ ; _proto.parseDocument = function parseDocument() { var start = this._lexer.token; return { kind: Kind.DOCUMENT, definitions: this.many(TokenKind.SOF, this.parseDefinition, TokenKind.EOF), loc: this.loc(start) }; } /** * Definition : * - ExecutableDefinition * - TypeSystemDefinition * - TypeSystemExtension * * ExecutableDefinition : * - OperationDefinition * - FragmentDefinition */ ; _proto.parseDefinition = function parseDefinition() { if (this.peek(TokenKind.NAME)) { switch (this._lexer.token.value) { case 'query': case 'mutation': case 'subscription': return this.parseOperationDefinition(); case 'fragment': return this.parseFragmentDefinition(); case 'schema': case 'scalar': case 'type': case 'interface': case 'union': case 'enum': case 'input': case 'directive': return this.parseTypeSystemDefinition(); case 'extend': return this.parseTypeSystemExtension(); } } else if (this.peek(TokenKind.BRACE_L)) { return this.parseOperationDefinition(); } else if (this.peekDescription()) { return this.parseTypeSystemDefinition(); } throw this.unexpected(); } // Implements the parsing rules in the Operations section. /** * OperationDefinition : * - SelectionSet * - OperationType Name? VariableDefinitions? Directives? SelectionSet */ ; _proto.parseOperationDefinition = function parseOperationDefinition() { var start = this._lexer.token; if (this.peek(TokenKind.BRACE_L)) { return { kind: Kind.OPERATION_DEFINITION, operation: 'query', name: undefined, variableDefinitions: [], directives: [], selectionSet: this.parseSelectionSet(), loc: this.loc(start) }; } var operation = this.parseOperationType(); var name; if (this.peek(TokenKind.NAME)) { name = this.parseName(); } return { kind: Kind.OPERATION_DEFINITION, operation: operation, name: name, variableDefinitions: this.parseVariableDefinitions(), directives: this.parseDirectives(false), selectionSet: this.parseSelectionSet(), loc: this.loc(start) }; } /** * OperationType : one of query mutation subscription */ ; _proto.parseOperationType = function parseOperationType() { var operationToken = this.expectToken(TokenKind.NAME); switch (operationToken.value) { case 'query': return 'query'; case 'mutation': return 'mutation'; case 'subscription': return 'subscription'; } throw this.unexpected(operationToken); } /** * VariableDefinitions : ( VariableDefinition+ ) */ ; _proto.parseVariableDefinitions = function parseVariableDefinitions() { return this.optionalMany(TokenKind.PAREN_L, this.parseVariableDefinition, TokenKind.PAREN_R); } /** * VariableDefinition : Variable : Type DefaultValue? Directives[Const]? */ ; _proto.parseVariableDefinition = function parseVariableDefinition() { var start = this._lexer.token; return { kind: Kind.VARIABLE_DEFINITION, variable: this.parseVariable(), type: (this.expectToken(TokenKind.COLON), this.parseTypeReference()), defaultValue: this.expectOptionalToken(TokenKind.EQUALS) ? this.parseValueLiteral(true) : undefined, directives: this.parseDirectives(true), loc: this.loc(start) }; } /** * Variable : $ Name */ ; _proto.parseVariable = function parseVariable() { var start = this._lexer.token; this.expectToken(TokenKind.DOLLAR); return { kind: Kind.VARIABLE, name: this.parseName(), loc: this.loc(start) }; } /** * SelectionSet : { Selection+ } */ ; _proto.parseSelectionSet = function parseSelectionSet() { var start = this._lexer.token; return { kind: Kind.SELECTION_SET, selections: this.many(TokenKind.BRACE_L, this.parseSelection, TokenKind.BRACE_R), loc: this.loc(start) }; } /** * Selection : * - Field * - FragmentSpread * - InlineFragment */ ; _proto.parseSelection = function parseSelection() { return this.peek(TokenKind.SPREAD) ? this.parseFragment() : this.parseField(); } /** * Field : Alias? Name Arguments? Directives? SelectionSet? * * Alias : Name : */ ; _proto.parseField = function parseField() { var start = this._lexer.token; var nameOrAlias = this.parseName(); var alias; var name; if (this.expectOptionalToken(TokenKind.COLON)) { alias = nameOrAlias; name = this.parseName(); } else { name = nameOrAlias; } return { kind: Kind.FIELD, alias: alias, name: name, arguments: this.parseArguments(false), directives: this.parseDirectives(false), selectionSet: this.peek(TokenKind.BRACE_L) ? this.parseSelectionSet() : undefined, loc: this.loc(start) }; } /** * Arguments[Const] : ( Argument[?Const]+ ) */ ; _proto.parseArguments = function parseArguments(isConst) { var item = isConst ? this.parseConstArgument : this.parseArgument; return this.optionalMany(TokenKind.PAREN_L, item, TokenKind.PAREN_R); } /** * Argument[Const] : Name : Value[?Const] */ ; _proto.parseArgument = function parseArgument() { var start = this._lexer.token; var name = this.parseName(); this.expectToken(TokenKind.COLON); return { kind: Kind.ARGUMENT, name: name, value: this.parseValueLiteral(false), loc: this.loc(start) }; }; _proto.parseConstArgument = function parseConstArgument() { var start = this._lexer.token; return { kind: Kind.ARGUMENT, name: this.parseName(), value: (this.expectToken(TokenKind.COLON), this.parseValueLiteral(true)), loc: this.loc(start) }; } // Implements the parsing rules in the Fragments section. /** * Corresponds to both FragmentSpread and InlineFragment in the spec. * * FragmentSpread : ... FragmentName Directives? * * InlineFragment : ... TypeCondition? Directives? SelectionSet */ ; _proto.parseFragment = function parseFragment() { var start = this._lexer.token; this.expectToken(TokenKind.SPREAD); var hasTypeCondition = this.expectOptionalKeyword('on'); if (!hasTypeCondition && this.peek(TokenKind.NAME)) { return { kind: Kind.FRAGMENT_SPREAD, name: this.parseFragmentName(), directives: this.parseDirectives(false), loc: this.loc(start) }; } return { kind: Kind.INLINE_FRAGMENT, typeCondition: hasTypeCondition ? this.parseNamedType() : undefined, directives: this.parseDirectives(false), selectionSet: this.parseSelectionSet(), loc: this.loc(start) }; } /** * FragmentDefinition : * - fragment FragmentName on TypeCondition Directives? SelectionSet * * TypeCondition : NamedType */ ; _proto.parseFragmentDefinition = function parseFragmentDefinition() { var _this$_options; var start = this._lexer.token; this.expectKeyword('fragment'); // Experimental support for defining variables within fragments changes // the grammar of FragmentDefinition: // - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet if (((_this$_options = this._options) === null || _this$_options === void 0 ? void 0 : _this$_options.experimentalFragmentVariables) === true) { return { kind: Kind.FRAGMENT_DEFINITION, name: this.parseFragmentName(), variableDefinitions: this.parseVariableDefinitions(), typeCondition: (this.expectKeyword('on'), this.parseNamedType()), directives: this.parseDirectives(false), selectionSet: this.parseSelectionSet(), loc: this.loc(start) }; } return { kind: Kind.FRAGMENT_DEFINITION, name: this.parseFragmentName(), typeCondition: (this.expectKeyword('on'), this.parseNamedType()), directives: this.parseDirectives(false), selectionSet: this.parseSelectionSet(), loc: this.loc(start) }; } /** * FragmentName : Name but not `on` */ ; _proto.parseFragmentName = function parseFragmentName() { if (this._lexer.token.value === 'on') { throw this.unexpected(); } return this.parseName(); } // Implements the parsing rules in the Values section. /** * Value[Const] : * - [~Const] Variable * - IntValue * - FloatValue * - StringValue * - BooleanValue * - NullValue * - EnumValue * - ListValue[?Const] * - ObjectValue[?Const] * * BooleanValue : one of `true` `false` * * NullValue : `null` * * EnumValue : Name but not `true`, `false` or `null` */ ; _proto.parseValueLiteral = function parseValueLiteral(isConst) { var token = this._lexer.token; switch (token.kind) { case TokenKind.BRACKET_L: return this.parseList(isConst); case TokenKind.BRACE_L: return this.parseObject(isConst); case TokenKind.INT: this._lexer.advance(); return { kind: Kind.INT, value: token.value, loc: this.loc(token) }; case TokenKind.FLOAT: this._lexer.advance(); return { kind: Kind.FLOAT, value: token.value, loc: this.loc(token) }; case TokenKind.STRING: case TokenKind.BLOCK_STRING: return this.parseStringLiteral(); case TokenKind.NAME: this._lexer.advance(); switch (token.value) { case 'true': return { kind: Kind.BOOLEAN, value: true, loc: this.loc(token) }; case 'false': return { kind: Kind.BOOLEAN, value: false, loc: this.loc(token) }; case 'null': return { kind: Kind.NULL, loc: this.loc(token) }; default: return { kind: Kind.ENUM, value: token.value, loc: this.loc(token) }; } case TokenKind.DOLLAR: if (!isConst) { return this.parseVariable(); } break; } throw this.unexpected(); }; _proto.parseStringLiteral = function parseStringLiteral() { var token = this._lexer.token; this._lexer.advance(); return { kind: Kind.STRING, value: token.value, block: token.kind === TokenKind.BLOCK_STRING, loc: this.loc(token) }; } /** * ListValue[Const] : * - [ ] * - [ Value[?Const]+ ] */ ; _proto.parseList = function parseList(isConst) { var _this = this; var start = this._lexer.token; var item = function item() { return _this.parseValueLiteral(isConst); }; return { kind: Kind.LIST, values: this.any(TokenKind.BRACKET_L, item, TokenKind.BRACKET_R), loc: this.loc(start) }; } /** * ObjectValue[Const] : * - { } * - { ObjectField[?Const]+ } */ ; _proto.parseObject = function parseObject(isConst) { var _this2 = this; var start = this._lexer.token; var item = function item() { return _this2.parseObjectField(isConst); }; return { kind: Kind.OBJECT, fields: this.any(TokenKind.BRACE_L, item, TokenKind.BRACE_R), loc: this.loc(start) }; } /** * ObjectField[Const] : Name : Value[?Const] */ ; _proto.parseObjectField = function parseObjectField(isConst) { var start = this._lexer.token; var name = this.parseName(); this.expectToken(TokenKind.COLON); return { kind: Kind.OBJECT_FIELD, name: name, value: this.parseValueLiteral(isConst), loc: this.loc(start) }; } // Implements the parsing rules in the Directives section. /** * Directives[Const] : Directive[?Const]+ */ ; _proto.parseDirectives = function parseDirectives(isConst) { var directives = []; while (this.peek(TokenKind.AT)) { directives.push(this.parseDirective(isConst)); } return directives; } /** * Directive[Const] : @ Name Arguments[?Const]? */ ; _proto.parseDirective = function parseDirective(isConst) { var start = this._lexer.token; this.expectToken(TokenKind.AT); return { kind: Kind.DIRECTIVE, name: this.parseName(), arguments: this.parseArguments(isConst), loc: this.loc(start) }; } // Implements the parsing rules in the Types section. /** * Type : * - NamedType * - ListType * - NonNullType */ ; _proto.parseTypeReference = function parseTypeReference() { var start = this._lexer.token; var type; if (this.expectOptionalToken(TokenKind.BRACKET_L)) { type = this.parseTypeReference(); this.expectToken(TokenKind.BRACKET_R); type = { kind: Kind.LIST_TYPE, type: type, loc: this.loc(start) }; } else { type = this.parseNamedType(); } if (this.expectOptionalToken(TokenKind.BANG)) { return { kind: Kind.NON_NULL_TYPE, type: type, loc: this.loc(start) }; } return type; } /** * NamedType : Name */ ; _proto.parseNamedType = function parseNamedType() { var start = this._lexer.token; return { kind: Kind.NAMED_TYPE, name: this.parseName(), loc: this.loc(start) }; } // Implements the parsing rules in the Type Definition section. /** * TypeSystemDefinition : * - SchemaDefinition * - TypeDefinition * - DirectiveDefinition * * TypeDefinition : * - ScalarTypeDefinition * - ObjectTypeDefinition * - InterfaceTypeDefinition * - UnionTypeDefinition * - EnumTypeDefinition * - InputObjectTypeDefinition */ ; _proto.parseTypeSystemDefinition = function parseTypeSystemDefinition() { // Many definitions begin with a description and require a lookahead. var keywordToken = this.peekDescription() ? this._lexer.lookahead() : this._lexer.token; if (keywordToken.kind === TokenKind.NAME) { switch (keywordToken.value) { case 'schema': return this.parseSchemaDefinition(); case 'scalar': return this.parseScalarTypeDefinition(); case 'type': return this.parseObjectTypeDefinition(); case 'interface': return this.parseInterfaceTypeDefinition(); case 'union': return this.parseUnionTypeDefinition(); case 'enum': return this.parseEnumTypeDefinition(); case 'input': return this.parseInputObjectTypeDefinition(); case 'directive': return this.parseDirectiveDefinition(); } } throw this.unexpected(keywordToken); }; _proto.peekDescription = function peekDescription() { return this.peek(TokenKind.STRING) || this.peek(TokenKind.BLOCK_STRING); } /** * Description : StringValue */ ; _proto.parseDescription = function parseDescription() { if (this.peekDescription()) { return this.parseStringLiteral(); } } /** * SchemaDefinition : Description? schema Directives[Const]? { OperationTypeDefinition+ } */ ; _proto.parseSchemaDefinition = function parseSchemaDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('schema'); var directives = this.parseDirectives(true); var operationTypes = this.many(TokenKind.BRACE_L, this.parseOperationTypeDefinition, TokenKind.BRACE_R); return { kind: Kind.SCHEMA_DEFINITION, description: description, directives: directives, operationTypes: operationTypes, loc: this.loc(start) }; } /** * OperationTypeDefinition : OperationType : NamedType */ ; _proto.parseOperationTypeDefinition = function parseOperationTypeDefinition() { var start = this._lexer.token; var operation = this.parseOperationType(); this.expectToken(TokenKind.COLON); var type = this.parseNamedType(); return { kind: Kind.OPERATION_TYPE_DEFINITION, operation: operation, type: type, loc: this.loc(start) }; } /** * ScalarTypeDefinition : Description? scalar Name Directives[Const]? */ ; _proto.parseScalarTypeDefinition = function parseScalarTypeDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('scalar'); var name = this.parseName(); var directives = this.parseDirectives(true); return { kind: Kind.SCALAR_TYPE_DEFINITION, description: description, name: name, directives: directives, loc: this.loc(start) }; } /** * ObjectTypeDefinition : * Description? * type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition? */ ; _proto.parseObjectTypeDefinition = function parseObjectTypeDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('type'); var name = this.parseName(); var interfaces = this.parseImplementsInterfaces(); var directives = this.parseDirectives(true); var fields = this.parseFieldsDefinition(); return { kind: Kind.OBJECT_TYPE_DEFINITION, description: description, name: name, interfaces: interfaces, directives: directives, fields: fields, loc: this.loc(start) }; } /** * ImplementsInterfaces : * - implements `&`? NamedType * - ImplementsInterfaces & NamedType */ ; _proto.parseImplementsInterfaces = function parseImplementsInterfaces() { var types = []; if (this.expectOptionalKeyword('implements')) { // Optional leading ampersand this.expectOptionalToken(TokenKind.AMP); do { var _this$_options2; types.push(this.parseNamedType()); } while (this.expectOptionalToken(TokenKind.AMP) || // Legacy support for the SDL? ((_this$_options2 = this._options) === null || _this$_options2 === void 0 ? void 0 : _this$_options2.allowLegacySDLImplementsInterfaces) === true && this.peek(TokenKind.NAME)); } return types; } /** * FieldsDefinition : { FieldDefinition+ } */ ; _proto.parseFieldsDefinition = function parseFieldsDefinition() { var _this$_options3; // Legacy support for the SDL? if (((_this$_options3 = this._options) === null || _this$_options3 === void 0 ? void 0 : _this$_options3.allowLegacySDLEmptyFields) === true && this.peek(TokenKind.BRACE_L) && this._lexer.lookahead().kind === TokenKind.BRACE_R) { this._lexer.advance(); this._lexer.advance(); return []; } return this.optionalMany(TokenKind.BRACE_L, this.parseFieldDefinition, TokenKind.BRACE_R); } /** * FieldDefinition : * - Description? Name ArgumentsDefinition? : Type Directives[Const]? */ ; _proto.parseFieldDefinition = function parseFieldDefinition() { var start = this._lexer.token; var description = this.parseDescription(); var name = this.parseName(); var args = this.parseArgumentDefs(); this.expectToken(TokenKind.COLON); var type = this.parseTypeReference(); var directives = this.parseDirectives(true); return { kind: Kind.FIELD_DEFINITION, description: description, name: name, arguments: args, type: type, directives: directives, loc: this.loc(start) }; } /** * ArgumentsDefinition : ( InputValueDefinition+ ) */ ; _proto.parseArgumentDefs = function parseArgumentDefs() { return this.optionalMany(TokenKind.PAREN_L, this.parseInputValueDef, TokenKind.PAREN_R); } /** * InputValueDefinition : * - Description? Name : Type DefaultValue? Directives[Const]? */ ; _proto.parseInputValueDef = function parseInputValueDef() { var start = this._lexer.token; var description = this.parseDescription(); var name = this.parseName(); this.expectToken(TokenKind.COLON); var type = this.parseTypeReference(); var defaultValue; if (this.expectOptionalToken(TokenKind.EQUALS)) { defaultValue = this.parseValueLiteral(true); } var directives = this.parseDirectives(true); return { kind: Kind.INPUT_VALUE_DEFINITION, description: description, name: name, type: type, defaultValue: defaultValue, directives: directives, loc: this.loc(start) }; } /** * InterfaceTypeDefinition : * - Description? interface Name Directives[Const]? FieldsDefinition? */ ; _proto.parseInterfaceTypeDefinition = function parseInterfaceTypeDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('interface'); var name = this.parseName(); var interfaces = this.parseImplementsInterfaces(); var directives = this.parseDirectives(true); var fields = this.parseFieldsDefinition(); return { kind: Kind.INTERFACE_TYPE_DEFINITION, description: description, name: name, interfaces: interfaces, directives: directives, fields: fields, loc: this.loc(start) }; } /** * UnionTypeDefinition : * - Description? union Name Directives[Const]? UnionMemberTypes? */ ; _proto.parseUnionTypeDefinition = function parseUnionTypeDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('union'); var name = this.parseName(); var directives = this.parseDirectives(true); var types = this.parseUnionMemberTypes(); return { kind: Kind.UNION_TYPE_DEFINITION, description: description, name: name, directives: directives, types: types, loc: this.loc(start) }; } /** * UnionMemberTypes : * - = `|`? NamedType * - UnionMemberTypes | NamedType */ ; _proto.parseUnionMemberTypes = function parseUnionMemberTypes() { var types = []; if (this.expectOptionalToken(TokenKind.EQUALS)) { // Optional leading pipe this.expectOptionalToken(TokenKind.PIPE); do { types.push(this.parseNamedType()); } while (this.expectOptionalToken(TokenKind.PIPE)); } return types; } /** * EnumTypeDefinition : * - Description? enum Name Directives[Const]? EnumValuesDefinition? */ ; _proto.parseEnumTypeDefinition = function parseEnumTypeDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('enum'); var name = this.parseName(); var directives = this.parseDirectives(true); var values = this.parseEnumValuesDefinition(); return { kind: Kind.ENUM_TYPE_DEFINITION, description: description, name: name, directives: directives, values: values, loc: this.loc(start) }; } /** * EnumValuesDefinition : { EnumValueDefinition+ } */ ; _proto.parseEnumValuesDefinition = function parseEnumValuesDefinition() { return this.optionalMany(TokenKind.BRACE_L, this.parseEnumValueDefinition, TokenKind.BRACE_R); } /** * EnumValueDefinition : Description? EnumValue Directives[Const]? * * EnumValue : Name */ ; _proto.parseEnumValueDefinition = function parseEnumValueDefinition() { var start = this._lexer.token; var description = this.parseDescription(); var name = this.parseName(); var directives = this.parseDirectives(true); return { kind: Kind.ENUM_VALUE_DEFINITION, description: description, name: name, directives: directives, loc: this.loc(start) }; } /** * InputObjectTypeDefinition : * - Description? input Name Directives[Const]? InputFieldsDefinition? */ ; _proto.parseInputObjectTypeDefinition = function parseInputObjectTypeDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('input'); var name = this.parseName(); var directives = this.parseDirectives(true); var fields = this.parseInputFieldsDefinition(); return { kind: Kind.INPUT_OBJECT_TYPE_DEFINITION, description: description, name: name, directives: directives, fields: fields, loc: this.loc(start) }; } /** * InputFieldsDefinition : { InputValueDefinition+ } */ ; _proto.parseInputFieldsDefinition = function parseInputFieldsDefinition() { return this.optionalMany(TokenKind.BRACE_L, this.parseInputValueDef, TokenKind.BRACE_R); } /** * TypeSystemExtension : * - SchemaExtension * - TypeExtension * * TypeExtension : * - ScalarTypeExtension * - ObjectTypeExtension * - InterfaceTypeExtension * - UnionTypeExtension * - EnumTypeExtension * - InputObjectTypeDefinition */ ; _proto.parseTypeSystemExtension = function parseTypeSystemExtension() { var keywordToken = this._lexer.lookahead(); if (keywordToken.kind === TokenKind.NAME) { switch (keywordToken.value) { case 'schema': return this.parseSchemaExtension(); case 'scalar': return this.parseScalarTypeExtension(); case 'type': return this.parseObjectTypeExtension(); case 'interface': return this.parseInterfaceTypeExtension(); case 'union': return this.parseUnionTypeExtension(); case 'enum': return this.parseEnumTypeExtension(); case 'input': return this.parseInputObjectTypeExtension(); } } throw this.unexpected(keywordToken); } /** * SchemaExtension : * - extend schema Directives[Const]? { OperationTypeDefinition+ } * - extend schema Directives[Const] */ ; _proto.parseSchemaExtension = function parseSchemaExtension() { var start = this._lexer.token; this.expectKeyword('extend'); this.expectKeyword('schema'); var directives = this.parseDirectives(true); var operationTypes = this.optionalMany(TokenKind.BRACE_L, this.parseOperationTypeDefinition, TokenKind.BRACE_R); if (directives.length === 0 && operationTypes.length === 0) { throw this.unexpected(); } return { kind: Kind.SCHEMA_EXTENSION, directives: directives, operationTypes: operationTypes, loc: this.loc(start) }; } /** * ScalarTypeExtension : * - extend scalar Name Directives[Const] */ ; _proto.parseScalarTypeExtension = function parseScalarTypeExtension() { var start = this._lexer.token; this.expectKeyword('extend'); this.expectKeyword('scalar'); var name = this.parseName(); var directives = this.parseDirectives(true); if (directives.length === 0) { throw this.unexpected(); } return { kind: Kind.SCALAR_TYPE_EXTENSION, name: name, directives: directives, loc: this.loc(start) }; } /** * ObjectTypeExtension : * - extend type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition * - extend type Name ImplementsInterfaces? Directives[Const] * - extend type Name ImplementsInterfaces */ ; _proto.parseObjectTypeExtension = function parseObjectTypeExtension() { var start = this._lexer.token; this.expectKeyword('extend'); this.expectKeyword('type'); var name = this.parseName(); var interfaces = this.parseImplementsInterfaces(); var directives = this.parseDirectives(true); var fields = this.parseFieldsDefinition(); if (interfaces.length === 0 && directives.length === 0 && fields.length === 0) { throw this.unexpected(); } return { kind: Kind.OBJECT_TYPE_EXTENSION, name: name, interfaces: interfaces, directives: directives, fields: fields, loc: this.loc(start) }; } /** * InterfaceTypeExtension : * - extend interface Name ImplementsInterfaces? Directives[Const]? FieldsDefinition * - extend interface Name ImplementsInterfaces? Directives[Const] * - extend interface Name ImplementsInterfaces */ ; _proto.parseInterfaceTypeExtension = function parseInterfaceTypeExtension() { var start = this._lexer.token; this.expectKeyword('extend'); this.expectKeyword('interface'); var name = this.parseName(); var interfaces = this.parseImplementsInterfaces(); var directives = this.parseDirectives(true); var fields = this.parseFieldsDefinition(); if (interfaces.length === 0 && directives.length === 0 && fields.length === 0) { throw this.unexpected(); } return { kind: Kind.INTERFACE_TYPE_EXTENSION, name: name, interfaces: interfaces, directives: directives, fields: fields, loc: this.loc(start) }; } /** * UnionTypeExtension : * - extend union Name Directives[Const]? UnionMemberTypes * - extend union Name Directives[Const] */ ; _proto.parseUnionTypeExtension = function parseUnionTypeExtension() { var start = this._lexer.token; this.expectKeyword('extend'); this.expectKeyword('union'); var name = this.parseName(); var directives = this.parseDirectives(true); var types = this.parseUnionMemberTypes(); if (directives.length === 0 && types.length === 0) { throw this.unexpected(); } return { kind: Kind.UNION_TYPE_EXTENSION, name: name, directives: directives, types: types, loc: this.loc(start) }; } /** * EnumTypeExtension : * - extend enum Name Directives[Const]? EnumValuesDefinition * - extend enum Name Directives[Const] */ ; _proto.parseEnumTypeExtension = function parseEnumTypeExtension() { var start = this._lexer.token; this.expectKeyword('extend'); this.expectKeyword('enum'); var name = this.parseName(); var directives = this.parseDirectives(true); var values = this.parseEnumValuesDefinition(); if (directives.length === 0 && values.length === 0) { throw this.unexpected(); } return { kind: Kind.ENUM_TYPE_EXTENSION, name: name, directives: directives, values: values, loc: this.loc(start) }; } /** * InputObjectTypeExtension : * - extend input Name Directives[Const]? InputFieldsDefinition * - extend input Name Directives[Const] */ ; _proto.parseInputObjectTypeExtension = function parseInputObjectTypeExtension() { var start = this._lexer.token; this.expectKeyword('extend'); this.expectKeyword('input'); var name = this.parseName(); var directives = this.parseDirectives(true); var fields = this.parseInputFieldsDefinition(); if (directives.length === 0 && fields.length === 0) { throw this.unexpected(); } return { kind: Kind.INPUT_OBJECT_TYPE_EXTENSION, name: name, directives: directives, fields: fields, loc: this.loc(start) }; } /** * DirectiveDefinition : * - Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations */ ; _proto.parseDirectiveDefinition = function parseDirectiveDefinition() { var start = this._lexer.token; var description = this.parseDescription(); this.expectKeyword('directive'); this.expectToken(TokenKind.AT); var name = this.parseName(); var args = this.parseArgumentDefs(); var repeatable = this.expectOptionalKeyword('repeatable'); this.expectKeyword('on'); var locations = this.parseDirectiveLocations(); return { kind: Kind.DIRECTIVE_DEFINITION, description: description, name: name, arguments: args, repeatable: repeatable, locations: locations, loc: this.loc(start) }; } /** * DirectiveLocations : * - `|`? DirectiveLocation * - DirectiveLocations | DirectiveLocation */ ; _proto.parseDirectiveLocations = function parseDirectiveLocations() { // Optional leading pipe this.expectOptionalToken(TokenKind.PIPE); var locations = []; do { locations.push(this.parseDirectiveLocation()); } while (this.expectOptionalToken(TokenKind.PIPE)); return locations; } /* * DirectiveLocation : * - ExecutableDirectiveLocation * - TypeSystemDirectiveLocation * * ExecutableDirectiveLocation : one of * `QUERY` * `MUTATION` * `SUBSCRIPTION` * `FIELD` * `FRAGMENT_DEFINITION` * `FRAGMENT_SPREAD` * `INLINE_FRAGMENT` * * TypeSystemDirectiveLocation : one of * `SCHEMA` * `SCALAR` * `OBJECT` * `FIELD_DEFINITION` * `ARGUMENT_DEFINITION` * `INTERFACE` * `UNION` * `ENUM` * `ENUM_VALUE` * `INPUT_OBJECT` * `INPUT_FIELD_DEFINITION` */ ; _proto.parseDirectiveLocation = function parseDirectiveLocation() { var start = this._lexer.token; var name = this.parseName(); if (DirectiveLocation[name.value] !== undefined) { return name; } throw this.unexpected(start); } // Core parsing utility functions /** * Returns a location object, used to identify the place in * the source that created a given parsed object. */ ; _proto.loc = function loc(startToken) { var _this$_options4; if (((_this$_options4 = this._options) === null || _this$_options4 === void 0 ? void 0 : _this$_options4.noLocation) !== true) { return new Location(startToken, this._lexer.lastToken, this._lexer.source); } } /** * Determines if the next token is of a given kind */ ; _proto.peek = function peek(kind) { return this._lexer.token.kind === kind; } /** * If the next token is of the given kind, return that token after advancing * the lexer. Otherwise, do not change the parser state and throw an error. */ ; _proto.expectToken = function expectToken(kind) { var token = this._lexer.token; if (token.kind === kind) { this._lexer.advance(); return token; } throw syntaxError(this._lexer.source, token.start, "Expected ".concat(getTokenKindDesc(kind), ", found ").concat(getTokenDesc(token), ".")); } /** * If the next token is of the given kind, return that token after advancing * the lexer. Otherwise, do not change the parser state and return undefined. */ ; _proto.expectOptionalToken = function expectOptionalToken(kind) { var token = this._lexer.token; if (token.kind === kind) { this._lexer.advance(); return token; } return undefined; } /** * If the next token is a given keyword, advance the lexer. * Otherwise, do not change the parser state and throw an error. */ ; _proto.expectKeyword = function expectKeyword(value) { var token = this._lexer.token; if (token.kind === TokenKind.NAME && token.value === value) { this._lexer.advance(); } else { throw syntaxError(this._lexer.source, token.start, "Expected \"".concat(value, "\", found ").concat(getTokenDesc(token), ".")); } } /** * If the next token is a given keyword, return "true" after advancing * the lexer. Otherwise, do not change the parser state and return "false". */ ; _proto.expectOptionalKeyword = function expectOptionalKeyword(value) { var token = this._lexer.token; if (token.kind === TokenKind.NAME && token.value === value) { this._lexer.advance(); return true; } return false; } /** * Helper function for creating an error when an unexpected lexed token * is encountered. */ ; _proto.unexpected = function unexpected(atToken) { var token = atToken !== null && atToken !== void 0 ? atToken : this._lexer.token; return syntaxError(this._lexer.source, token.start, "Unexpected ".concat(getTokenDesc(token), ".")); } /** * Returns a possibly empty list of parse nodes, determined by * the parseFn. This list begins with a lex token of openKind * and ends with a lex token of closeKind. Advances the parser * to the next lex token after the closing token. */ ; _proto.any = function any(openKind, parseFn, closeKind) { this.expectToken(openKind); var nodes = []; while (!this.expectOptionalToken(closeKind)) { nodes.push(parseFn.call(this)); } return nodes; } /** * Returns a list of parse nodes, determined by the parseFn. * It can be empty only if open token is missing otherwise it will always * return non-empty list that begins with a lex token of openKind and ends * with a lex token of closeKind. Advances the parser to the next lex token * after the closing token. */ ; _proto.optionalMany = function optionalMany(openKind, parseFn, closeKind) { if (this.expectOptionalToken(openKind)) { var nodes = []; do { nodes.push(parseFn.call(this)); } while (!this.expectOptionalToken(closeKind)); return nodes; } return []; } /** * Returns a non-empty list of parse nodes, determined by * the parseFn. This list begins with a lex token of openKind * and ends with a lex token of closeKind. Advances the parser * to the next lex token after the closing token. */ ; _proto.many = function many(openKind, parseFn, closeKind) { this.expectToken(openKind); var nodes = []; do { nodes.push(parseFn.call(this)); } while (!this.expectOptionalToken(closeKind)); return nodes; }; return Parser; }(); /** * A helper function to describe a token as a string for debugging */ function getTokenDesc(token) { var value = token.value; return getTokenKindDesc(token.kind) + (value != null ? " \"".concat(value, "\"") : ''); } /** * A helper function to describe a token kind as a string for debugging */ function getTokenKindDesc(kind) { return isPunctuatorTokenKind(kind) ? "\"".concat(kind, "\"") : kind; }