text: "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.parse = parse;
  exports.parseValue = parseValue;
  exports.parseType = parseType;
  exports.parseConstValue = parseConstValue;
  exports.parseTypeReference = parseTypeReference;
  exports.parseNamedType = parseNamedType;
  
  var _inspect = _interopRequireDefault(require("../jsutils/inspect"));
  
  var _defineToJSON = _interopRequireDefault(require("../jsutils/defineToJSON"));
  
  var _source = require("./source");
  
  var _error = require("../error");
  
  var _lexer = require("./lexer");
  
  var _kinds = require("./kinds");
  
  var _directiveLocation = require("./directiveLocation");
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * Copyright (c) 2015-present, Facebook, Inc.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   *
   * 
   */
  
  /**
   * Given a GraphQL source, parses it into a Document.
   * Throws GraphQLError if a syntax error is encountered.
   */
  function parse(source, options) {
    var sourceObj = typeof source === 'string' ? new _source.Source(source) : source;
  
    if (!(sourceObj instanceof _source.Source)) {
      throw new TypeError("Must provide Source. Received: ".concat((0, _inspect.default)(sourceObj)));
    }
  
    var lexer = (0, _lexer.createLexer)(sourceObj, options || {});
    return parseDocument(lexer);
  }
  /**
   * 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().
   */
  
  
  function parseValue(source, options) {
    var sourceObj = typeof source === 'string' ? new _source.Source(source) : source;
    var lexer = (0, _lexer.createLexer)(sourceObj, options || {});
    expect(lexer, _lexer.TokenKind.SOF);
    var value = parseValueLiteral(lexer, false);
    expect(lexer, _lexer.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().
   */
  
  
  function parseType(source, options) {
    var sourceObj = typeof source === 'string' ? new _source.Source(source) : source;
    var lexer = (0, _lexer.createLexer)(sourceObj, options || {});
    expect(lexer, _lexer.TokenKind.SOF);
    var type = parseTypeReference(lexer);
    expect(lexer, _lexer.TokenKind.EOF);
    return type;
  }
  /**
   * Converts a name lex token into a name parse node.
   */
  
  
  function parseName(lexer) {
    var token = expect(lexer, _lexer.TokenKind.NAME);
    return {
      kind: _kinds.Kind.NAME,
      value: token.value,
      loc: loc(lexer, token)
    };
  } // Implements the parsing rules in the Document section.
  
  /**
   * Document : Definition+
   */
  
  
  function parseDocument(lexer) {
    var start = lexer.token;
    return {
      kind: _kinds.Kind.DOCUMENT,
      definitions: many(lexer, _lexer.TokenKind.SOF, parseDefinition, _lexer.TokenKind.EOF),
      loc: loc(lexer, start)
    };
  }
  /**
   * Definition :
   *   - ExecutableDefinition
   *   - TypeSystemDefinition
   *   - TypeSystemExtension
   */
  
  
  function parseDefinition(lexer) {
    if (peek(lexer, _lexer.TokenKind.NAME)) {
      switch (lexer.token.value) {
        case 'query':
        case 'mutation':
        case 'subscription':
        case 'fragment':
          return parseExecutableDefinition(lexer);
  
        case 'schema':
        case 'scalar':
        case 'type':
        case 'interface':
        case 'union':
        case 'enum':
        case 'input':
        case 'directive':
          return parseTypeSystemDefinition(lexer);
  
        case 'extend':
          return parseTypeSystemExtension(lexer);
      }
    } else if (peek(lexer, _lexer.TokenKind.BRACE_L)) {
      return parseExecutableDefinition(lexer);
    } else if (peekDescription(lexer)) {
      return parseTypeSystemDefinition(lexer);
    }
  
    throw unexpected(lexer);
  }
  /**
   * ExecutableDefinition :
   *   - OperationDefinition
   *   - FragmentDefinition
   */
  
  
  function parseExecutableDefinition(lexer) {
    if (peek(lexer, _lexer.TokenKind.NAME)) {
      switch (lexer.token.value) {
        case 'query':
        case 'mutation':
        case 'subscription':
          return parseOperationDefinition(lexer);
  
        case 'fragment':
          return parseFragmentDefinition(lexer);
      }
    } else if (peek(lexer, _lexer.TokenKind.BRACE_L)) {
      return parseOperationDefinition(lexer);
    }
  
    throw unexpected(lexer);
  } // Implements the parsing rules in the Operations section.
  
  /**
   * OperationDefinition :
   *  - SelectionSet
   *  - OperationType Name? VariableDefinitions? Directives? SelectionSet
   */
  
  
  function parseOperationDefinition(lexer) {
    var start = lexer.token;
  
    if (peek(lexer, _lexer.TokenKind.BRACE_L)) {
      return {
        kind: _kinds.Kind.OPERATION_DEFINITION,
        operation: 'query',
        name: undefined,
        variableDefinitions: [],
        directives: [],
        selectionSet: parseSelectionSet(lexer),
        loc: loc(lexer, start)
      };
    }
  
    var operation = parseOperationType(lexer);
    var name;
  
    if (peek(lexer, _lexer.TokenKind.NAME)) {
      name = parseName(lexer);
    }
  
    return {
      kind: _kinds.Kind.OPERATION_DEFINITION,
      operation: operation,
      name: name,
      variableDefinitions: parseVariableDefinitions(lexer),
      directives: parseDirectives(lexer, false),
      selectionSet: parseSelectionSet(lexer),
      loc: loc(lexer, start)
    };
  }
  /**
   * OperationType : one of query mutation subscription
   */
  
  
  function parseOperationType(lexer) {
    var operationToken = expect(lexer, _lexer.TokenKind.NAME);
  
    switch (operationToken.value) {
      case 'query':
        return 'query';
  
      case 'mutation':
        return 'mutation';
  
      case 'subscription':
        return 'subscription';
    }
  
    throw unexpected(lexer, operationToken);
  }
  /**
   * VariableDefinitions : ( VariableDefinition+ )
   */
  
  
  function parseVariableDefinitions(lexer) {
    return peek(lexer, _lexer.TokenKind.PAREN_L) ? many(lexer, _lexer.TokenKind.PAREN_L, parseVariableDefinition, _lexer.TokenKind.PAREN_R) : [];
  }
  /**
   * VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
   */
  
  
  function parseVariableDefinition(lexer) {
    var start = lexer.token;
    return {
      kind: _kinds.Kind.VARIABLE_DEFINITION,
      variable: parseVariable(lexer),
      type: (expect(lexer, _lexer.TokenKind.COLON), parseTypeReference(lexer)),
      defaultValue: skip(lexer, _lexer.TokenKind.EQUALS) ? parseValueLiteral(lexer, true) : undefined,
      directives: parseDirectives(lexer, true),
      loc: loc(lexer, start)
    };
  }
  /**
   * Variable : $ Name
   */
  
  
  function parseVariable(lexer) {
    var start = lexer.token;
    expect(lexer, _lexer.TokenKind.DOLLAR);
    return {
      kind: _kinds.Kind.VARIABLE,
      name: parseName(lexer),
      loc: loc(lexer, start)
    };
  }
  /**
   * SelectionSet : { Selection+ }
   */
  
  
  function parseSelectionSet(lexer) {
    var start = lexer.token;
    return {
      kind: _kinds.Kind.SELECTION_SET,
      selections: many(lexer, _lexer.TokenKind.BRACE_L, parseSelection, _lexer.TokenKind.BRACE_R),
      loc: loc(lexer, start)
    };
  }
  /**
   * Selection :
   *   - Field
   *   - FragmentSpread
   *   - InlineFragment
   */
  
  
  function parseSelection(lexer) {
    return peek(lexer, _lexer.TokenKind.SPREAD) ? parseFragment(lexer) : parseField(lexer);
  }
  /**
   * Field : Alias? Name Arguments? Directives? SelectionSet?
   *
   * Alias : Name :
   */
  
  
  function parseField(lexer) {
    var start = lexer.token;
    var nameOrAlias = parseName(lexer);
    var alias;
    var name;
  
    if (skip(lexer, _lexer.TokenKind.COLON)) {
      alias = nameOrAlias;
      name = parseName(lexer);
    } else {
      name = nameOrAlias;
    }
  
    return {
      kind: _kinds.Kind.FIELD,
      alias: alias,
      name: name,
      arguments: parseArguments(lexer, false),
      directives: parseDirectives(lexer, false),
      selectionSet: peek(lexer, _lexer.TokenKind.BRACE_L) ? parseSelectionSet(lexer) : undefined,
      loc: loc(lexer, start)
    };
  }
  /**
   * Arguments[Const] : ( Argument[?Const]+ )
   */
  
  
  function parseArguments(lexer, isConst) {
    var item = isConst ? parseConstArgument : parseArgument;
    return peek(lexer, _lexer.TokenKind.PAREN_L) ? many(lexer, _lexer.TokenKind.PAREN_L, item, _lexer.TokenKind.PAREN_R) : [];
  }
  /**
   * Argument[Const] : Name : Value[?Const]
   */
  
  
  function parseArgument(lexer) {
    var start = lexer.token;
    return {
      kind: _kinds.Kind.ARGUMENT,
      name: parseName(lexer),
      value: (expect(lexer, _lexer.TokenKind.COLON), parseValueLiteral(lexer, false)),
      loc: loc(lexer, start)
    };
  }
  
  function parseConstArgument(lexer) {
    var start = lexer.token;
    return {
      kind: _kinds.Kind.ARGUMENT,
      name: parseName(lexer),
      value: (expect(lexer, _lexer.TokenKind.COLON), parseConstValue(lexer)),
      loc: loc(lexer, 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
   */
  
  
  function parseFragment(lexer) {
    var start = lexer.token;
    expect(lexer, _lexer.TokenKind.SPREAD);
    var hasTypeCondition = skipKeyword(lexer, 'on');
  
    if (!hasTypeCondition && peek(lexer, _lexer.TokenKind.NAME)) {
      return {
        kind: _kinds.Kind.FRAGMENT_SPREAD,
        name: parseFragmentName(lexer),
        directives: parseDirectives(lexer, false),
        loc: loc(lexer, start)
      };
    }
  
    return {
      kind: _kinds.Kind.INLINE_FRAGMENT,
      typeCondition: hasTypeCondition ? parseNamedType(lexer) : undefined,
      directives: parseDirectives(lexer, false),
      selectionSet: parseSelectionSet(lexer),
      loc: loc(lexer, start)
    };
  }
  /**
   * FragmentDefinition :
   *   - fragment FragmentName on TypeCondition Directives? SelectionSet
   *
   * TypeCondition : NamedType
   */
  
  
  function parseFragmentDefinition(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'fragment'); // Experimental support for defining variables within fragments changes
    // the grammar of FragmentDefinition:
    //   - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
  
    if (lexer.options.experimentalFragmentVariables) {
      return {
        kind: _kinds.Kind.FRAGMENT_DEFINITION,
        name: parseFragmentName(lexer),
        variableDefinitions: parseVariableDefinitions(lexer),
        typeCondition: (expectKeyword(lexer, 'on'), parseNamedType(lexer)),
        directives: parseDirectives(lexer, false),
        selectionSet: parseSelectionSet(lexer),
        loc: loc(lexer, start)
      };
    }
  
    return {
      kind: _kinds.Kind.FRAGMENT_DEFINITION,
      name: parseFragmentName(lexer),
      typeCondition: (expectKeyword(lexer, 'on'), parseNamedType(lexer)),
      directives: parseDirectives(lexer, false),
      selectionSet: parseSelectionSet(lexer),
      loc: loc(lexer, start)
    };
  }
  /**
   * FragmentName : Name but not `on`
   */
  
  
  function parseFragmentName(lexer) {
    if (lexer.token.value === 'on') {
      throw unexpected(lexer);
    }
  
    return parseName(lexer);
  } // 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`
   */
  
  
  function parseValueLiteral(lexer, isConst) {
    var token = lexer.token;
  
    switch (token.kind) {
      case _lexer.TokenKind.BRACKET_L:
        return parseList(lexer, isConst);
  
      case _lexer.TokenKind.BRACE_L:
        return parseObject(lexer, isConst);
  
      case _lexer.TokenKind.INT:
        lexer.advance();
        return {
          kind: _kinds.Kind.INT,
          value: token.value,
          loc: loc(lexer, token)
        };
  
      case _lexer.TokenKind.FLOAT:
        lexer.advance();
        return {
          kind: _kinds.Kind.FLOAT,
          value: token.value,
          loc: loc(lexer, token)
        };
  
      case _lexer.TokenKind.STRING:
      case _lexer.TokenKind.BLOCK_STRING:
        return parseStringLiteral(lexer);
  
      case _lexer.TokenKind.NAME:
        if (token.value === 'true' || token.value === 'false') {
          lexer.advance();
          return {
            kind: _kinds.Kind.BOOLEAN,
            value: token.value === 'true',
            loc: loc(lexer, token)
          };
        } else if (token.value === 'null') {
          lexer.advance();
          return {
            kind: _kinds.Kind.NULL,
            loc: loc(lexer, token)
          };
        }
  
        lexer.advance();
        return {
          kind: _kinds.Kind.ENUM,
          value: token.value,
          loc: loc(lexer, token)
        };
  
      case _lexer.TokenKind.DOLLAR:
        if (!isConst) {
          return parseVariable(lexer);
        }
  
        break;
    }
  
    throw unexpected(lexer);
  }
  
  function parseStringLiteral(lexer) {
    var token = lexer.token;
    lexer.advance();
    return {
      kind: _kinds.Kind.STRING,
      value: token.value,
      block: token.kind === _lexer.TokenKind.BLOCK_STRING,
      loc: loc(lexer, token)
    };
  }
  
  function parseConstValue(lexer) {
    return parseValueLiteral(lexer, true);
  }
  
  function parseValueValue(lexer) {
    return parseValueLiteral(lexer, false);
  }
  /**
   * ListValue[Const] :
   *   - [ ]
   *   - [ Value[?Const]+ ]
   */
  
  
  function parseList(lexer, isConst) {
    var start = lexer.token;
    var item = isConst ? parseConstValue : parseValueValue;
    return {
      kind: _kinds.Kind.LIST,
      values: any(lexer, _lexer.TokenKind.BRACKET_L, item, _lexer.TokenKind.BRACKET_R),
      loc: loc(lexer, start)
    };
  }
  /**
   * ObjectValue[Const] :
   *   - { }
   *   - { ObjectField[?Const]+ }
   */
  
  
  function parseObject(lexer, isConst) {
    var start = lexer.token;
    expect(lexer, _lexer.TokenKind.BRACE_L);
    var fields = [];
  
    while (!skip(lexer, _lexer.TokenKind.BRACE_R)) {
      fields.push(parseObjectField(lexer, isConst));
    }
  
    return {
      kind: _kinds.Kind.OBJECT,
      fields: fields,
      loc: loc(lexer, start)
    };
  }
  /**
   * ObjectField[Const] : Name : Value[?Const]
   */
  
  
  function parseObjectField(lexer, isConst) {
    var start = lexer.token;
    return {
      kind: _kinds.Kind.OBJECT_FIELD,
      name: parseName(lexer),
      value: (expect(lexer, _lexer.TokenKind.COLON), parseValueLiteral(lexer, isConst)),
      loc: loc(lexer, start)
    };
  } // Implements the parsing rules in the Directives section.
  
  /**
   * Directives[Const] : Directive[?Const]+
   */
  
  
  function parseDirectives(lexer, isConst) {
    var directives = [];
  
    while (peek(lexer, _lexer.TokenKind.AT)) {
      directives.push(parseDirective(lexer, isConst));
    }
  
    return directives;
  }
  /**
   * Directive[Const] : @ Name Arguments[?Const]?
   */
  
  
  function parseDirective(lexer, isConst) {
    var start = lexer.token;
    expect(lexer, _lexer.TokenKind.AT);
    return {
      kind: _kinds.Kind.DIRECTIVE,
      name: parseName(lexer),
      arguments: parseArguments(lexer, isConst),
      loc: loc(lexer, start)
    };
  } // Implements the parsing rules in the Types section.
  
  /**
   * Type :
   *   - NamedType
   *   - ListType
   *   - NonNullType
   */
  
  
  function parseTypeReference(lexer) {
    var start = lexer.token;
    var type;
  
    if (skip(lexer, _lexer.TokenKind.BRACKET_L)) {
      type = parseTypeReference(lexer);
      expect(lexer, _lexer.TokenKind.BRACKET_R);
      type = {
        kind: _kinds.Kind.LIST_TYPE,
        type: type,
        loc: loc(lexer, start)
      };
    } else {
      type = parseNamedType(lexer);
    }
  
    if (skip(lexer, _lexer.TokenKind.BANG)) {
      return {
        kind: _kinds.Kind.NON_NULL_TYPE,
        type: type,
        loc: loc(lexer, start)
      };
    }
  
    return type;
  }
  /**
   * NamedType : Name
   */
  
  
  function parseNamedType(lexer) {
    var start = lexer.token;
    return {
      kind: _kinds.Kind.NAMED_TYPE,
      name: parseName(lexer),
      loc: loc(lexer, start)
    };
  } // Implements the parsing rules in the Type Definition section.
  
  /**
   * TypeSystemDefinition :
   *   - SchemaDefinition
   *   - TypeDefinition
   *   - DirectiveDefinition
   *
   * TypeDefinition :
   *   - ScalarTypeDefinition
   *   - ObjectTypeDefinition
   *   - InterfaceTypeDefinition
   *   - UnionTypeDefinition
   *   - EnumTypeDefinition
   *   - InputObjectTypeDefinition
   */
  
  
  function parseTypeSystemDefinition(lexer) {
    // Many definitions begin with a description and require a lookahead.
    var keywordToken = peekDescription(lexer) ? lexer.lookahead() : lexer.token;
  
    if (keywordToken.kind === _lexer.TokenKind.NAME) {
      switch (keywordToken.value) {
        case 'schema':
          return parseSchemaDefinition(lexer);
  
        case 'scalar':
          return parseScalarTypeDefinition(lexer);
  
        case 'type':
          return parseObjectTypeDefinition(lexer);
  
        case 'interface':
          return parseInterfaceTypeDefinition(lexer);
  
        case 'union':
          return parseUnionTypeDefinition(lexer);
  
        case 'enum':
          return parseEnumTypeDefinition(lexer);
  
        case 'input':
          return parseInputObjectTypeDefinition(lexer);
  
        case 'directive':
          return parseDirectiveDefinition(lexer);
      }
    }
  
    throw unexpected(lexer, keywordToken);
  }
  
  function peekDescription(lexer) {
    return peek(lexer, _lexer.TokenKind.STRING) || peek(lexer, _lexer.TokenKind.BLOCK_STRING);
  }
  /**
   * Description : StringValue
   */
  
  
  function parseDescription(lexer) {
    if (peekDescription(lexer)) {
      return parseStringLiteral(lexer);
    }
  }
  /**
   * SchemaDefinition : schema Directives[Const]? { OperationTypeDefinition+ }
   */
  
  
  function parseSchemaDefinition(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'schema');
    var directives = parseDirectives(lexer, true);
    var operationTypes = many(lexer, _lexer.TokenKind.BRACE_L, parseOperationTypeDefinition, _lexer.TokenKind.BRACE_R);
    return {
      kind: _kinds.Kind.SCHEMA_DEFINITION,
      directives: directives,
      operationTypes: operationTypes,
      loc: loc(lexer, start)
    };
  }
  /**
   * OperationTypeDefinition : OperationType : NamedType
   */
  
  
  function parseOperationTypeDefinition(lexer) {
    var start = lexer.token;
    var operation = parseOperationType(lexer);
    expect(lexer, _lexer.TokenKind.COLON);
    var type = parseNamedType(lexer);
    return {
      kind: _kinds.Kind.OPERATION_TYPE_DEFINITION,
      operation: operation,
      type: type,
      loc: loc(lexer, start)
    };
  }
  /**
   * ScalarTypeDefinition : Description? scalar Name Directives[Const]?
   */
  
  
  function parseScalarTypeDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    expectKeyword(lexer, 'scalar');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    return {
      kind: _kinds.Kind.SCALAR_TYPE_DEFINITION,
      description: description,
      name: name,
      directives: directives,
      loc: loc(lexer, start)
    };
  }
  /**
   * ObjectTypeDefinition :
   *   Description?
   *   type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition?
   */
  
  
  function parseObjectTypeDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    expectKeyword(lexer, 'type');
    var name = parseName(lexer);
    var interfaces = parseImplementsInterfaces(lexer);
    var directives = parseDirectives(lexer, true);
    var fields = parseFieldsDefinition(lexer);
    return {
      kind: _kinds.Kind.OBJECT_TYPE_DEFINITION,
      description: description,
      name: name,
      interfaces: interfaces,
      directives: directives,
      fields: fields,
      loc: loc(lexer, start)
    };
  }
  /**
   * ImplementsInterfaces :
   *   - implements `&`? NamedType
   *   - ImplementsInterfaces & NamedType
   */
  
  
  function parseImplementsInterfaces(lexer) {
    var types = [];
  
    if (skipKeyword(lexer, 'implements')) {
      // Optional leading ampersand
      skip(lexer, _lexer.TokenKind.AMP);
  
      do {
        types.push(parseNamedType(lexer));
      } while (skip(lexer, _lexer.TokenKind.AMP) || // Legacy support for the SDL?
      lexer.options.allowLegacySDLImplementsInterfaces && peek(lexer, _lexer.TokenKind.NAME));
    }
  
    return types;
  }
  /**
   * FieldsDefinition : { FieldDefinition+ }
   */
  
  
  function parseFieldsDefinition(lexer) {
    // Legacy support for the SDL?
    if (lexer.options.allowLegacySDLEmptyFields && peek(lexer, _lexer.TokenKind.BRACE_L) && lexer.lookahead().kind === _lexer.TokenKind.BRACE_R) {
      lexer.advance();
      lexer.advance();
      return [];
    }
  
    return peek(lexer, _lexer.TokenKind.BRACE_L) ? many(lexer, _lexer.TokenKind.BRACE_L, parseFieldDefinition, _lexer.TokenKind.BRACE_R) : [];
  }
  /**
   * FieldDefinition :
   *   - Description? Name ArgumentsDefinition? : Type Directives[Const]?
   */
  
  
  function parseFieldDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    var name = parseName(lexer);
    var args = parseArgumentDefs(lexer);
    expect(lexer, _lexer.TokenKind.COLON);
    var type = parseTypeReference(lexer);
    var directives = parseDirectives(lexer, true);
    return {
      kind: _kinds.Kind.FIELD_DEFINITION,
      description: description,
      name: name,
      arguments: args,
      type: type,
      directives: directives,
      loc: loc(lexer, start)
    };
  }
  /**
   * ArgumentsDefinition : ( InputValueDefinition+ )
   */
  
  
  function parseArgumentDefs(lexer) {
    if (!peek(lexer, _lexer.TokenKind.PAREN_L)) {
      return [];
    }
  
    return many(lexer, _lexer.TokenKind.PAREN_L, parseInputValueDef, _lexer.TokenKind.PAREN_R);
  }
  /**
   * InputValueDefinition :
   *   - Description? Name : Type DefaultValue? Directives[Const]?
   */
  
  
  function parseInputValueDef(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    var name = parseName(lexer);
    expect(lexer, _lexer.TokenKind.COLON);
    var type = parseTypeReference(lexer);
    var defaultValue;
  
    if (skip(lexer, _lexer.TokenKind.EQUALS)) {
      defaultValue = parseConstValue(lexer);
    }
  
    var directives = parseDirectives(lexer, true);
    return {
      kind: _kinds.Kind.INPUT_VALUE_DEFINITION,
      description: description,
      name: name,
      type: type,
      defaultValue: defaultValue,
      directives: directives,
      loc: loc(lexer, start)
    };
  }
  /**
   * InterfaceTypeDefinition :
   *   - Description? interface Name Directives[Const]? FieldsDefinition?
   */
  
  
  function parseInterfaceTypeDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    expectKeyword(lexer, 'interface');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var fields = parseFieldsDefinition(lexer);
    return {
      kind: _kinds.Kind.INTERFACE_TYPE_DEFINITION,
      description: description,
      name: name,
      directives: directives,
      fields: fields,
      loc: loc(lexer, start)
    };
  }
  /**
   * UnionTypeDefinition :
   *   - Description? union Name Directives[Const]? UnionMemberTypes?
   */
  
  
  function parseUnionTypeDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    expectKeyword(lexer, 'union');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var types = parseUnionMemberTypes(lexer);
    return {
      kind: _kinds.Kind.UNION_TYPE_DEFINITION,
      description: description,
      name: name,
      directives: directives,
      types: types,
      loc: loc(lexer, start)
    };
  }
  /**
   * UnionMemberTypes :
   *   - = `|`? NamedType
   *   - UnionMemberTypes | NamedType
   */
  
  
  function parseUnionMemberTypes(lexer) {
    var types = [];
  
    if (skip(lexer, _lexer.TokenKind.EQUALS)) {
      // Optional leading pipe
      skip(lexer, _lexer.TokenKind.PIPE);
  
      do {
        types.push(parseNamedType(lexer));
      } while (skip(lexer, _lexer.TokenKind.PIPE));
    }
  
    return types;
  }
  /**
   * EnumTypeDefinition :
   *   - Description? enum Name Directives[Const]? EnumValuesDefinition?
   */
  
  
  function parseEnumTypeDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    expectKeyword(lexer, 'enum');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var values = parseEnumValuesDefinition(lexer);
    return {
      kind: _kinds.Kind.ENUM_TYPE_DEFINITION,
      description: description,
      name: name,
      directives: directives,
      values: values,
      loc: loc(lexer, start)
    };
  }
  /**
   * EnumValuesDefinition : { EnumValueDefinition+ }
   */
  
  
  function parseEnumValuesDefinition(lexer) {
    return peek(lexer, _lexer.TokenKind.BRACE_L) ? many(lexer, _lexer.TokenKind.BRACE_L, parseEnumValueDefinition, _lexer.TokenKind.BRACE_R) : [];
  }
  /**
   * EnumValueDefinition : Description? EnumValue Directives[Const]?
   *
   * EnumValue : Name
   */
  
  
  function parseEnumValueDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    return {
      kind: _kinds.Kind.ENUM_VALUE_DEFINITION,
      description: description,
      name: name,
      directives: directives,
      loc: loc(lexer, start)
    };
  }
  /**
   * InputObjectTypeDefinition :
   *   - Description? input Name Directives[Const]? InputFieldsDefinition?
   */
  
  
  function parseInputObjectTypeDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    expectKeyword(lexer, 'input');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var fields = parseInputFieldsDefinition(lexer);
    return {
      kind: _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION,
      description: description,
      name: name,
      directives: directives,
      fields: fields,
      loc: loc(lexer, start)
    };
  }
  /**
   * InputFieldsDefinition : { InputValueDefinition+ }
   */
  
  
  function parseInputFieldsDefinition(lexer) {
    return peek(lexer, _lexer.TokenKind.BRACE_L) ? many(lexer, _lexer.TokenKind.BRACE_L, parseInputValueDef, _lexer.TokenKind.BRACE_R) : [];
  }
  /**
   * TypeSystemExtension :
   *   - SchemaExtension
   *   - TypeExtension
   *
   * TypeExtension :
   *   - ScalarTypeExtension
   *   - ObjectTypeExtension
   *   - InterfaceTypeExtension
   *   - UnionTypeExtension
   *   - EnumTypeExtension
   *   - InputObjectTypeDefinition
   */
  
  
  function parseTypeSystemExtension(lexer) {
    var keywordToken = lexer.lookahead();
  
    if (keywordToken.kind === _lexer.TokenKind.NAME) {
      switch (keywordToken.value) {
        case 'schema':
          return parseSchemaExtension(lexer);
  
        case 'scalar':
          return parseScalarTypeExtension(lexer);
  
        case 'type':
          return parseObjectTypeExtension(lexer);
  
        case 'interface':
          return parseInterfaceTypeExtension(lexer);
  
        case 'union':
          return parseUnionTypeExtension(lexer);
  
        case 'enum':
          return parseEnumTypeExtension(lexer);
  
        case 'input':
          return parseInputObjectTypeExtension(lexer);
      }
    }
  
    throw unexpected(lexer, keywordToken);
  }
  /**
   * SchemaExtension :
   *  - extend schema Directives[Const]? { OperationTypeDefinition+ }
   *  - extend schema Directives[Const]
   */
  
  
  function parseSchemaExtension(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'extend');
    expectKeyword(lexer, 'schema');
    var directives = parseDirectives(lexer, true);
    var operationTypes = peek(lexer, _lexer.TokenKind.BRACE_L) ? many(lexer, _lexer.TokenKind.BRACE_L, parseOperationTypeDefinition, _lexer.TokenKind.BRACE_R) : [];
  
    if (directives.length === 0 && operationTypes.length === 0) {
      throw unexpected(lexer);
    }
  
    return {
      kind: _kinds.Kind.SCHEMA_EXTENSION,
      directives: directives,
      operationTypes: operationTypes,
      loc: loc(lexer, start)
    };
  }
  /**
   * ScalarTypeExtension :
   *   - extend scalar Name Directives[Const]
   */
  
  
  function parseScalarTypeExtension(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'extend');
    expectKeyword(lexer, 'scalar');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
  
    if (directives.length === 0) {
      throw unexpected(lexer);
    }
  
    return {
      kind: _kinds.Kind.SCALAR_TYPE_EXTENSION,
      name: name,
      directives: directives,
      loc: loc(lexer, start)
    };
  }
  /**
   * ObjectTypeExtension :
   *  - extend type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition
   *  - extend type Name ImplementsInterfaces? Directives[Const]
   *  - extend type Name ImplementsInterfaces
   */
  
  
  function parseObjectTypeExtension(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'extend');
    expectKeyword(lexer, 'type');
    var name = parseName(lexer);
    var interfaces = parseImplementsInterfaces(lexer);
    var directives = parseDirectives(lexer, true);
    var fields = parseFieldsDefinition(lexer);
  
    if (interfaces.length === 0 && directives.length === 0 && fields.length === 0) {
      throw unexpected(lexer);
    }
  
    return {
      kind: _kinds.Kind.OBJECT_TYPE_EXTENSION,
      name: name,
      interfaces: interfaces,
      directives: directives,
      fields: fields,
      loc: loc(lexer, start)
    };
  }
  /**
   * InterfaceTypeExtension :
   *   - extend interface Name Directives[Const]? FieldsDefinition
   *   - extend interface Name Directives[Const]
   */
  
  
  function parseInterfaceTypeExtension(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'extend');
    expectKeyword(lexer, 'interface');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var fields = parseFieldsDefinition(lexer);
  
    if (directives.length === 0 && fields.length === 0) {
      throw unexpected(lexer);
    }
  
    return {
      kind: _kinds.Kind.INTERFACE_TYPE_EXTENSION,
      name: name,
      directives: directives,
      fields: fields,
      loc: loc(lexer, start)
    };
  }
  /**
   * UnionTypeExtension :
   *   - extend union Name Directives[Const]? UnionMemberTypes
   *   - extend union Name Directives[Const]
   */
  
  
  function parseUnionTypeExtension(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'extend');
    expectKeyword(lexer, 'union');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var types = parseUnionMemberTypes(lexer);
  
    if (directives.length === 0 && types.length === 0) {
      throw unexpected(lexer);
    }
  
    return {
      kind: _kinds.Kind.UNION_TYPE_EXTENSION,
      name: name,
      directives: directives,
      types: types,
      loc: loc(lexer, start)
    };
  }
  /**
   * EnumTypeExtension :
   *   - extend enum Name Directives[Const]? EnumValuesDefinition
   *   - extend enum Name Directives[Const]
   */
  
  
  function parseEnumTypeExtension(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'extend');
    expectKeyword(lexer, 'enum');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var values = parseEnumValuesDefinition(lexer);
  
    if (directives.length === 0 && values.length === 0) {
      throw unexpected(lexer);
    }
  
    return {
      kind: _kinds.Kind.ENUM_TYPE_EXTENSION,
      name: name,
      directives: directives,
      values: values,
      loc: loc(lexer, start)
    };
  }
  /**
   * InputObjectTypeExtension :
   *   - extend input Name Directives[Const]? InputFieldsDefinition
   *   - extend input Name Directives[Const]
   */
  
  
  function parseInputObjectTypeExtension(lexer) {
    var start = lexer.token;
    expectKeyword(lexer, 'extend');
    expectKeyword(lexer, 'input');
    var name = parseName(lexer);
    var directives = parseDirectives(lexer, true);
    var fields = parseInputFieldsDefinition(lexer);
  
    if (directives.length === 0 && fields.length === 0) {
      throw unexpected(lexer);
    }
  
    return {
      kind: _kinds.Kind.INPUT_OBJECT_TYPE_EXTENSION,
      name: name,
      directives: directives,
      fields: fields,
      loc: loc(lexer, start)
    };
  }
  /**
   * DirectiveDefinition :
   *   - Description? directive @ Name ArgumentsDefinition? on DirectiveLocations
   */
  
  
  function parseDirectiveDefinition(lexer) {
    var start = lexer.token;
    var description = parseDescription(lexer);
    expectKeyword(lexer, 'directive');
    expect(lexer, _lexer.TokenKind.AT);
    var name = parseName(lexer);
    var args = parseArgumentDefs(lexer);
    expectKeyword(lexer, 'on');
    var locations = parseDirectiveLocations(lexer);
    return {
      kind: _kinds.Kind.DIRECTIVE_DEFINITION,
      description: description,
      name: name,
      arguments: args,
      locations: locations,
      loc: loc(lexer, start)
    };
  }
  /**
   * DirectiveLocations :
   *   - `|`? DirectiveLocation
   *   - DirectiveLocations | DirectiveLocation
   */
  
  
  function parseDirectiveLocations(lexer) {
    // Optional leading pipe
    skip(lexer, _lexer.TokenKind.PIPE);
    var locations = [];
  
    do {
      locations.push(parseDirectiveLocation(lexer));
    } while (skip(lexer, _lexer.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`
   */
  
  
  function parseDirectiveLocation(lexer) {
    var start = lexer.token;
    var name = parseName(lexer);
  
    if (_directiveLocation.DirectiveLocation.hasOwnProperty(name.value)) {
      return name;
    }
  
    throw unexpected(lexer, start);
  } // Core parsing utility functions
  
  /**
   * Returns a location object, used to identify the place in
   * the source that created a given parsed object.
   */
  
  
  function loc(lexer, startToken) {
    if (!lexer.options.noLocation) {
      return new Loc(startToken, lexer.lastToken, lexer.source);
    }
  }
  
  function Loc(startToken, endToken, source) {
    this.start = startToken.start;
    this.end = endToken.end;
    this.startToken = startToken;
    this.endToken = endToken;
    this.source = source;
  } // Print a simplified form when appearing in JSON/util.inspect.
  
  
  (0, _defineToJSON.default)(Loc, function () {
    return {
      start: this.start,
      end: this.end
    };
  });
  /**
   * Determines if the next token is of a given kind
   */
  
  function peek(lexer, kind) {
    return lexer.token.kind === kind;
  }
  /**
   * If the next token is of the given kind, return true after advancing
   * the lexer. Otherwise, do not change the parser state and return false.
   */
  
  
  function skip(lexer, kind) {
    if (lexer.token.kind === kind) {
      lexer.advance();
      return true;
    }
  
    return false;
  }
  /**
   * 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.
   */
  
  
  function expect(lexer, kind) {
    var token = lexer.token;
  
    if (token.kind === kind) {
      lexer.advance();
      return token;
    }
  
    throw (0, _error.syntaxError)(lexer.source, token.start, "Expected ".concat(kind, ", found ").concat((0, _lexer.getTokenDesc)(token)));
  }
  /**
   * If the next token is a keyword with the given value, return true after advancing
   * the lexer. Otherwise, do not change the parser state and return false.
   */
  
  
  function skipKeyword(lexer, value) {
    var token = lexer.token;
  
    if (token.kind === _lexer.TokenKind.NAME && token.value === value) {
      lexer.advance();
      return true;
    }
  
    return false;
  }
  /**
   * If the next token is a keyword with the given value, return that token after
   * advancing the lexer. Otherwise, do not change the parser state and throw
   * an error.
   */
  
  
  function expectKeyword(lexer, value) {
    if (!skipKeyword(lexer, value)) {
      throw (0, _error.syntaxError)(lexer.source, lexer.token.start, "Expected \"".concat(value, "\", found ").concat((0, _lexer.getTokenDesc)(lexer.token)));
    }
  }
  /**
   * Helper function for creating an error when an unexpected lexed token
   * is encountered.
   */
  
  
  function unexpected(lexer, atToken) {
    var token = atToken || lexer.token;
    return (0, _error.syntaxError)(lexer.source, token.start, "Unexpected ".concat((0, _lexer.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.
   */
  
  
  function any(lexer, openKind, parseFn, closeKind) {
    expect(lexer, openKind);
    var nodes = [];
  
    while (!skip(lexer, closeKind)) {
      nodes.push(parseFn(lexer));
    }
  
    return nodes;
  }
  /**
   * 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.
   */
  
  
  function many(lexer, openKind, parseFn, closeKind) {
    expect(lexer, openKind);
    var nodes = [parseFn(lexer)];
  
    while (!skip(lexer, closeKind)) {
      nodes.push(parseFn(lexer));
    }
  
    return nodes;
  }