{-# LANGUAGE OverloadedStrings #-} module Data.Morpheus.Parser.Primitive where import Control.Applicative import Data.Attoparsec.Text import Data.Functor import Data.Morpheus.Types.JSType (JSType (..), ScalarValue (..), decodeScientific) import qualified Data.Text as T (Text, pack) import qualified Data.Attoparsec.Internal.Types as AT replaceType :: T.Text -> T.Text replaceType "type" = "_type" replaceType x = x boolTrue :: Parser JSType boolTrue = string "true" $> Scalar (Boolean True) boolFalse :: Parser JSType boolFalse = string "false" $> Scalar (Boolean False) jsBool :: Parser JSType jsBool = boolTrue <|> boolFalse jsNumber :: Parser JSType jsNumber = Scalar . decodeScientific <$> scientific codes :: String codes = ['b', 'n', 'f', 'r', 't', '\\', '\"', '/'] replacements :: String replacements = ['\b', '\n', '\f', '\r', '\t', '\\', '\"', '/'] escaped :: Parser Char escaped = do x <- notChar '\"' if x == '\\' then choice (zipWith escapeChar codes replacements) else pure x where escapeChar code replacement = char code >> return replacement jsString :: Parser JSType jsString = do _ <- char '"' value <- many escaped _ <- char '"' pure $ Scalar $ String $ T.pack value token :: Parser T.Text token = replaceType . T.pack <$> some (letter <|> char '_') variable :: Parser T.Text variable = skipSpace *> char '$' *> token separator :: Parser Char separator = char ',' <|> char ' ' <|> char '\n' <|> char '\t' getPosition :: Parser Int getPosition = AT.Parser internFunc where internFunc t pos more _ success = success t pos more (AT.fromPos pos) getNextLine :: Parser Int getNextLine = do _ <- many (notChar '\n') index <- getPosition _ <- char '\n' pure index getLines :: Parser [Int] getLines = many getNextLine