parser.js.flow 42 KB

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