1use combine::combinator::sep_by1;
2use combine::combinator::{choice, eof, many, many1, optional, position};
3use combine::easy::{Error, Errors};
4use combine::error::StreamError;
5use combine::{parser, ParseResult, Parser};
6
7use crate::common::{default_value, directives, parse_type, string};
8use crate::helpers::{ident, kind, name, punct};
9use crate::schema::ast::*;
10use crate::schema::error::ParseError;
11use crate::tokenizer::{Kind as T, Token, TokenStream};
12
13pub fn schema<'a>(input: &mut TokenStream<'a>) -> ParseResult<SchemaDefinition, TokenStream<'a>> {
14 (
15 position().skip(ident("schema")),
16 parser(directives),
17 punct("{")
18 .with(many((kind(T::Name).skip(punct(":")), name())))
19 .skip(punct("}")),
20 )
21 .flat_map(
22 |(position, directives, operations): (_, _, Vec<(Token, _)>)| {
23 let mut query = None;
24 let mut mutation = None;
25 let mut subscription = None;
26 let mut err = Errors::empty(position);
27 for (oper, type_name) in operations {
28 match oper.value {
29 "query" if query.is_some() => {
30 err.add_error(Error::unexpected_static_message(
31 "duplicate `query` operation",
32 ));
33 }
34 "query" => {
35 query = Some(type_name);
36 }
37 "mutation" if mutation.is_some() => {
38 err.add_error(Error::unexpected_static_message(
39 "duplicate `mutation` operation",
40 ));
41 }
42 "mutation" => {
43 mutation = Some(type_name);
44 }
45 "subscription" if subscription.is_some() => {
46 err.add_error(Error::unexpected_static_message(
47 "duplicate `subscription` operation",
48 ));
49 }
50 "subscription" => {
51 subscription = Some(type_name);
52 }
53 _ => {
54 err.add_error(Error::unexpected_token(oper));
55 err.add_error(Error::expected_static_message("query"));
56 err.add_error(Error::expected_static_message("mutation"));
57 err.add_error(Error::expected_static_message("subscription"));
58 }
59 }
60 }
61 if !err.errors.is_empty() {
62 return Err(err);
63 }
64 Ok(SchemaDefinition {
65 position,
66 directives,
67 query,
68 mutation,
69 subscription,
70 })
71 },
72 )
73 .parse_stream(input)
74}
75
76pub fn scalar_type<'a>(input: &mut TokenStream<'a>) -> ParseResult<ScalarType, TokenStream<'a>> {
77 (position(), ident("scalar").with(name()), parser(directives))
78 .map(|(position, name, directives)| ScalarType {
79 position,
80 description: None,
81 name,
82 directives,
83 })
84 .parse_stream(input)
85}
86
87pub fn scalar_type_extension<'a>(
88 input: &mut TokenStream<'a>,
89) -> ParseResult<ScalarTypeExtension, TokenStream<'a>> {
90 (position(), ident("scalar").with(name()), parser(directives))
91 .flat_map(|(position, name, directives)| {
92 if directives.is_empty() {
93 let mut e = Errors::empty(position);
94 e.add_error(Error::expected_static_message(
95 "Scalar type extension should contain at least \
96 one directive.",
97 ));
98 return Err(e);
99 }
100 Ok(ScalarTypeExtension {
101 position,
102 name,
103 directives,
104 })
105 })
106 .parse_stream(input)
107}
108
109pub fn implements_interfaces<'a>(
110 input: &mut TokenStream<'a>,
111) -> ParseResult<Vec<NamedType>, TokenStream<'a>> {
112 optional(
113 ident("implements")
114 .skip(optional(punct("&")))
115 .with(sep_by1(name(), punct("&"))),
116 )
117 .map(|opt| opt.unwrap_or_else(Vec::new))
118 .parse_stream(input)
119}
120
121pub fn input_value<'a>(input: &mut TokenStream<'a>) -> ParseResult<InputValue, TokenStream<'a>> {
122 (
123 position(),
124 optional(parser(string)),
125 name(),
126 punct(":").with(parser(parse_type)),
127 optional(punct("=").with(parser(default_value))),
128 parser(directives),
129 )
130 .map(
131 |(position, description, name, value_type, default_value, directives)| InputValue {
132 position,
133 description,
134 name,
135 value_type,
136 default_value,
137 directives,
138 },
139 )
140 .parse_stream(input)
141}
142
143pub fn arguments_definition<'a>(
144 input: &mut TokenStream<'a>,
145) -> ParseResult<Vec<InputValue>, TokenStream<'a>> {
146 optional(punct("(").with(many1(parser(input_value))).skip(punct(")")))
147 .map(|v| v.unwrap_or_else(Vec::new))
148 .parse_stream(input)
149}
150
151pub fn field<'a>(input: &mut TokenStream<'a>) -> ParseResult<Field, TokenStream<'a>> {
152 (
153 position(),
154 optional(parser(string)),
155 name(),
156 parser(arguments_definition),
157 punct(":").with(parser(parse_type)),
158 parser(directives),
159 )
160 .map(
161 |(position, description, name, arguments, field_type, directives)| Field {
162 position,
163 description,
164 name,
165 arguments,
166 field_type,
167 directives,
168 },
169 )
170 .parse_stream(input)
171}
172
173pub fn fields<'a>(input: &mut TokenStream<'a>) -> ParseResult<Vec<Field>, TokenStream<'a>> {
174 optional(punct("{").with(many1(parser(field))).skip(punct("}")))
175 .map(|v| v.unwrap_or_else(Vec::new))
176 .parse_stream(input)
177}
178
179pub fn object_type<'a>(input: &mut TokenStream<'a>) -> ParseResult<ObjectType, TokenStream<'a>> {
180 (
181 position(),
182 ident("type").with(name()),
183 parser(implements_interfaces),
184 parser(directives),
185 parser(fields),
186 )
187 .map(|(position, name, interfaces, directives, fields)| {
188 ObjectType {
189 position,
190 name,
191 directives,
192 fields,
193 implements_interfaces: interfaces,
194 description: None, }
196 })
197 .parse_stream(input)
198}
199
200pub fn object_type_extension<'a>(
201 input: &mut TokenStream<'a>,
202) -> ParseResult<ObjectTypeExtension, TokenStream<'a>> {
203 (
204 position(),
205 ident("type").with(name()),
206 parser(implements_interfaces),
207 parser(directives),
208 parser(fields),
209 )
210 .flat_map(|(position, name, interfaces, directives, fields)| {
211 if interfaces.is_empty() && directives.is_empty() && fields.is_empty() {
212 let mut e = Errors::empty(position);
213 e.add_error(Error::expected_static_message(
214 "Object type extension should contain at least \
215 one interface, directive or field.",
216 ));
217 return Err(e);
218 }
219 Ok(ObjectTypeExtension {
220 position,
221 name,
222 directives,
223 fields,
224 implements_interfaces: interfaces,
225 })
226 })
227 .parse_stream(input)
228}
229
230pub fn interface_type<'a>(
231 input: &mut TokenStream<'a>,
232) -> ParseResult<InterfaceType, TokenStream<'a>> {
233 (
234 position(),
235 ident("interface").with(name()),
236 parser(directives),
237 parser(fields),
238 )
239 .map(|(position, name, directives, fields)| {
240 InterfaceType {
241 position,
242 name,
243 directives,
244 fields,
245 description: None, }
247 })
248 .parse_stream(input)
249}
250
251pub fn interface_type_extension<'a>(
252 input: &mut TokenStream<'a>,
253) -> ParseResult<InterfaceTypeExtension, TokenStream<'a>> {
254 (
255 position(),
256 ident("interface").with(name()),
257 parser(directives),
258 parser(fields),
259 )
260 .flat_map(|(position, name, directives, fields)| {
261 if directives.is_empty() && fields.is_empty() {
262 let mut e = Errors::empty(position);
263 e.add_error(Error::expected_static_message(
264 "Interface type extension should contain at least \
265 one directive or field.",
266 ));
267 return Err(e);
268 }
269 Ok(InterfaceTypeExtension {
270 position,
271 name,
272 directives,
273 fields,
274 })
275 })
276 .parse_stream(input)
277}
278
279pub fn union_members<'a>(
280 input: &mut TokenStream<'a>,
281) -> ParseResult<Vec<NamedType>, TokenStream<'a>> {
282 optional(punct("|"))
283 .with(sep_by1(name(), punct("|")))
284 .parse_stream(input)
285}
286
287pub fn union_type<'a>(input: &mut TokenStream<'a>) -> ParseResult<UnionType, TokenStream<'a>> {
288 (
289 position(),
290 ident("union").with(name()),
291 parser(directives),
292 optional(punct("=").with(parser(union_members))),
293 )
294 .map(|(position, name, directives, types)| {
295 UnionType {
296 position,
297 name,
298 directives,
299 types: types.unwrap_or_else(Vec::new),
300 description: None, }
302 })
303 .parse_stream(input)
304}
305
306pub fn union_type_extension<'a>(
307 input: &mut TokenStream<'a>,
308) -> ParseResult<UnionTypeExtension, TokenStream<'a>> {
309 (
310 position(),
311 ident("union").with(name()),
312 parser(directives),
313 optional(punct("=").with(parser(union_members))),
314 )
315 .flat_map(|(position, name, directives, types)| {
316 if directives.is_empty() && types.is_none() {
317 let mut e = Errors::empty(position);
318 e.add_error(Error::expected_static_message(
319 "Union type extension should contain at least \
320 one directive or type.",
321 ));
322 return Err(e);
323 }
324 Ok(UnionTypeExtension {
325 position,
326 name,
327 directives,
328 types: types.unwrap_or_else(Vec::new),
329 })
330 })
331 .parse_stream(input)
332}
333
334pub fn enum_values<'a>(
335 input: &mut TokenStream<'a>,
336) -> ParseResult<Vec<EnumValue>, TokenStream<'a>> {
337 punct("{")
338 .with(many1(
339 (
340 position(),
341 optional(parser(string)),
342 name(),
343 parser(directives),
344 )
345 .map(|(position, description, name, directives)| EnumValue {
346 position,
347 description,
348 name,
349 directives,
350 }),
351 ))
352 .skip(punct("}"))
353 .parse_stream(input)
354}
355
356pub fn enum_type<'a>(input: &mut TokenStream<'a>) -> ParseResult<EnumType, TokenStream<'a>> {
357 (
358 position(),
359 ident("enum").with(name()),
360 parser(directives),
361 optional(parser(enum_values)),
362 )
363 .map(|(position, name, directives, values)| {
364 EnumType {
365 position,
366 name,
367 directives,
368 values: values.unwrap_or_else(Vec::new),
369 description: None, }
371 })
372 .parse_stream(input)
373}
374
375pub fn enum_type_extension<'a>(
376 input: &mut TokenStream<'a>,
377) -> ParseResult<EnumTypeExtension, TokenStream<'a>> {
378 (
379 position(),
380 ident("enum").with(name()),
381 parser(directives),
382 optional(parser(enum_values)),
383 )
384 .flat_map(|(position, name, directives, values)| {
385 if directives.is_empty() && values.is_none() {
386 let mut e = Errors::empty(position);
387 e.add_error(Error::expected_static_message(
388 "Enum type extension should contain at least \
389 one directive or value.",
390 ));
391 return Err(e);
392 }
393 Ok(EnumTypeExtension {
394 position,
395 name,
396 directives,
397 values: values.unwrap_or_else(Vec::new),
398 })
399 })
400 .parse_stream(input)
401}
402
403pub fn input_fields<'a>(
404 input: &mut TokenStream<'a>,
405) -> ParseResult<Vec<InputValue>, TokenStream<'a>> {
406 optional(punct("{").with(many1(parser(input_value))).skip(punct("}")))
407 .map(|v| v.unwrap_or_else(Vec::new))
408 .parse_stream(input)
409}
410
411pub fn input_object_type<'a>(
412 input: &mut TokenStream<'a>,
413) -> ParseResult<InputObjectType, TokenStream<'a>> {
414 (
415 position(),
416 ident("input").with(name()),
417 parser(directives),
418 parser(input_fields),
419 )
420 .map(|(position, name, directives, fields)| {
421 InputObjectType {
422 position,
423 name,
424 directives,
425 fields,
426 description: None, }
428 })
429 .parse_stream(input)
430}
431
432pub fn input_object_type_extension<'a>(
433 input: &mut TokenStream<'a>,
434) -> ParseResult<InputObjectTypeExtension, TokenStream<'a>> {
435 (
436 position(),
437 ident("input").with(name()),
438 parser(directives),
439 parser(input_fields),
440 )
441 .flat_map(|(position, name, directives, fields)| {
442 if directives.is_empty() && fields.is_empty() {
443 let mut e = Errors::empty(position);
444 e.add_error(Error::expected_static_message(
445 "Input object type extension should contain at least \
446 one directive or field.",
447 ));
448 return Err(e);
449 }
450 Ok(InputObjectTypeExtension {
451 position,
452 name,
453 directives,
454 fields,
455 })
456 })
457 .parse_stream(input)
458}
459
460pub fn directive_locations<'a>(
461 input: &mut TokenStream<'a>,
462) -> ParseResult<Vec<DirectiveLocation>, TokenStream<'a>> {
463 optional(optional(punct("|")).with(sep_by1(
464 kind(T::Name).and_then(|tok| tok.value.parse::<DirectiveLocation>()),
465 punct("|"),
466 )))
467 .map(|opt| opt.unwrap_or_else(Vec::new))
468 .parse_stream(input)
469}
470
471pub fn directive_definition<'a>(
472 input: &mut TokenStream<'a>,
473) -> ParseResult<DirectiveDefinition, TokenStream<'a>> {
474 (
475 position(),
476 ident("directive").and(punct("@")).with(name()),
477 parser(arguments_definition),
478 optional(ident("repeatable")),
479 ident("on").with(parser(directive_locations)),
480 )
481 .map(|(position, name, arguments, repeatable, locations)| {
482 DirectiveDefinition {
483 position,
484 name,
485 arguments,
486 locations,
487 repeatable: repeatable.is_some(),
488 description: None, }
490 })
491 .parse_stream(input)
492}
493
494pub fn described_definition<'a>(
495 input: &mut TokenStream<'a>,
496) -> ParseResult<Definition, TokenStream<'a>> {
497 use self::TypeDefinition::*;
498 (
499 optional(parser(string)),
500 choice((
501 choice((
502 parser(scalar_type).map(Scalar),
503 parser(object_type).map(Object),
504 parser(interface_type).map(Interface),
505 parser(union_type).map(Union),
506 parser(enum_type).map(Enum),
507 parser(input_object_type).map(InputObject),
508 ))
509 .map(Definition::TypeDefinition),
510 parser(directive_definition).map(Definition::DirectiveDefinition),
511 )),
512 )
513 .map(|(descr, mut def)| {
517 use crate::schema::ast::Definition::TypeDefinition as T;
518 use crate::schema::ast::Definition::*;
519 use crate::schema::ast::TypeDefinition::*;
520 match def {
521 T(Scalar(ref mut s)) => s.description = descr,
522 T(Object(ref mut o)) => o.description = descr,
523 T(Interface(ref mut i)) => i.description = descr,
524 T(Union(ref mut u)) => u.description = descr,
525 T(Enum(ref mut e)) => e.description = descr,
526 T(InputObject(ref mut o)) => o.description = descr,
527 DirectiveDefinition(ref mut d) => d.description = descr,
528 SchemaDefinition(_) => unreachable!(),
529 TypeExtension(_) => unreachable!(),
530 }
531 def
532 })
533 .parse_stream(input)
534}
535
536pub fn type_extension<'a>(
537 input: &mut TokenStream<'a>,
538) -> ParseResult<TypeExtension, TokenStream<'a>> {
539 ident("extend")
540 .with(choice((
541 parser(scalar_type_extension).map(TypeExtension::Scalar),
542 parser(object_type_extension).map(TypeExtension::Object),
543 parser(interface_type_extension).map(TypeExtension::Interface),
544 parser(union_type_extension).map(TypeExtension::Union),
545 parser(enum_type_extension).map(TypeExtension::Enum),
546 parser(input_object_type_extension).map(TypeExtension::InputObject),
547 )))
548 .parse_stream(input)
549}
550
551pub fn definition<'a>(input: &mut TokenStream<'a>) -> ParseResult<Definition, TokenStream<'a>> {
552 choice((
553 parser(schema).map(Definition::SchemaDefinition),
554 parser(type_extension).map(Definition::TypeExtension),
555 parser(described_definition),
556 ))
557 .parse_stream(input)
558}
559
560pub fn parse_schema(s: &str) -> Result<Document, ParseError> {
562 let mut tokens = TokenStream::new(s);
563 let (doc, _) = many1(parser(definition))
564 .map(|d| Document { definitions: d })
565 .skip(eof())
566 .parse_stream(&mut tokens)
567 .map_err(|e| e.into_inner().error)?;
568
569 Ok(doc)
570}
571
572#[cfg(test)]
573mod test {
574 use super::parse_schema;
575 use crate::position::Pos;
576 use crate::schema::grammar::*;
577
578 fn ast(s: &str) -> Document {
579 parse_schema(s).unwrap()
580 }
581
582 #[test]
583 fn one_field() {
584 assert_eq!(
585 ast("schema { query: Query }"),
586 Document {
587 definitions: vec![Definition::SchemaDefinition(SchemaDefinition {
588 position: Pos { line: 1, column: 1 },
589 directives: vec![],
590 query: Some("Query".into()),
591 mutation: None,
592 subscription: None
593 })],
594 }
595 );
596 }
597}