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