schema.go

  1package parser
  2
  3import (
  4	. "github.com/vektah/gqlparser/ast"
  5	"github.com/vektah/gqlparser/gqlerror"
  6	"github.com/vektah/gqlparser/lexer"
  7)
  8
  9func ParseSchema(source *Source) (*SchemaDocument, *gqlerror.Error) {
 10	p := parser{
 11		lexer: lexer.New(source),
 12	}
 13	return p.parseSchemaDocument(), p.err
 14}
 15
 16func (p *parser) parseSchemaDocument() *SchemaDocument {
 17	var doc SchemaDocument
 18	doc.Position = p.peekPos()
 19	for p.peek().Kind != lexer.EOF {
 20		if p.err != nil {
 21			return nil
 22		}
 23
 24		var description string
 25		if p.peek().Kind == lexer.BlockString || p.peek().Kind == lexer.String {
 26			description = p.parseDescription()
 27		}
 28
 29		if p.peek().Kind != lexer.Name {
 30			p.unexpectedError()
 31			break
 32		}
 33
 34		switch p.peek().Value {
 35		case "scalar", "type", "interface", "union", "enum", "input":
 36			doc.Definitions = append(doc.Definitions, p.parseTypeSystemDefinition(description))
 37		case "schema":
 38			doc.Schema = append(doc.Schema, p.parseSchemaDefinition(description))
 39		case "directive":
 40			doc.Directives = append(doc.Directives, p.parseDirectiveDefinition(description))
 41		case "extend":
 42			if description != "" {
 43				p.unexpectedToken(p.prev)
 44			}
 45			p.parseTypeSystemExtension(&doc)
 46		default:
 47			p.unexpectedError()
 48			return nil
 49		}
 50	}
 51
 52	return &doc
 53}
 54
 55func (p *parser) parseDescription() string {
 56	token := p.peek()
 57
 58	if token.Kind != lexer.BlockString && token.Kind != lexer.String {
 59		return ""
 60	}
 61
 62	return p.next().Value
 63}
 64
 65func (p *parser) parseTypeSystemDefinition(description string) *Definition {
 66	tok := p.peek()
 67	if tok.Kind != lexer.Name {
 68		p.unexpectedError()
 69		return nil
 70	}
 71
 72	switch tok.Value {
 73	case "scalar":
 74		return p.parseScalarTypeDefinition(description)
 75	case "type":
 76		return p.parseObjectTypeDefinition(description)
 77	case "interface":
 78		return p.parseInterfaceTypeDefinition(description)
 79	case "union":
 80		return p.parseUnionTypeDefinition(description)
 81	case "enum":
 82		return p.parseEnumTypeDefinition(description)
 83	case "input":
 84		return p.parseInputObjectTypeDefinition(description)
 85	default:
 86		p.unexpectedError()
 87		return nil
 88	}
 89}
 90
 91func (p *parser) parseSchemaDefinition(description string) *SchemaDefinition {
 92	p.expectKeyword("schema")
 93
 94	def := SchemaDefinition{Description: description}
 95	def.Position = p.peekPos()
 96	def.Description = description
 97	def.Directives = p.parseDirectives(true)
 98
 99	p.many(lexer.BraceL, lexer.BraceR, func() {
100		def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition())
101	})
102	return &def
103}
104
105func (p *parser) parseOperationTypeDefinition() *OperationTypeDefinition {
106	var op OperationTypeDefinition
107	op.Position = p.peekPos()
108	op.Operation = p.parseOperationType()
109	p.expect(lexer.Colon)
110	op.Type = p.parseName()
111	return &op
112}
113
114func (p *parser) parseScalarTypeDefinition(description string) *Definition {
115	p.expectKeyword("scalar")
116
117	var def Definition
118	def.Position = p.peekPos()
119	def.Kind = Scalar
120	def.Description = description
121	def.Name = p.parseName()
122	def.Directives = p.parseDirectives(true)
123	return &def
124}
125
126func (p *parser) parseObjectTypeDefinition(description string) *Definition {
127	p.expectKeyword("type")
128
129	var def Definition
130	def.Position = p.peekPos()
131	def.Kind = Object
132	def.Description = description
133	def.Name = p.parseName()
134	def.Interfaces = p.parseImplementsInterfaces()
135	def.Directives = p.parseDirectives(true)
136	def.Fields = p.parseFieldsDefinition()
137	return &def
138}
139
140func (p *parser) parseImplementsInterfaces() []string {
141	var types []string
142	if p.peek().Value == "implements" {
143		p.next()
144		// optional leading ampersand
145		p.skip(lexer.Amp)
146
147		types = append(types, p.parseName())
148		for p.skip(lexer.Amp) && p.err == nil {
149			types = append(types, p.parseName())
150		}
151	}
152	return types
153}
154
155func (p *parser) parseFieldsDefinition() FieldList {
156	var defs FieldList
157	p.many(lexer.BraceL, lexer.BraceR, func() {
158		defs = append(defs, p.parseFieldDefinition())
159	})
160	return defs
161}
162
163func (p *parser) parseFieldDefinition() *FieldDefinition {
164	var def FieldDefinition
165	def.Position = p.peekPos()
166	def.Description = p.parseDescription()
167	def.Name = p.parseName()
168	def.Arguments = p.parseArgumentDefs()
169	p.expect(lexer.Colon)
170	def.Type = p.parseTypeReference()
171	def.Directives = p.parseDirectives(true)
172
173	return &def
174}
175
176func (p *parser) parseArgumentDefs() ArgumentDefinitionList {
177	var args ArgumentDefinitionList
178	p.many(lexer.ParenL, lexer.ParenR, func() {
179		args = append(args, p.parseArgumentDef())
180	})
181	return args
182}
183
184func (p *parser) parseArgumentDef() *ArgumentDefinition {
185	var def ArgumentDefinition
186	def.Position = p.peekPos()
187	def.Description = p.parseDescription()
188	def.Name = p.parseName()
189	p.expect(lexer.Colon)
190	def.Type = p.parseTypeReference()
191	if p.skip(lexer.Equals) {
192		def.DefaultValue = p.parseValueLiteral(true)
193	}
194	def.Directives = p.parseDirectives(true)
195	return &def
196}
197
198func (p *parser) parseInputValueDef() *FieldDefinition {
199	var def FieldDefinition
200	def.Position = p.peekPos()
201	def.Description = p.parseDescription()
202	def.Name = p.parseName()
203	p.expect(lexer.Colon)
204	def.Type = p.parseTypeReference()
205	if p.skip(lexer.Equals) {
206		def.DefaultValue = p.parseValueLiteral(true)
207	}
208	def.Directives = p.parseDirectives(true)
209	return &def
210}
211
212func (p *parser) parseInterfaceTypeDefinition(description string) *Definition {
213	p.expectKeyword("interface")
214
215	var def Definition
216	def.Position = p.peekPos()
217	def.Kind = Interface
218	def.Description = description
219	def.Name = p.parseName()
220	def.Directives = p.parseDirectives(true)
221	def.Fields = p.parseFieldsDefinition()
222	return &def
223}
224
225func (p *parser) parseUnionTypeDefinition(description string) *Definition {
226	p.expectKeyword("union")
227
228	var def Definition
229	def.Position = p.peekPos()
230	def.Kind = Union
231	def.Description = description
232	def.Name = p.parseName()
233	def.Directives = p.parseDirectives(true)
234	def.Types = p.parseUnionMemberTypes()
235	return &def
236}
237
238func (p *parser) parseUnionMemberTypes() []string {
239	var types []string
240	if p.skip(lexer.Equals) {
241		// optional leading pipe
242		p.skip(lexer.Pipe)
243
244		types = append(types, p.parseName())
245		for p.skip(lexer.Pipe) && p.err == nil {
246			types = append(types, p.parseName())
247		}
248	}
249	return types
250}
251
252func (p *parser) parseEnumTypeDefinition(description string) *Definition {
253	p.expectKeyword("enum")
254
255	var def Definition
256	def.Position = p.peekPos()
257	def.Kind = Enum
258	def.Description = description
259	def.Name = p.parseName()
260	def.Directives = p.parseDirectives(true)
261	def.EnumValues = p.parseEnumValuesDefinition()
262	return &def
263}
264
265func (p *parser) parseEnumValuesDefinition() EnumValueList {
266	var values EnumValueList
267	p.many(lexer.BraceL, lexer.BraceR, func() {
268		values = append(values, p.parseEnumValueDefinition())
269	})
270	return values
271}
272
273func (p *parser) parseEnumValueDefinition() *EnumValueDefinition {
274	return &EnumValueDefinition{
275		Position:    p.peekPos(),
276		Description: p.parseDescription(),
277		Name:        p.parseName(),
278		Directives:  p.parseDirectives(true),
279	}
280}
281
282func (p *parser) parseInputObjectTypeDefinition(description string) *Definition {
283	p.expectKeyword("input")
284
285	var def Definition
286	def.Position = p.peekPos()
287	def.Kind = InputObject
288	def.Description = description
289	def.Name = p.parseName()
290	def.Directives = p.parseDirectives(true)
291	def.Fields = p.parseInputFieldsDefinition()
292	return &def
293}
294
295func (p *parser) parseInputFieldsDefinition() FieldList {
296	var values FieldList
297	p.many(lexer.BraceL, lexer.BraceR, func() {
298		values = append(values, p.parseInputValueDef())
299	})
300	return values
301}
302
303func (p *parser) parseTypeSystemExtension(doc *SchemaDocument) {
304	p.expectKeyword("extend")
305
306	switch p.peek().Value {
307	case "schema":
308		doc.SchemaExtension = append(doc.SchemaExtension, p.parseSchemaExtension())
309	case "scalar":
310		doc.Extensions = append(doc.Extensions, p.parseScalarTypeExtension())
311	case "type":
312		doc.Extensions = append(doc.Extensions, p.parseObjectTypeExtension())
313	case "interface":
314		doc.Extensions = append(doc.Extensions, p.parseInterfaceTypeExtension())
315	case "union":
316		doc.Extensions = append(doc.Extensions, p.parseUnionTypeExtension())
317	case "enum":
318		doc.Extensions = append(doc.Extensions, p.parseEnumTypeExtension())
319	case "input":
320		doc.Extensions = append(doc.Extensions, p.parseInputObjectTypeExtension())
321	default:
322		p.unexpectedError()
323	}
324}
325
326func (p *parser) parseSchemaExtension() *SchemaDefinition {
327	p.expectKeyword("schema")
328
329	var def SchemaDefinition
330	def.Position = p.peekPos()
331	def.Directives = p.parseDirectives(true)
332	p.many(lexer.BraceL, lexer.BraceR, func() {
333		def.OperationTypes = append(def.OperationTypes, p.parseOperationTypeDefinition())
334	})
335	if len(def.Directives) == 0 && len(def.OperationTypes) == 0 {
336		p.unexpectedError()
337	}
338	return &def
339}
340
341func (p *parser) parseScalarTypeExtension() *Definition {
342	p.expectKeyword("scalar")
343
344	var def Definition
345	def.Position = p.peekPos()
346	def.Kind = Scalar
347	def.Name = p.parseName()
348	def.Directives = p.parseDirectives(true)
349	if len(def.Directives) == 0 {
350		p.unexpectedError()
351	}
352	return &def
353}
354
355func (p *parser) parseObjectTypeExtension() *Definition {
356	p.expectKeyword("type")
357
358	var def Definition
359	def.Position = p.peekPos()
360	def.Kind = Object
361	def.Name = p.parseName()
362	def.Interfaces = p.parseImplementsInterfaces()
363	def.Directives = p.parseDirectives(true)
364	def.Fields = p.parseFieldsDefinition()
365	if len(def.Interfaces) == 0 && len(def.Directives) == 0 && len(def.Fields) == 0 {
366		p.unexpectedError()
367	}
368	return &def
369}
370
371func (p *parser) parseInterfaceTypeExtension() *Definition {
372	p.expectKeyword("interface")
373
374	var def Definition
375	def.Position = p.peekPos()
376	def.Kind = Interface
377	def.Name = p.parseName()
378	def.Directives = p.parseDirectives(true)
379	def.Fields = p.parseFieldsDefinition()
380	if len(def.Directives) == 0 && len(def.Fields) == 0 {
381		p.unexpectedError()
382	}
383	return &def
384}
385
386func (p *parser) parseUnionTypeExtension() *Definition {
387	p.expectKeyword("union")
388
389	var def Definition
390	def.Position = p.peekPos()
391	def.Kind = Union
392	def.Name = p.parseName()
393	def.Directives = p.parseDirectives(true)
394	def.Types = p.parseUnionMemberTypes()
395
396	if len(def.Directives) == 0 && len(def.Types) == 0 {
397		p.unexpectedError()
398	}
399	return &def
400}
401
402func (p *parser) parseEnumTypeExtension() *Definition {
403	p.expectKeyword("enum")
404
405	var def Definition
406	def.Position = p.peekPos()
407	def.Kind = Enum
408	def.Name = p.parseName()
409	def.Directives = p.parseDirectives(true)
410	def.EnumValues = p.parseEnumValuesDefinition()
411	if len(def.Directives) == 0 && len(def.EnumValues) == 0 {
412		p.unexpectedError()
413	}
414	return &def
415}
416
417func (p *parser) parseInputObjectTypeExtension() *Definition {
418	p.expectKeyword("input")
419
420	var def Definition
421	def.Position = p.peekPos()
422	def.Kind = InputObject
423	def.Name = p.parseName()
424	def.Directives = p.parseDirectives(false)
425	def.Fields = p.parseInputFieldsDefinition()
426	if len(def.Directives) == 0 && len(def.Fields) == 0 {
427		p.unexpectedError()
428	}
429	return &def
430}
431
432func (p *parser) parseDirectiveDefinition(description string) *DirectiveDefinition {
433	p.expectKeyword("directive")
434	p.expect(lexer.At)
435
436	var def DirectiveDefinition
437	def.Position = p.peekPos()
438	def.Description = description
439	def.Name = p.parseName()
440	def.Arguments = p.parseArgumentDefs()
441
442	p.expectKeyword("on")
443	def.Locations = p.parseDirectiveLocations()
444	return &def
445}
446
447func (p *parser) parseDirectiveLocations() []DirectiveLocation {
448	p.skip(lexer.Pipe)
449
450	locations := []DirectiveLocation{p.parseDirectiveLocation()}
451
452	for p.skip(lexer.Pipe) && p.err == nil {
453		locations = append(locations, p.parseDirectiveLocation())
454	}
455
456	return locations
457}
458
459func (p *parser) parseDirectiveLocation() DirectiveLocation {
460	name := p.expect(lexer.Name)
461
462	switch name.Value {
463	case `QUERY`:
464		return LocationQuery
465	case `MUTATION`:
466		return LocationMutation
467	case `SUBSCRIPTION`:
468		return LocationSubscription
469	case `FIELD`:
470		return LocationField
471	case `FRAGMENT_DEFINITION`:
472		return LocationFragmentDefinition
473	case `FRAGMENT_SPREAD`:
474		return LocationFragmentSpread
475	case `INLINE_FRAGMENT`:
476		return LocationInlineFragment
477	case `SCHEMA`:
478		return LocationSchema
479	case `SCALAR`:
480		return LocationScalar
481	case `OBJECT`:
482		return LocationObject
483	case `FIELD_DEFINITION`:
484		return LocationFieldDefinition
485	case `ARGUMENT_DEFINITION`:
486		return LocationArgumentDefinition
487	case `INTERFACE`:
488		return LocationInterface
489	case `UNION`:
490		return LocationUnion
491	case `ENUM`:
492		return LocationEnum
493	case `ENUM_VALUE`:
494		return LocationEnumValue
495	case `INPUT_OBJECT`:
496		return LocationInputObject
497	case `INPUT_FIELD_DEFINITION`:
498		return LocationInputFieldDefinition
499	}
500
501	p.unexpectedToken(name)
502	return ""
503}