parser.js.flow 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561
  1. // @flow strict
  2. import inspect from '../jsutils/inspect';
  3. import devAssert from '../jsutils/devAssert';
  4. import defineToJSON from '../jsutils/defineToJSON';
  5. import { syntaxError } from '../error/syntaxError';
  6. import { type GraphQLError } from '../error/GraphQLError';
  7. import { Kind } from './kinds';
  8. import { Source } from './source';
  9. import { type Lexer, createLexer } from './lexer';
  10. import { DirectiveLocation } from './directiveLocation';
  11. import { type TokenKindEnum, TokenKind } from './tokenKind';
  12. import {
  13. type Location,
  14. type Token,
  15. type NameNode,
  16. type VariableNode,
  17. type DocumentNode,
  18. type DefinitionNode,
  19. type OperationDefinitionNode,
  20. type OperationTypeNode,
  21. type VariableDefinitionNode,
  22. type SelectionSetNode,
  23. type SelectionNode,
  24. type FieldNode,
  25. type ArgumentNode,
  26. type FragmentSpreadNode,
  27. type InlineFragmentNode,
  28. type FragmentDefinitionNode,
  29. type ValueNode,
  30. type StringValueNode,
  31. type ListValueNode,
  32. type ObjectValueNode,
  33. type ObjectFieldNode,
  34. type DirectiveNode,
  35. type TypeNode,
  36. type NamedTypeNode,
  37. type TypeSystemDefinitionNode,
  38. type SchemaDefinitionNode,
  39. type OperationTypeDefinitionNode,
  40. type ScalarTypeDefinitionNode,
  41. type ObjectTypeDefinitionNode,
  42. type FieldDefinitionNode,
  43. type InputValueDefinitionNode,
  44. type InterfaceTypeDefinitionNode,
  45. type UnionTypeDefinitionNode,
  46. type EnumTypeDefinitionNode,
  47. type EnumValueDefinitionNode,
  48. type InputObjectTypeDefinitionNode,
  49. type DirectiveDefinitionNode,
  50. type TypeSystemExtensionNode,
  51. type SchemaExtensionNode,
  52. type ScalarTypeExtensionNode,
  53. type ObjectTypeExtensionNode,
  54. type InterfaceTypeExtensionNode,
  55. type UnionTypeExtensionNode,
  56. type EnumTypeExtensionNode,
  57. type InputObjectTypeExtensionNode,
  58. } from './ast';
  59. /**
  60. * Configuration options to control parser behavior
  61. */
  62. export type ParseOptions = {
  63. /**
  64. * By default, the parser creates AST nodes that know the location
  65. * in the source that they correspond to. This configuration flag
  66. * disables that behavior for performance or testing.
  67. */
  68. noLocation?: boolean,
  69. /**
  70. * If enabled, the parser will parse empty fields sets in the Schema
  71. * Definition Language. Otherwise, the parser will follow the current
  72. * specification.
  73. *
  74. * This option is provided to ease adoption of the final SDL specification
  75. * and will be removed in v16.
  76. */
  77. allowLegacySDLEmptyFields?: boolean,
  78. /**
  79. * If enabled, the parser will parse implemented interfaces with no `&`
  80. * character between each interface. Otherwise, the parser will follow the
  81. * current specification.
  82. *
  83. * This option is provided to ease adoption of the final SDL specification
  84. * and will be removed in v16.
  85. */
  86. allowLegacySDLImplementsInterfaces?: boolean,
  87. /**
  88. * EXPERIMENTAL:
  89. *
  90. * If enabled, the parser will understand and parse variable definitions
  91. * contained in a fragment definition. They'll be represented in the
  92. * `variableDefinitions` field of the FragmentDefinitionNode.
  93. *
  94. * The syntax is identical to normal, query-defined variables. For example:
  95. *
  96. * fragment A($var: Boolean = false) on T {
  97. * ...
  98. * }
  99. *
  100. * Note: this feature is experimental and may change or be removed in the
  101. * future.
  102. */
  103. experimentalFragmentVariables?: boolean,
  104. ...
  105. };
  106. /**
  107. * Given a GraphQL source, parses it into a Document.
  108. * Throws GraphQLError if a syntax error is encountered.
  109. */
  110. export function parse(
  111. source: string | Source,
  112. options?: ParseOptions,
  113. ): DocumentNode {
  114. const parser = new Parser(source, options);
  115. return parser.parseDocument();
  116. }
  117. /**
  118. * Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
  119. * that value.
  120. * Throws GraphQLError if a syntax error is encountered.
  121. *
  122. * This is useful within tools that operate upon GraphQL Values directly and
  123. * in isolation of complete GraphQL documents.
  124. *
  125. * Consider providing the results to the utility function: valueFromAST().
  126. */
  127. export function parseValue(
  128. source: string | Source,
  129. options?: ParseOptions,
  130. ): ValueNode {
  131. const parser = new Parser(source, options);
  132. parser.expectToken(TokenKind.SOF);
  133. const value = parser.parseValueLiteral(false);
  134. parser.expectToken(TokenKind.EOF);
  135. return value;
  136. }
  137. /**
  138. * Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for
  139. * that type.
  140. * Throws GraphQLError if a syntax error is encountered.
  141. *
  142. * This is useful within tools that operate upon GraphQL Types directly and
  143. * in isolation of complete GraphQL documents.
  144. *
  145. * Consider providing the results to the utility function: typeFromAST().
  146. */
  147. export function parseType(
  148. source: string | Source,
  149. options?: ParseOptions,
  150. ): TypeNode {
  151. const parser = new Parser(source, options);
  152. parser.expectToken(TokenKind.SOF);
  153. const type = parser.parseTypeReference();
  154. parser.expectToken(TokenKind.EOF);
  155. return type;
  156. }
  157. class Parser {
  158. _options: ParseOptions;
  159. _lexer: Lexer<void>;
  160. constructor(source: string | Source, options?: ParseOptions) {
  161. const sourceObj = typeof source === 'string' ? new Source(source) : source;
  162. devAssert(
  163. sourceObj instanceof Source,
  164. `Must provide Source. Received: ${inspect(sourceObj)}`,
  165. );
  166. this._lexer = createLexer(sourceObj);
  167. this._options = options || {};
  168. }
  169. /**
  170. * Converts a name lex token into a name parse node.
  171. */
  172. parseName(): NameNode {
  173. const token = this.expectToken(TokenKind.NAME);
  174. return {
  175. kind: Kind.NAME,
  176. value: ((token.value: any): string),
  177. loc: this.loc(token),
  178. };
  179. }
  180. // Implements the parsing rules in the Document section.
  181. /**
  182. * Document : Definition+
  183. */
  184. parseDocument(): DocumentNode {
  185. const start = this._lexer.token;
  186. return {
  187. kind: Kind.DOCUMENT,
  188. definitions: this.many(
  189. TokenKind.SOF,
  190. this.parseDefinition,
  191. TokenKind.EOF,
  192. ),
  193. loc: this.loc(start),
  194. };
  195. }
  196. /**
  197. * Definition :
  198. * - ExecutableDefinition
  199. * - TypeSystemDefinition
  200. * - TypeSystemExtension
  201. *
  202. * ExecutableDefinition :
  203. * - OperationDefinition
  204. * - FragmentDefinition
  205. */
  206. parseDefinition(): DefinitionNode {
  207. if (this.peek(TokenKind.NAME)) {
  208. switch (this._lexer.token.value) {
  209. case 'query':
  210. case 'mutation':
  211. case 'subscription':
  212. return this.parseOperationDefinition();
  213. case 'fragment':
  214. return this.parseFragmentDefinition();
  215. case 'schema':
  216. case 'scalar':
  217. case 'type':
  218. case 'interface':
  219. case 'union':
  220. case 'enum':
  221. case 'input':
  222. case 'directive':
  223. return this.parseTypeSystemDefinition();
  224. case 'extend':
  225. return this.parseTypeSystemExtension();
  226. }
  227. } else if (this.peek(TokenKind.BRACE_L)) {
  228. return this.parseOperationDefinition();
  229. } else if (this.peekDescription()) {
  230. return this.parseTypeSystemDefinition();
  231. }
  232. throw this.unexpected();
  233. }
  234. // Implements the parsing rules in the Operations section.
  235. /**
  236. * OperationDefinition :
  237. * - SelectionSet
  238. * - OperationType Name? VariableDefinitions? Directives? SelectionSet
  239. */
  240. parseOperationDefinition(): OperationDefinitionNode {
  241. const start = this._lexer.token;
  242. if (this.peek(TokenKind.BRACE_L)) {
  243. return {
  244. kind: Kind.OPERATION_DEFINITION,
  245. operation: 'query',
  246. name: undefined,
  247. variableDefinitions: [],
  248. directives: [],
  249. selectionSet: this.parseSelectionSet(),
  250. loc: this.loc(start),
  251. };
  252. }
  253. const operation = this.parseOperationType();
  254. let name;
  255. if (this.peek(TokenKind.NAME)) {
  256. name = this.parseName();
  257. }
  258. return {
  259. kind: Kind.OPERATION_DEFINITION,
  260. operation,
  261. name,
  262. variableDefinitions: this.parseVariableDefinitions(),
  263. directives: this.parseDirectives(false),
  264. selectionSet: this.parseSelectionSet(),
  265. loc: this.loc(start),
  266. };
  267. }
  268. /**
  269. * OperationType : one of query mutation subscription
  270. */
  271. parseOperationType(): OperationTypeNode {
  272. const operationToken = this.expectToken(TokenKind.NAME);
  273. switch (operationToken.value) {
  274. case 'query':
  275. return 'query';
  276. case 'mutation':
  277. return 'mutation';
  278. case 'subscription':
  279. return 'subscription';
  280. }
  281. throw this.unexpected(operationToken);
  282. }
  283. /**
  284. * VariableDefinitions : ( VariableDefinition+ )
  285. */
  286. parseVariableDefinitions(): Array<VariableDefinitionNode> {
  287. return this.optionalMany(
  288. TokenKind.PAREN_L,
  289. this.parseVariableDefinition,
  290. TokenKind.PAREN_R,
  291. );
  292. }
  293. /**
  294. * VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
  295. */
  296. parseVariableDefinition(): VariableDefinitionNode {
  297. const start = this._lexer.token;
  298. return {
  299. kind: Kind.VARIABLE_DEFINITION,
  300. variable: this.parseVariable(),
  301. type: (this.expectToken(TokenKind.COLON), this.parseTypeReference()),
  302. defaultValue: this.expectOptionalToken(TokenKind.EQUALS)
  303. ? this.parseValueLiteral(true)
  304. : undefined,
  305. directives: this.parseDirectives(true),
  306. loc: this.loc(start),
  307. };
  308. }
  309. /**
  310. * Variable : $ Name
  311. */
  312. parseVariable(): VariableNode {
  313. const start = this._lexer.token;
  314. this.expectToken(TokenKind.DOLLAR);
  315. return {
  316. kind: Kind.VARIABLE,
  317. name: this.parseName(),
  318. loc: this.loc(start),
  319. };
  320. }
  321. /**
  322. * SelectionSet : { Selection+ }
  323. */
  324. parseSelectionSet(): SelectionSetNode {
  325. const start = this._lexer.token;
  326. return {
  327. kind: Kind.SELECTION_SET,
  328. selections: this.many(
  329. TokenKind.BRACE_L,
  330. this.parseSelection,
  331. TokenKind.BRACE_R,
  332. ),
  333. loc: this.loc(start),
  334. };
  335. }
  336. /**
  337. * Selection :
  338. * - Field
  339. * - FragmentSpread
  340. * - InlineFragment
  341. */
  342. parseSelection(): SelectionNode {
  343. return this.peek(TokenKind.SPREAD)
  344. ? this.parseFragment()
  345. : this.parseField();
  346. }
  347. /**
  348. * Field : Alias? Name Arguments? Directives? SelectionSet?
  349. *
  350. * Alias : Name :
  351. */
  352. parseField(): FieldNode {
  353. const start = this._lexer.token;
  354. const nameOrAlias = this.parseName();
  355. let alias;
  356. let name;
  357. if (this.expectOptionalToken(TokenKind.COLON)) {
  358. alias = nameOrAlias;
  359. name = this.parseName();
  360. } else {
  361. name = nameOrAlias;
  362. }
  363. return {
  364. kind: Kind.FIELD,
  365. alias,
  366. name,
  367. arguments: this.parseArguments(false),
  368. directives: this.parseDirectives(false),
  369. selectionSet: this.peek(TokenKind.BRACE_L)
  370. ? this.parseSelectionSet()
  371. : undefined,
  372. loc: this.loc(start),
  373. };
  374. }
  375. /**
  376. * Arguments[Const] : ( Argument[?Const]+ )
  377. */
  378. parseArguments(isConst: boolean): Array<ArgumentNode> {
  379. const item = isConst ? this.parseConstArgument : this.parseArgument;
  380. return this.optionalMany(TokenKind.PAREN_L, item, TokenKind.PAREN_R);
  381. }
  382. /**
  383. * Argument[Const] : Name : Value[?Const]
  384. */
  385. parseArgument(): ArgumentNode {
  386. const start = this._lexer.token;
  387. const name = this.parseName();
  388. this.expectToken(TokenKind.COLON);
  389. return {
  390. kind: Kind.ARGUMENT,
  391. name,
  392. value: this.parseValueLiteral(false),
  393. loc: this.loc(start),
  394. };
  395. }
  396. parseConstArgument(): ArgumentNode {
  397. const start = this._lexer.token;
  398. return {
  399. kind: Kind.ARGUMENT,
  400. name: this.parseName(),
  401. value: (this.expectToken(TokenKind.COLON), this.parseValueLiteral(true)),
  402. loc: this.loc(start),
  403. };
  404. }
  405. // Implements the parsing rules in the Fragments section.
  406. /**
  407. * Corresponds to both FragmentSpread and InlineFragment in the spec.
  408. *
  409. * FragmentSpread : ... FragmentName Directives?
  410. *
  411. * InlineFragment : ... TypeCondition? Directives? SelectionSet
  412. */
  413. parseFragment(): FragmentSpreadNode | InlineFragmentNode {
  414. const start = this._lexer.token;
  415. this.expectToken(TokenKind.SPREAD);
  416. const hasTypeCondition = this.expectOptionalKeyword('on');
  417. if (!hasTypeCondition && this.peek(TokenKind.NAME)) {
  418. return {
  419. kind: Kind.FRAGMENT_SPREAD,
  420. name: this.parseFragmentName(),
  421. directives: this.parseDirectives(false),
  422. loc: this.loc(start),
  423. };
  424. }
  425. return {
  426. kind: Kind.INLINE_FRAGMENT,
  427. typeCondition: hasTypeCondition ? this.parseNamedType() : undefined,
  428. directives: this.parseDirectives(false),
  429. selectionSet: this.parseSelectionSet(),
  430. loc: this.loc(start),
  431. };
  432. }
  433. /**
  434. * FragmentDefinition :
  435. * - fragment FragmentName on TypeCondition Directives? SelectionSet
  436. *
  437. * TypeCondition : NamedType
  438. */
  439. parseFragmentDefinition(): FragmentDefinitionNode {
  440. const start = this._lexer.token;
  441. this.expectKeyword('fragment');
  442. // Experimental support for defining variables within fragments changes
  443. // the grammar of FragmentDefinition:
  444. // - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
  445. if (this._options.experimentalFragmentVariables) {
  446. return {
  447. kind: Kind.FRAGMENT_DEFINITION,
  448. name: this.parseFragmentName(),
  449. variableDefinitions: this.parseVariableDefinitions(),
  450. typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
  451. directives: this.parseDirectives(false),
  452. selectionSet: this.parseSelectionSet(),
  453. loc: this.loc(start),
  454. };
  455. }
  456. return {
  457. kind: Kind.FRAGMENT_DEFINITION,
  458. name: this.parseFragmentName(),
  459. typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
  460. directives: this.parseDirectives(false),
  461. selectionSet: this.parseSelectionSet(),
  462. loc: this.loc(start),
  463. };
  464. }
  465. /**
  466. * FragmentName : Name but not `on`
  467. */
  468. parseFragmentName(): NameNode {
  469. if (this._lexer.token.value === 'on') {
  470. throw this.unexpected();
  471. }
  472. return this.parseName();
  473. }
  474. // Implements the parsing rules in the Values section.
  475. /**
  476. * Value[Const] :
  477. * - [~Const] Variable
  478. * - IntValue
  479. * - FloatValue
  480. * - StringValue
  481. * - BooleanValue
  482. * - NullValue
  483. * - EnumValue
  484. * - ListValue[?Const]
  485. * - ObjectValue[?Const]
  486. *
  487. * BooleanValue : one of `true` `false`
  488. *
  489. * NullValue : `null`
  490. *
  491. * EnumValue : Name but not `true`, `false` or `null`
  492. */
  493. parseValueLiteral(isConst: boolean): ValueNode {
  494. const token = this._lexer.token;
  495. switch (token.kind) {
  496. case TokenKind.BRACKET_L:
  497. return this.parseList(isConst);
  498. case TokenKind.BRACE_L:
  499. return this.parseObject(isConst);
  500. case TokenKind.INT:
  501. this._lexer.advance();
  502. return {
  503. kind: Kind.INT,
  504. value: ((token.value: any): string),
  505. loc: this.loc(token),
  506. };
  507. case TokenKind.FLOAT:
  508. this._lexer.advance();
  509. return {
  510. kind: Kind.FLOAT,
  511. value: ((token.value: any): string),
  512. loc: this.loc(token),
  513. };
  514. case TokenKind.STRING:
  515. case TokenKind.BLOCK_STRING:
  516. return this.parseStringLiteral();
  517. case TokenKind.NAME:
  518. if (token.value === 'true' || token.value === 'false') {
  519. this._lexer.advance();
  520. return {
  521. kind: Kind.BOOLEAN,
  522. value: token.value === 'true',
  523. loc: this.loc(token),
  524. };
  525. } else if (token.value === 'null') {
  526. this._lexer.advance();
  527. return {
  528. kind: Kind.NULL,
  529. loc: this.loc(token),
  530. };
  531. }
  532. this._lexer.advance();
  533. return {
  534. kind: Kind.ENUM,
  535. value: ((token.value: any): string),
  536. loc: this.loc(token),
  537. };
  538. case TokenKind.DOLLAR:
  539. if (!isConst) {
  540. return this.parseVariable();
  541. }
  542. break;
  543. }
  544. throw this.unexpected();
  545. }
  546. parseStringLiteral(): StringValueNode {
  547. const token = this._lexer.token;
  548. this._lexer.advance();
  549. return {
  550. kind: Kind.STRING,
  551. value: ((token.value: any): string),
  552. block: token.kind === TokenKind.BLOCK_STRING,
  553. loc: this.loc(token),
  554. };
  555. }
  556. /**
  557. * ListValue[Const] :
  558. * - [ ]
  559. * - [ Value[?Const]+ ]
  560. */
  561. parseList(isConst: boolean): ListValueNode {
  562. const start = this._lexer.token;
  563. const item = () => this.parseValueLiteral(isConst);
  564. return {
  565. kind: Kind.LIST,
  566. values: this.any(TokenKind.BRACKET_L, item, TokenKind.BRACKET_R),
  567. loc: this.loc(start),
  568. };
  569. }
  570. /**
  571. * ObjectValue[Const] :
  572. * - { }
  573. * - { ObjectField[?Const]+ }
  574. */
  575. parseObject(isConst: boolean): ObjectValueNode {
  576. const start = this._lexer.token;
  577. const item = () => this.parseObjectField(isConst);
  578. return {
  579. kind: Kind.OBJECT,
  580. fields: this.any(TokenKind.BRACE_L, item, TokenKind.BRACE_R),
  581. loc: this.loc(start),
  582. };
  583. }
  584. /**
  585. * ObjectField[Const] : Name : Value[?Const]
  586. */
  587. parseObjectField(isConst: boolean): ObjectFieldNode {
  588. const start = this._lexer.token;
  589. const name = this.parseName();
  590. this.expectToken(TokenKind.COLON);
  591. return {
  592. kind: Kind.OBJECT_FIELD,
  593. name,
  594. value: this.parseValueLiteral(isConst),
  595. loc: this.loc(start),
  596. };
  597. }
  598. // Implements the parsing rules in the Directives section.
  599. /**
  600. * Directives[Const] : Directive[?Const]+
  601. */
  602. parseDirectives(isConst: boolean): Array<DirectiveNode> {
  603. const directives = [];
  604. while (this.peek(TokenKind.AT)) {
  605. directives.push(this.parseDirective(isConst));
  606. }
  607. return directives;
  608. }
  609. /**
  610. * Directive[Const] : @ Name Arguments[?Const]?
  611. */
  612. parseDirective(isConst: boolean): DirectiveNode {
  613. const start = this._lexer.token;
  614. this.expectToken(TokenKind.AT);
  615. return {
  616. kind: Kind.DIRECTIVE,
  617. name: this.parseName(),
  618. arguments: this.parseArguments(isConst),
  619. loc: this.loc(start),
  620. };
  621. }
  622. // Implements the parsing rules in the Types section.
  623. /**
  624. * Type :
  625. * - NamedType
  626. * - ListType
  627. * - NonNullType
  628. */
  629. parseTypeReference(): TypeNode {
  630. const start = this._lexer.token;
  631. let type;
  632. if (this.expectOptionalToken(TokenKind.BRACKET_L)) {
  633. type = this.parseTypeReference();
  634. this.expectToken(TokenKind.BRACKET_R);
  635. type = {
  636. kind: Kind.LIST_TYPE,
  637. type,
  638. loc: this.loc(start),
  639. };
  640. } else {
  641. type = this.parseNamedType();
  642. }
  643. if (this.expectOptionalToken(TokenKind.BANG)) {
  644. return {
  645. kind: Kind.NON_NULL_TYPE,
  646. type,
  647. loc: this.loc(start),
  648. };
  649. }
  650. return type;
  651. }
  652. /**
  653. * NamedType : Name
  654. */
  655. parseNamedType(): NamedTypeNode {
  656. const start = this._lexer.token;
  657. return {
  658. kind: Kind.NAMED_TYPE,
  659. name: this.parseName(),
  660. loc: this.loc(start),
  661. };
  662. }
  663. // Implements the parsing rules in the Type Definition section.
  664. /**
  665. * TypeSystemDefinition :
  666. * - SchemaDefinition
  667. * - TypeDefinition
  668. * - DirectiveDefinition
  669. *
  670. * TypeDefinition :
  671. * - ScalarTypeDefinition
  672. * - ObjectTypeDefinition
  673. * - InterfaceTypeDefinition
  674. * - UnionTypeDefinition
  675. * - EnumTypeDefinition
  676. * - InputObjectTypeDefinition
  677. */
  678. parseTypeSystemDefinition(): TypeSystemDefinitionNode {
  679. // Many definitions begin with a description and require a lookahead.
  680. const keywordToken = this.peekDescription()
  681. ? this._lexer.lookahead()
  682. : this._lexer.token;
  683. if (keywordToken.kind === TokenKind.NAME) {
  684. switch (keywordToken.value) {
  685. case 'schema':
  686. return this.parseSchemaDefinition();
  687. case 'scalar':
  688. return this.parseScalarTypeDefinition();
  689. case 'type':
  690. return this.parseObjectTypeDefinition();
  691. case 'interface':
  692. return this.parseInterfaceTypeDefinition();
  693. case 'union':
  694. return this.parseUnionTypeDefinition();
  695. case 'enum':
  696. return this.parseEnumTypeDefinition();
  697. case 'input':
  698. return this.parseInputObjectTypeDefinition();
  699. case 'directive':
  700. return this.parseDirectiveDefinition();
  701. }
  702. }
  703. throw this.unexpected(keywordToken);
  704. }
  705. peekDescription(): boolean {
  706. return this.peek(TokenKind.STRING) || this.peek(TokenKind.BLOCK_STRING);
  707. }
  708. /**
  709. * Description : StringValue
  710. */
  711. parseDescription(): void | StringValueNode {
  712. if (this.peekDescription()) {
  713. return this.parseStringLiteral();
  714. }
  715. }
  716. /**
  717. * SchemaDefinition : schema Directives[Const]? { OperationTypeDefinition+ }
  718. */
  719. parseSchemaDefinition(): SchemaDefinitionNode {
  720. const start = this._lexer.token;
  721. this.expectKeyword('schema');
  722. const directives = this.parseDirectives(true);
  723. const operationTypes = this.many(
  724. TokenKind.BRACE_L,
  725. this.parseOperationTypeDefinition,
  726. TokenKind.BRACE_R,
  727. );
  728. return {
  729. kind: Kind.SCHEMA_DEFINITION,
  730. directives,
  731. operationTypes,
  732. loc: this.loc(start),
  733. };
  734. }
  735. /**
  736. * OperationTypeDefinition : OperationType : NamedType
  737. */
  738. parseOperationTypeDefinition(): OperationTypeDefinitionNode {
  739. const start = this._lexer.token;
  740. const operation = this.parseOperationType();
  741. this.expectToken(TokenKind.COLON);
  742. const type = this.parseNamedType();
  743. return {
  744. kind: Kind.OPERATION_TYPE_DEFINITION,
  745. operation,
  746. type,
  747. loc: this.loc(start),
  748. };
  749. }
  750. /**
  751. * ScalarTypeDefinition : Description? scalar Name Directives[Const]?
  752. */
  753. parseScalarTypeDefinition(): ScalarTypeDefinitionNode {
  754. const start = this._lexer.token;
  755. const description = this.parseDescription();
  756. this.expectKeyword('scalar');
  757. const name = this.parseName();
  758. const directives = this.parseDirectives(true);
  759. return {
  760. kind: Kind.SCALAR_TYPE_DEFINITION,
  761. description,
  762. name,
  763. directives,
  764. loc: this.loc(start),
  765. };
  766. }
  767. /**
  768. * ObjectTypeDefinition :
  769. * Description?
  770. * type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition?
  771. */
  772. parseObjectTypeDefinition(): ObjectTypeDefinitionNode {
  773. const start = this._lexer.token;
  774. const description = this.parseDescription();
  775. this.expectKeyword('type');
  776. const name = this.parseName();
  777. const interfaces = this.parseImplementsInterfaces();
  778. const directives = this.parseDirectives(true);
  779. const fields = this.parseFieldsDefinition();
  780. return {
  781. kind: Kind.OBJECT_TYPE_DEFINITION,
  782. description,
  783. name,
  784. interfaces,
  785. directives,
  786. fields,
  787. loc: this.loc(start),
  788. };
  789. }
  790. /**
  791. * ImplementsInterfaces :
  792. * - implements `&`? NamedType
  793. * - ImplementsInterfaces & NamedType
  794. */
  795. parseImplementsInterfaces(): Array<NamedTypeNode> {
  796. const types = [];
  797. if (this.expectOptionalKeyword('implements')) {
  798. // Optional leading ampersand
  799. this.expectOptionalToken(TokenKind.AMP);
  800. do {
  801. types.push(this.parseNamedType());
  802. } while (
  803. this.expectOptionalToken(TokenKind.AMP) ||
  804. // Legacy support for the SDL?
  805. (this._options.allowLegacySDLImplementsInterfaces &&
  806. this.peek(TokenKind.NAME))
  807. );
  808. }
  809. return types;
  810. }
  811. /**
  812. * FieldsDefinition : { FieldDefinition+ }
  813. */
  814. parseFieldsDefinition(): Array<FieldDefinitionNode> {
  815. // Legacy support for the SDL?
  816. if (
  817. this._options.allowLegacySDLEmptyFields &&
  818. this.peek(TokenKind.BRACE_L) &&
  819. this._lexer.lookahead().kind === TokenKind.BRACE_R
  820. ) {
  821. this._lexer.advance();
  822. this._lexer.advance();
  823. return [];
  824. }
  825. return this.optionalMany(
  826. TokenKind.BRACE_L,
  827. this.parseFieldDefinition,
  828. TokenKind.BRACE_R,
  829. );
  830. }
  831. /**
  832. * FieldDefinition :
  833. * - Description? Name ArgumentsDefinition? : Type Directives[Const]?
  834. */
  835. parseFieldDefinition(): FieldDefinitionNode {
  836. const start = this._lexer.token;
  837. const description = this.parseDescription();
  838. const name = this.parseName();
  839. const args = this.parseArgumentDefs();
  840. this.expectToken(TokenKind.COLON);
  841. const type = this.parseTypeReference();
  842. const directives = this.parseDirectives(true);
  843. return {
  844. kind: Kind.FIELD_DEFINITION,
  845. description,
  846. name,
  847. arguments: args,
  848. type,
  849. directives,
  850. loc: this.loc(start),
  851. };
  852. }
  853. /**
  854. * ArgumentsDefinition : ( InputValueDefinition+ )
  855. */
  856. parseArgumentDefs(): Array<InputValueDefinitionNode> {
  857. return this.optionalMany(
  858. TokenKind.PAREN_L,
  859. this.parseInputValueDef,
  860. TokenKind.PAREN_R,
  861. );
  862. }
  863. /**
  864. * InputValueDefinition :
  865. * - Description? Name : Type DefaultValue? Directives[Const]?
  866. */
  867. parseInputValueDef(): InputValueDefinitionNode {
  868. const start = this._lexer.token;
  869. const description = this.parseDescription();
  870. const name = this.parseName();
  871. this.expectToken(TokenKind.COLON);
  872. const type = this.parseTypeReference();
  873. let defaultValue;
  874. if (this.expectOptionalToken(TokenKind.EQUALS)) {
  875. defaultValue = this.parseValueLiteral(true);
  876. }
  877. const directives = this.parseDirectives(true);
  878. return {
  879. kind: Kind.INPUT_VALUE_DEFINITION,
  880. description,
  881. name,
  882. type,
  883. defaultValue,
  884. directives,
  885. loc: this.loc(start),
  886. };
  887. }
  888. /**
  889. * InterfaceTypeDefinition :
  890. * - Description? interface Name Directives[Const]? FieldsDefinition?
  891. */
  892. parseInterfaceTypeDefinition(): InterfaceTypeDefinitionNode {
  893. const start = this._lexer.token;
  894. const description = this.parseDescription();
  895. this.expectKeyword('interface');
  896. const name = this.parseName();
  897. const directives = this.parseDirectives(true);
  898. const fields = this.parseFieldsDefinition();
  899. return {
  900. kind: Kind.INTERFACE_TYPE_DEFINITION,
  901. description,
  902. name,
  903. directives,
  904. fields,
  905. loc: this.loc(start),
  906. };
  907. }
  908. /**
  909. * UnionTypeDefinition :
  910. * - Description? union Name Directives[Const]? UnionMemberTypes?
  911. */
  912. parseUnionTypeDefinition(): UnionTypeDefinitionNode {
  913. const start = this._lexer.token;
  914. const description = this.parseDescription();
  915. this.expectKeyword('union');
  916. const name = this.parseName();
  917. const directives = this.parseDirectives(true);
  918. const types = this.parseUnionMemberTypes();
  919. return {
  920. kind: Kind.UNION_TYPE_DEFINITION,
  921. description,
  922. name,
  923. directives,
  924. types,
  925. loc: this.loc(start),
  926. };
  927. }
  928. /**
  929. * UnionMemberTypes :
  930. * - = `|`? NamedType
  931. * - UnionMemberTypes | NamedType
  932. */
  933. parseUnionMemberTypes(): Array<NamedTypeNode> {
  934. const types = [];
  935. if (this.expectOptionalToken(TokenKind.EQUALS)) {
  936. // Optional leading pipe
  937. this.expectOptionalToken(TokenKind.PIPE);
  938. do {
  939. types.push(this.parseNamedType());
  940. } while (this.expectOptionalToken(TokenKind.PIPE));
  941. }
  942. return types;
  943. }
  944. /**
  945. * EnumTypeDefinition :
  946. * - Description? enum Name Directives[Const]? EnumValuesDefinition?
  947. */
  948. parseEnumTypeDefinition(): EnumTypeDefinitionNode {
  949. const start = this._lexer.token;
  950. const description = this.parseDescription();
  951. this.expectKeyword('enum');
  952. const name = this.parseName();
  953. const directives = this.parseDirectives(true);
  954. const values = this.parseEnumValuesDefinition();
  955. return {
  956. kind: Kind.ENUM_TYPE_DEFINITION,
  957. description,
  958. name,
  959. directives,
  960. values,
  961. loc: this.loc(start),
  962. };
  963. }
  964. /**
  965. * EnumValuesDefinition : { EnumValueDefinition+ }
  966. */
  967. parseEnumValuesDefinition(): Array<EnumValueDefinitionNode> {
  968. return this.optionalMany(
  969. TokenKind.BRACE_L,
  970. this.parseEnumValueDefinition,
  971. TokenKind.BRACE_R,
  972. );
  973. }
  974. /**
  975. * EnumValueDefinition : Description? EnumValue Directives[Const]?
  976. *
  977. * EnumValue : Name
  978. */
  979. parseEnumValueDefinition(): EnumValueDefinitionNode {
  980. const start = this._lexer.token;
  981. const description = this.parseDescription();
  982. const name = this.parseName();
  983. const directives = this.parseDirectives(true);
  984. return {
  985. kind: Kind.ENUM_VALUE_DEFINITION,
  986. description,
  987. name,
  988. directives,
  989. loc: this.loc(start),
  990. };
  991. }
  992. /**
  993. * InputObjectTypeDefinition :
  994. * - Description? input Name Directives[Const]? InputFieldsDefinition?
  995. */
  996. parseInputObjectTypeDefinition(): InputObjectTypeDefinitionNode {
  997. const start = this._lexer.token;
  998. const description = this.parseDescription();
  999. this.expectKeyword('input');
  1000. const name = this.parseName();
  1001. const directives = this.parseDirectives(true);
  1002. const fields = this.parseInputFieldsDefinition();
  1003. return {
  1004. kind: Kind.INPUT_OBJECT_TYPE_DEFINITION,
  1005. description,
  1006. name,
  1007. directives,
  1008. fields,
  1009. loc: this.loc(start),
  1010. };
  1011. }
  1012. /**
  1013. * InputFieldsDefinition : { InputValueDefinition+ }
  1014. */
  1015. parseInputFieldsDefinition(): Array<InputValueDefinitionNode> {
  1016. return this.optionalMany(
  1017. TokenKind.BRACE_L,
  1018. this.parseInputValueDef,
  1019. TokenKind.BRACE_R,
  1020. );
  1021. }
  1022. /**
  1023. * TypeSystemExtension :
  1024. * - SchemaExtension
  1025. * - TypeExtension
  1026. *
  1027. * TypeExtension :
  1028. * - ScalarTypeExtension
  1029. * - ObjectTypeExtension
  1030. * - InterfaceTypeExtension
  1031. * - UnionTypeExtension
  1032. * - EnumTypeExtension
  1033. * - InputObjectTypeDefinition
  1034. */
  1035. parseTypeSystemExtension(): TypeSystemExtensionNode {
  1036. const keywordToken = this._lexer.lookahead();
  1037. if (keywordToken.kind === TokenKind.NAME) {
  1038. switch (keywordToken.value) {
  1039. case 'schema':
  1040. return this.parseSchemaExtension();
  1041. case 'scalar':
  1042. return this.parseScalarTypeExtension();
  1043. case 'type':
  1044. return this.parseObjectTypeExtension();
  1045. case 'interface':
  1046. return this.parseInterfaceTypeExtension();
  1047. case 'union':
  1048. return this.parseUnionTypeExtension();
  1049. case 'enum':
  1050. return this.parseEnumTypeExtension();
  1051. case 'input':
  1052. return this.parseInputObjectTypeExtension();
  1053. }
  1054. }
  1055. throw this.unexpected(keywordToken);
  1056. }
  1057. /**
  1058. * SchemaExtension :
  1059. * - extend schema Directives[Const]? { OperationTypeDefinition+ }
  1060. * - extend schema Directives[Const]
  1061. */
  1062. parseSchemaExtension(): SchemaExtensionNode {
  1063. const start = this._lexer.token;
  1064. this.expectKeyword('extend');
  1065. this.expectKeyword('schema');
  1066. const directives = this.parseDirectives(true);
  1067. const operationTypes = this.optionalMany(
  1068. TokenKind.BRACE_L,
  1069. this.parseOperationTypeDefinition,
  1070. TokenKind.BRACE_R,
  1071. );
  1072. if (directives.length === 0 && operationTypes.length === 0) {
  1073. throw this.unexpected();
  1074. }
  1075. return {
  1076. kind: Kind.SCHEMA_EXTENSION,
  1077. directives,
  1078. operationTypes,
  1079. loc: this.loc(start),
  1080. };
  1081. }
  1082. /**
  1083. * ScalarTypeExtension :
  1084. * - extend scalar Name Directives[Const]
  1085. */
  1086. parseScalarTypeExtension(): ScalarTypeExtensionNode {
  1087. const start = this._lexer.token;
  1088. this.expectKeyword('extend');
  1089. this.expectKeyword('scalar');
  1090. const name = this.parseName();
  1091. const directives = this.parseDirectives(true);
  1092. if (directives.length === 0) {
  1093. throw this.unexpected();
  1094. }
  1095. return {
  1096. kind: Kind.SCALAR_TYPE_EXTENSION,
  1097. name,
  1098. directives,
  1099. loc: this.loc(start),
  1100. };
  1101. }
  1102. /**
  1103. * ObjectTypeExtension :
  1104. * - extend type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition
  1105. * - extend type Name ImplementsInterfaces? Directives[Const]
  1106. * - extend type Name ImplementsInterfaces
  1107. */
  1108. parseObjectTypeExtension(): ObjectTypeExtensionNode {
  1109. const start = this._lexer.token;
  1110. this.expectKeyword('extend');
  1111. this.expectKeyword('type');
  1112. const name = this.parseName();
  1113. const interfaces = this.parseImplementsInterfaces();
  1114. const directives = this.parseDirectives(true);
  1115. const fields = this.parseFieldsDefinition();
  1116. if (
  1117. interfaces.length === 0 &&
  1118. directives.length === 0 &&
  1119. fields.length === 0
  1120. ) {
  1121. throw this.unexpected();
  1122. }
  1123. return {
  1124. kind: Kind.OBJECT_TYPE_EXTENSION,
  1125. name,
  1126. interfaces,
  1127. directives,
  1128. fields,
  1129. loc: this.loc(start),
  1130. };
  1131. }
  1132. /**
  1133. * InterfaceTypeExtension :
  1134. * - extend interface Name Directives[Const]? FieldsDefinition
  1135. * - extend interface Name Directives[Const]
  1136. */
  1137. parseInterfaceTypeExtension(): InterfaceTypeExtensionNode {
  1138. const start = this._lexer.token;
  1139. this.expectKeyword('extend');
  1140. this.expectKeyword('interface');
  1141. const name = this.parseName();
  1142. const directives = this.parseDirectives(true);
  1143. const fields = this.parseFieldsDefinition();
  1144. if (directives.length === 0 && fields.length === 0) {
  1145. throw this.unexpected();
  1146. }
  1147. return {
  1148. kind: Kind.INTERFACE_TYPE_EXTENSION,
  1149. name,
  1150. directives,
  1151. fields,
  1152. loc: this.loc(start),
  1153. };
  1154. }
  1155. /**
  1156. * UnionTypeExtension :
  1157. * - extend union Name Directives[Const]? UnionMemberTypes
  1158. * - extend union Name Directives[Const]
  1159. */
  1160. parseUnionTypeExtension(): UnionTypeExtensionNode {
  1161. const start = this._lexer.token;
  1162. this.expectKeyword('extend');
  1163. this.expectKeyword('union');
  1164. const name = this.parseName();
  1165. const directives = this.parseDirectives(true);
  1166. const types = this.parseUnionMemberTypes();
  1167. if (directives.length === 0 && types.length === 0) {
  1168. throw this.unexpected();
  1169. }
  1170. return {
  1171. kind: Kind.UNION_TYPE_EXTENSION,
  1172. name,
  1173. directives,
  1174. types,
  1175. loc: this.loc(start),
  1176. };
  1177. }
  1178. /**
  1179. * EnumTypeExtension :
  1180. * - extend enum Name Directives[Const]? EnumValuesDefinition
  1181. * - extend enum Name Directives[Const]
  1182. */
  1183. parseEnumTypeExtension(): EnumTypeExtensionNode {
  1184. const start = this._lexer.token;
  1185. this.expectKeyword('extend');
  1186. this.expectKeyword('enum');
  1187. const name = this.parseName();
  1188. const directives = this.parseDirectives(true);
  1189. const values = this.parseEnumValuesDefinition();
  1190. if (directives.length === 0 && values.length === 0) {
  1191. throw this.unexpected();
  1192. }
  1193. return {
  1194. kind: Kind.ENUM_TYPE_EXTENSION,
  1195. name,
  1196. directives,
  1197. values,
  1198. loc: this.loc(start),
  1199. };
  1200. }
  1201. /**
  1202. * InputObjectTypeExtension :
  1203. * - extend input Name Directives[Const]? InputFieldsDefinition
  1204. * - extend input Name Directives[Const]
  1205. */
  1206. parseInputObjectTypeExtension(): InputObjectTypeExtensionNode {
  1207. const start = this._lexer.token;
  1208. this.expectKeyword('extend');
  1209. this.expectKeyword('input');
  1210. const name = this.parseName();
  1211. const directives = this.parseDirectives(true);
  1212. const fields = this.parseInputFieldsDefinition();
  1213. if (directives.length === 0 && fields.length === 0) {
  1214. throw this.unexpected();
  1215. }
  1216. return {
  1217. kind: Kind.INPUT_OBJECT_TYPE_EXTENSION,
  1218. name,
  1219. directives,
  1220. fields,
  1221. loc: this.loc(start),
  1222. };
  1223. }
  1224. /**
  1225. * DirectiveDefinition :
  1226. * - Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations
  1227. */
  1228. parseDirectiveDefinition(): DirectiveDefinitionNode {
  1229. const start = this._lexer.token;
  1230. const description = this.parseDescription();
  1231. this.expectKeyword('directive');
  1232. this.expectToken(TokenKind.AT);
  1233. const name = this.parseName();
  1234. const args = this.parseArgumentDefs();
  1235. const repeatable = this.expectOptionalKeyword('repeatable');
  1236. this.expectKeyword('on');
  1237. const locations = this.parseDirectiveLocations();
  1238. return {
  1239. kind: Kind.DIRECTIVE_DEFINITION,
  1240. description,
  1241. name,
  1242. arguments: args,
  1243. repeatable,
  1244. locations,
  1245. loc: this.loc(start),
  1246. };
  1247. }
  1248. /**
  1249. * DirectiveLocations :
  1250. * - `|`? DirectiveLocation
  1251. * - DirectiveLocations | DirectiveLocation
  1252. */
  1253. parseDirectiveLocations(): Array<NameNode> {
  1254. // Optional leading pipe
  1255. this.expectOptionalToken(TokenKind.PIPE);
  1256. const locations = [];
  1257. do {
  1258. locations.push(this.parseDirectiveLocation());
  1259. } while (this.expectOptionalToken(TokenKind.PIPE));
  1260. return locations;
  1261. }
  1262. /*
  1263. * DirectiveLocation :
  1264. * - ExecutableDirectiveLocation
  1265. * - TypeSystemDirectiveLocation
  1266. *
  1267. * ExecutableDirectiveLocation : one of
  1268. * `QUERY`
  1269. * `MUTATION`
  1270. * `SUBSCRIPTION`
  1271. * `FIELD`
  1272. * `FRAGMENT_DEFINITION`
  1273. * `FRAGMENT_SPREAD`
  1274. * `INLINE_FRAGMENT`
  1275. *
  1276. * TypeSystemDirectiveLocation : one of
  1277. * `SCHEMA`
  1278. * `SCALAR`
  1279. * `OBJECT`
  1280. * `FIELD_DEFINITION`
  1281. * `ARGUMENT_DEFINITION`
  1282. * `INTERFACE`
  1283. * `UNION`
  1284. * `ENUM`
  1285. * `ENUM_VALUE`
  1286. * `INPUT_OBJECT`
  1287. * `INPUT_FIELD_DEFINITION`
  1288. */
  1289. parseDirectiveLocation(): NameNode {
  1290. const start = this._lexer.token;
  1291. const name = this.parseName();
  1292. if (DirectiveLocation[name.value] !== undefined) {
  1293. return name;
  1294. }
  1295. throw this.unexpected(start);
  1296. }
  1297. // Core parsing utility functions
  1298. /**
  1299. * Returns a location object, used to identify the place in
  1300. * the source that created a given parsed object.
  1301. */
  1302. loc(startToken: Token): Location | void {
  1303. if (!this._options.noLocation) {
  1304. return new Loc(startToken, this._lexer.lastToken, this._lexer.source);
  1305. }
  1306. }
  1307. /**
  1308. * Determines if the next token is of a given kind
  1309. */
  1310. peek(kind: TokenKindEnum): boolean {
  1311. return this._lexer.token.kind === kind;
  1312. }
  1313. /**
  1314. * If the next token is of the given kind, return that token after advancing
  1315. * the lexer. Otherwise, do not change the parser state and throw an error.
  1316. */
  1317. expectToken(kind: TokenKindEnum): Token {
  1318. const token = this._lexer.token;
  1319. if (token.kind === kind) {
  1320. this._lexer.advance();
  1321. return token;
  1322. }
  1323. throw syntaxError(
  1324. this._lexer.source,
  1325. token.start,
  1326. `Expected ${kind}, found ${getTokenDesc(token)}`,
  1327. );
  1328. }
  1329. /**
  1330. * If the next token is of the given kind, return that token after advancing
  1331. * the lexer. Otherwise, do not change the parser state and return undefined.
  1332. */
  1333. expectOptionalToken(kind: TokenKindEnum): ?Token {
  1334. const token = this._lexer.token;
  1335. if (token.kind === kind) {
  1336. this._lexer.advance();
  1337. return token;
  1338. }
  1339. return undefined;
  1340. }
  1341. /**
  1342. * If the next token is a given keyword, advance the lexer.
  1343. * Otherwise, do not change the parser state and throw an error.
  1344. */
  1345. expectKeyword(value: string) {
  1346. const token = this._lexer.token;
  1347. if (token.kind === TokenKind.NAME && token.value === value) {
  1348. this._lexer.advance();
  1349. } else {
  1350. throw syntaxError(
  1351. this._lexer.source,
  1352. token.start,
  1353. `Expected "${value}", found ${getTokenDesc(token)}`,
  1354. );
  1355. }
  1356. }
  1357. /**
  1358. * If the next token is a given keyword, return "true" after advancing
  1359. * the lexer. Otherwise, do not change the parser state and return "false".
  1360. */
  1361. expectOptionalKeyword(value: string): boolean {
  1362. const token = this._lexer.token;
  1363. if (token.kind === TokenKind.NAME && token.value === value) {
  1364. this._lexer.advance();
  1365. return true;
  1366. }
  1367. return false;
  1368. }
  1369. /**
  1370. * Helper function for creating an error when an unexpected lexed token
  1371. * is encountered.
  1372. */
  1373. unexpected(atToken?: ?Token): GraphQLError {
  1374. const token = atToken || this._lexer.token;
  1375. return syntaxError(
  1376. this._lexer.source,
  1377. token.start,
  1378. `Unexpected ${getTokenDesc(token)}`,
  1379. );
  1380. }
  1381. /**
  1382. * Returns a possibly empty list of parse nodes, determined by
  1383. * the parseFn. This list begins with a lex token of openKind
  1384. * and ends with a lex token of closeKind. Advances the parser
  1385. * to the next lex token after the closing token.
  1386. */
  1387. any<T>(
  1388. openKind: TokenKindEnum,
  1389. parseFn: () => T,
  1390. closeKind: TokenKindEnum,
  1391. ): Array<T> {
  1392. this.expectToken(openKind);
  1393. const nodes = [];
  1394. while (!this.expectOptionalToken(closeKind)) {
  1395. nodes.push(parseFn.call(this));
  1396. }
  1397. return nodes;
  1398. }
  1399. /**
  1400. * Returns a list of parse nodes, determined by the parseFn.
  1401. * It can be empty only if open token is missing otherwise it will always
  1402. * return non-empty list that begins with a lex token of openKind and ends
  1403. * with a lex token of closeKind. Advances the parser to the next lex token
  1404. * after the closing token.
  1405. */
  1406. optionalMany<T>(
  1407. openKind: TokenKindEnum,
  1408. parseFn: () => T,
  1409. closeKind: TokenKindEnum,
  1410. ): Array<T> {
  1411. if (this.expectOptionalToken(openKind)) {
  1412. const nodes = [];
  1413. do {
  1414. nodes.push(parseFn.call(this));
  1415. } while (!this.expectOptionalToken(closeKind));
  1416. return nodes;
  1417. }
  1418. return [];
  1419. }
  1420. /**
  1421. * Returns a non-empty list of parse nodes, determined by
  1422. * the parseFn. This list begins with a lex token of openKind
  1423. * and ends with a lex token of closeKind. Advances the parser
  1424. * to the next lex token after the closing token.
  1425. */
  1426. many<T>(
  1427. openKind: TokenKindEnum,
  1428. parseFn: () => T,
  1429. closeKind: TokenKindEnum,
  1430. ): Array<T> {
  1431. this.expectToken(openKind);
  1432. const nodes = [];
  1433. do {
  1434. nodes.push(parseFn.call(this));
  1435. } while (!this.expectOptionalToken(closeKind));
  1436. return nodes;
  1437. }
  1438. }
  1439. function Loc(startToken: Token, endToken: Token, source: Source) {
  1440. this.start = startToken.start;
  1441. this.end = endToken.end;
  1442. this.startToken = startToken;
  1443. this.endToken = endToken;
  1444. this.source = source;
  1445. }
  1446. // Print a simplified form when appearing in JSON/util.inspect.
  1447. defineToJSON(Loc, function() {
  1448. return { start: this.start, end: this.end };
  1449. });
  1450. /**
  1451. * A helper function to describe a token as a string for debugging
  1452. */
  1453. function getTokenDesc(token: Token): string {
  1454. const value = token.value;
  1455. return value ? `${token.kind} "${value}"` : token.kind;
  1456. }