{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE NoImplicitPrelude #-} module Data.Morpheus.Parsing.Internal.Value ( enumValue, parseDefaultValue, Parse (..), ) where import Data.Morpheus.Parsing.Internal.Internal ( Parser, ) import Data.Morpheus.Parsing.Internal.Terms ( brackets, colon, equal, ignoredTokens, parseName, parseString, parseTypeName, setOf, symbol, variable, ) import Data.Morpheus.Types.Internal.AST ( CONST, FieldName, ObjectEntry (..), OrdMap, RAW, ScalarValue (..), Value (..), decodeScientific, ) import Relude import Text.Megaparsec ( label, sepBy, ) import Text.Megaparsec.Byte ( string, ) import Text.Megaparsec.Byte.Lexer (scientific) -- '-' #define MINUS 45 valueNull :: Parser (Value a) valueNull = string "null" $> Null {-# INLINE valueNull #-} booleanValue :: Parser (Value a) booleanValue = Scalar . Boolean <$> ( string "true" $> True <|> string "false" $> False ) {-# INLINE booleanValue #-} valueNumber :: Parser (Value a) valueNumber = Scalar . decodeScientific <$> ((*) <$> negation <*> scientific) where negation = (symbol MINUS $> (-1) <* ignoredTokens) <|> pure 1 {-# INLINE negation #-} {-# INLINE valueNumber #-} enumValue :: Parser (Value a) enumValue = Enum <$> parseTypeName <* ignoredTokens {-# INLINE enumValue #-} stringValue :: Parser (Value a) stringValue = Scalar . String <$> parseString {-# INLINE stringValue #-} listValue :: Parser a -> Parser [a] listValue parser = label "List" $ brackets (parser `sepBy` ignoredTokens) {-# INLINE listValue #-} objectEntry :: Parser (Value a) -> Parser (ObjectEntry a) objectEntry parser = ObjectEntry <$> (parseName <* colon) <*> parser {-# INLINE objectEntry #-} objectValue :: Parser (Value a) -> Parser (OrdMap FieldName (ObjectEntry a)) objectValue = label "ObjectValue" . setOf . objectEntry {-# INLINE objectValue #-} parsePrimitives :: Parser (Value a) parsePrimitives = valueNull <|> booleanValue <|> valueNumber <|> enumValue <|> stringValue {-# INLINE parsePrimitives #-} parseDefaultValue :: Parser (Value s) parseDefaultValue = equal *> parseV where parseV :: Parser (Value s) parseV = compoundValue parseV class Parse a where parse :: Parser a instance Parse (Value RAW) where parse = (VariableValue <$> variable) <|> compoundValue parse instance Parse (Value CONST) where parse = compoundValue parse compoundValue :: Parser (Value a) -> Parser (Value a) compoundValue parser = label "Value" $ ( parsePrimitives <|> (Object <$> objectValue parser) <|> (List <$> listValue parser) ) <* ignoredTokens