use type_definition::*;
grammar;
// TODO: missing others types
pub schema: Vec<TypeDefinition> =
<TypeDefinition*> => <>;
TypeDefinition: TypeDefinition = {
ScalarTypeDefinition,
ObjectTypeDefinition,
EnumTypeDefinition,
InterfaceTypeDefinition,
UnionTypeDefinition,
InputObjectTypeDefinition,
};
ScalarTypeDefinition: TypeDefinition = {
<d:Description?> "scalar" <n:Name> => {
TypeDefinition::ScalarType(GraphQLScalar::new(d, n))
}
};
ObjectTypeDefinition: TypeDefinition = {
<d:Description?> "type" <n:Name> <i:(ImplementsInterfaces?)> <r:(Directives?)> "{" <f:(Fields?)> "}" => {
TypeDefinition::ObjectType(GraphQLObject::new(d, n, i, r, f))
},
};
EnumTypeDefinition: TypeDefinition = {
<d:Description?> "enum" <n:Name> <r:(Directives?)> "{" <f:(<EnumValueDefinition>)+> "}" => {
TypeDefinition::EnumType(GraphQLEnum::new(d, n, r, f))
}
};
InterfaceTypeDefinition: TypeDefinition = {
<d:Description?> "interface" <n:Name> <r:(Directives?)> "{" <f:(Fields?)> "}" => {
TypeDefinition::InterfaceType(GraphQLInterface::new(d, n, r, f))
},
};
UnionTypeDefinition: TypeDefinition = {
<d:Description?> "union" <n:Name> <r:(Directives?)> <t:DefaultValue> => {
// This is dumb, but there seemes to be some ambiguity conflict with "="
let res: Vec<String> = t.split("|").map(|s| s.trim().to_string()).collect();
TypeDefinition::UnionType(GraphQLUnion::new(d, n, r, res))
}
};
InputObjectTypeDefinition: TypeDefinition = {
<d:Description?> "input" <n:Name> <r:(Directives?)> "{" <f:(Fields?)> "}" => {
TypeDefinition::InputObjectType(GraphQLInputObject::new(d, n, r, f))
},
};
ImplementsInterfaces: Vec<String> = {
"implements" <i:Comma<Name>> => {
i
}
};
Fields: Vec<GraphQLField> = {
<f:FieldDefinition+> => {
f
}
};
FieldDefinition: GraphQLField = {
<d:Description?> <n:FieldName> <a:(ArgumentsDefinition?)> ":" <t:FieldType> <r:(Directives?)> => {
GraphQLField::new(d, n, t, a, r)
}
};
EnumValueDefinition: GraphQLValue = {
<d:Description?> <n:Name> <r:(Directives?)> => {
GraphQLValue::new(d, n, r)
}
};
FieldType: FieldType = {
<n:Name> <r:"!"?> => {
FieldType {
name: n,
info: match r {
None => TypeInfo::Nullable,
Some(r) => TypeInfo::NonNullable,
}
}
},
"[" <n:Name> <r:"!"?> "]" <l:"!"?> => {
FieldType {
name: n,
info: match r {
None => match l {
None => TypeInfo::NullableListNullableElements,
Some(l) => TypeInfo::NonNullableListNullableElements
},
Some(r) => match l {
None => TypeInfo::NonNullableListNullableElements,
Some(l) => TypeInfo::NonNullableListNonNullableElements
}
}
}
}
};
ArgumentsDefinition: Vec<GraphQLArgument> = {
"(" <i:InputValueDefinition+> ")" => {
i
}
};
InputValueDefinition: GraphQLArgument = {
<d:Description?> <n:FieldName> ":" <t:FieldType> <v:DefaultValue?> <r:(Directives?)> => {
GraphQLArgument::new(d, n, t, v, r)
}
};
Directives: Vec<GraphQLDirective> = {
<d:Directive+> => {
d
}
};
Directive: GraphQLDirective = {
"@" <n:Name> <d:(DirectiveArgumentsDefinition)?> => {
GraphQLDirective::new(n, d)
}
};
DirectiveArgumentsDefinition: Vec<GraphQLDirectiveArgument> = {
"(" <d:DirectiveArgumentDefinition+> ")" => {
d
}
};
DirectiveArgumentDefinition: GraphQLDirectiveArgument = {
<n:FieldName> <q:DirectiveArgumentTypeDefinition?> => {
GraphQLDirectiveArgument::new(n, q)
},
};
DirectiveArgumentTypeDefinition: String = {
":" <q:QuotedString> => {
q
}
};
Comma<T>: Vec<T> = {
Comma1<T>? => <>.unwrap_or(vec![])
};
Comma1<T>: Vec<T> = {
<t:T> => vec![t],
<v:Comma<T>> "," <t:T> => {
let mut v = v;
v.push(t);
v
}
};
Pipe<T>: Vec<T> = {
Pipe1<T>? => <>.unwrap_or(vec![])
};
Pipe1<T>: Vec<T> = {
<t:T> => vec![t],
<v:Pipe<T>> "|" <t:T> => {
let mut v = v;
v.push(t);
v
}
};
Description: String = {
<d:CommentedString+> => {
d.join(" ")
}
};
// NOTE: These are all gross, can they be improved?
Name: String = r"[_A-Za-z][_0-9A-Za-z]*" => <>.to_owned();
EQUALS_SIGN: String = => "".to_string();
DefaultValue: String = <s:r"=\s*.+"> => s[1..s.len()].trim().to_owned();
CommentedString: String = <s:r"#\s*.+"> => s[1..s.len()].trim().to_owned();
QuotedString: String = <s:r#""[^"]*""#> => s[1..s.len()-1].to_owned();
FieldName: String = {
r"[_A-Za-z][_0-9A-Za-z]*" => <>.to_owned(),
"scalar" => "scalar".to_owned(),
"type" => "type".to_owned(),
"enum" => "enum".to_owned(),
"interface" => "interface".to_owned(),
"union" => "union".to_owned(),
"input" => "input".to_owned(),
};