summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2020-01-07 13:56:58 +0100
committerEugen Wissner <belka@caraus.de>2020-01-13 08:21:02 +0100
commitf4ed06741dedb7b19cedc09b1c47afe1f0849f24 (patch)
treeb4ae8cf28d7ec7dc0c833bde6ccdf67ca82fcc3c /src
parent8efb08fda157770afb836537b27c2cd55042b706 (diff)
downloadgraphql-f4ed06741dedb7b19cedc09b1c47afe1f0849f24.tar.gz
Parse union definitions
Diffstat (limited to 'src')
-rw-r--r--src/Language/GraphQL/AST/Document.hs56
-rw-r--r--src/Language/GraphQL/AST/Parser.hs42
2 files changed, 65 insertions, 33 deletions
diff --git a/src/Language/GraphQL/AST/Document.hs b/src/Language/GraphQL/AST/Document.hs
index 619a6f3..74c6ce2 100644
--- a/src/Language/GraphQL/AST/Document.hs
+++ b/src/Language/GraphQL/AST/Document.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE OverloadedStrings #-}
+
-- | This module defines an abstract syntax tree for the @GraphQL@ language. It
-- follows closely the structure given in the specification. Please refer to
-- <https://facebook.github.io/graphql/ Facebook's GraphQL Specification>.
@@ -14,9 +16,9 @@ module Language.GraphQL.AST.Document
, FieldDefinition(..)
, FragmentDefinition(..)
, ImplementsInterfaces(..)
- , ImplementsInterfacesOpt(..)
, InputValueDefinition(..)
, Name
+ , NamedType
, NonNullType(..)
, ObjectField(..)
, OperationDefinition(..)
@@ -29,14 +31,18 @@ module Language.GraphQL.AST.Document
, Type(..)
, TypeCondition
, TypeDefinition(..)
+ , TypeExtension(..)
, TypeSystemDefinition(..)
+ , UnionMemberTypes(..)
, Value(..)
, VariableDefinition(..)
) where
+import Data.Foldable (toList)
import Data.Int (Int32)
import Data.List.NonEmpty (NonEmpty)
import Data.Text (Text)
+import qualified Data.Text as Text
import Language.GraphQL.AST.DirectiveLocation
-- * Language
@@ -274,9 +280,13 @@ newtype Description = Description (Maybe Text)
data TypeDefinition
= ScalarTypeDefinition Description Name [Directive]
| ObjectTypeDefinition
- Description Name ImplementsInterfacesOpt [Directive] [FieldDefinition]
+ Description
+ Name
+ (ImplementsInterfaces [])
+ [Directive]
+ [FieldDefinition]
| InterfaceTypeDefinition Description Name [Directive] [FieldDefinition]
- | UnionTypeDefinition Description Name [Directive] UnionMemberTypesOpt
+ | UnionTypeDefinition Description Name [Directive] (UnionMemberTypes [])
| EnumTypeDefinition Description Name [Directive] [EnumValueDefinition]
| InputObjectTypeDefinition
Description Name [Directive] InputFieldsDefinitionOpt
@@ -285,14 +295,16 @@ data TypeDefinition
data TypeExtension
= ScalarTypeExtension Name (NonEmpty Directive)
| ObjectTypeFieldsDefinitionExtension
- Name ImplementsInterfacesOpt [Directive] (NonEmpty FieldDefinition)
+ Name (ImplementsInterfaces []) [Directive] (NonEmpty FieldDefinition)
| ObjectTypeDirectivesExtension
- Name ImplementsInterfacesOpt (NonEmpty Directive)
- | ObjectTypeImplementsInterfacesExtension Name ImplementsInterfaces
+ Name (ImplementsInterfaces []) (NonEmpty Directive)
+ | ObjectTypeImplementsInterfacesExtension
+ Name (ImplementsInterfaces NonEmpty)
| InterfaceTypeFieldsDefinitionExtension
Name [Directive] (NonEmpty FieldDefinition)
| InterfaceTypeDirectivesExtension Name (NonEmpty Directive)
- | UnionTypeUnionMemberTypesExtension Name [Directive] UnionMemberTypes
+ | UnionTypeUnionMemberTypesExtension
+ Name [Directive] (UnionMemberTypes NonEmpty)
| UnionDirectivesExtension Name (NonEmpty Directive)
| EnumTypeEnumValuesDefinitionExtension
Name [Directive] (NonEmpty EnumValueDefinition)
@@ -304,17 +316,17 @@ data TypeExtension
-- ** Objects
-newtype ImplementsInterfaces = ImplementsInterfaces (NonEmpty NamedType)
- deriving (Eq, Show)
-newtype ImplementsInterfacesOpt = ImplementsInterfacesOpt [NamedType]
- deriving (Eq, Show)
+newtype ImplementsInterfaces t = ImplementsInterfaces (t NamedType)
-instance Semigroup ImplementsInterfacesOpt where
- (ImplementsInterfacesOpt xs) <> (ImplementsInterfacesOpt ys) =
- ImplementsInterfacesOpt $ xs <> ys
+instance Foldable t => Eq (ImplementsInterfaces t) where
+ (ImplementsInterfaces xs) == (ImplementsInterfaces ys)
+ = toList xs == toList ys
-instance Monoid ImplementsInterfacesOpt where
- mempty = ImplementsInterfacesOpt []
+instance Foldable t => Show (ImplementsInterfaces t) where
+ show (ImplementsInterfaces interfaces) = Text.unpack
+ $ Text.append "implements"
+ $ Text.intercalate " & "
+ $ toList interfaces
data FieldDefinition
= FieldDefinition Description Name ArgumentsDefinition Type [Directive]
@@ -336,11 +348,15 @@ data InputValueDefinition
-- ** Unions
-newtype UnionMemberTypes = UnionMemberTypes (NonEmpty NamedType)
- deriving (Eq, Show)
+newtype UnionMemberTypes t = UnionMemberTypes (t NamedType)
-newtype UnionMemberTypesOpt = UnionMemberTypesOpt [NamedType]
- deriving (Eq, Show)
+instance Foldable t => Eq (UnionMemberTypes t) where
+ (UnionMemberTypes xs) == (UnionMemberTypes ys) = toList xs == toList ys
+
+instance Foldable t => Show (UnionMemberTypes t) where
+ show (UnionMemberTypes memberTypes) = Text.unpack
+ $ Text.intercalate " | "
+ $ toList memberTypes
-- ** Enums
diff --git a/src/Language/GraphQL/AST/Parser.hs b/src/Language/GraphQL/AST/Parser.hs
index a851a66..274045d 100644
--- a/src/Language/GraphQL/AST/Parser.hs
+++ b/src/Language/GraphQL/AST/Parser.hs
@@ -8,7 +8,8 @@ module Language.GraphQL.AST.Parser
import Control.Applicative (Alternative(..), optional)
import qualified Control.Applicative.Combinators.NonEmpty as NonEmpty
-import Control.Applicative.Combinators (sepBy)
+import Control.Applicative.Combinators (sepBy, sepBy1)
+import Data.Text (Text)
import Language.GraphQL.AST.Document
import Language.GraphQL.AST.Lexer
import Text.Megaparsec (lookAhead, option, try, (<?>))
@@ -37,6 +38,7 @@ typeSystemDefinition = schemaDefinition
typeDefinition :: Parser TypeDefinition
typeDefinition = scalarTypeDefinition
<|> objectTypeDefinition
+ <|> unionTypeDefinition
<?> "TypeDefinition"
scalarTypeDefinition :: Parser TypeDefinition
@@ -52,7 +54,7 @@ objectTypeDefinition = ObjectTypeDefinition
<$> description
<* symbol "type"
<*> name
- <*> opt implementsInterfacesOpt
+ <*> option (ImplementsInterfaces []) (implementsInterfaces sepBy1)
<*> opt directives
<*> braces (many fieldDefinition)
<?> "ObjectTypeDefinition"
@@ -62,19 +64,33 @@ description = Description
<$> optional (string <|> blockString)
<?> "Description"
-{- TODO:
- implementsInterfaces :: Parser ImplementsInterfaces
-implementsInterfaces = ImplementsInterfaces
- <$ symbol "implements"
- <* optional amp
- <*> name `sepBy1` amp
- <?> "ImplementsInterfaces" -}
-
-implementsInterfacesOpt :: Parser ImplementsInterfacesOpt
-implementsInterfacesOpt = ImplementsInterfacesOpt
+unionTypeDefinition :: Parser TypeDefinition
+unionTypeDefinition = UnionTypeDefinition
+ <$> description
+ <* symbol "union"
+ <*> name
+ <*> opt directives
+ <*> option (UnionMemberTypes []) (unionMemberTypes sepBy1)
+ <?> "UnionTypeDefinition"
+
+unionMemberTypes ::
+ Foldable t =>
+ (Parser Text -> Parser Text -> Parser (t NamedType)) ->
+ Parser (UnionMemberTypes t)
+unionMemberTypes sepBy' = UnionMemberTypes
+ <$ equals
+ <* optional pipe
+ <*> name `sepBy'` pipe
+ <?> "UnionMemberTypes"
+
+implementsInterfaces ::
+ Foldable t =>
+ (Parser Text -> Parser Text -> Parser (t NamedType)) ->
+ Parser (ImplementsInterfaces t)
+implementsInterfaces sepBy' = ImplementsInterfaces
<$ symbol "implements"
<* optional amp
- <*> name `sepBy` amp
+ <*> name `sepBy'` amp
<?> "ImplementsInterfaces"
inputValueDefinition :: Parser InputValueDefinition