module Parsers.Collections (collOf, listOf, tupleOf, mapOf, csvOf) where

import Parser (Parser)
import ParserCombinators ((|*), (|?), maybeWithin)
import Parsers.Char (comma, openSquare, closeSquare, openParens,
                     closeParens, openCurly, closeCurly)
import Parsers.String(spacing)

import qualified Data.Foldable as Foldable
import qualified Data.Map as Map
import Data.Map(Map)


collOf :: Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
collOf :: Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
collOf Parser a
sep Parser b
start Parser c
end Parser d
elemParser = do Parser b
start
                                     [d]
elems <- ((Parser String -> Parser d -> Parser d
forall a b. Parser a -> Parser b -> Parser b
maybeWithin Parser String
spacing (Parser d -> Parser d) -> Parser d -> Parser d
forall a b. (a -> b) -> a -> b
$ Parser d
elemParser Parser d -> Parser a -> Parser d
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser a
sep) Parser d -> Parser [d]
forall a. Parser a -> Parser [a]
|*)
                                     Maybe d
element  <- Parser String -> Parser (Maybe d) -> Parser (Maybe d)
forall a b. Parser a -> Parser b -> Parser b
maybeWithin Parser String
spacing (Parser d
elemParser Parser d -> Parser (Maybe d)
forall a. Parser a -> Parser (Maybe a)
|?)
                                     Parser c
end
                                     pure ([d]
elems [d] -> [d] -> [d]
forall a. [a] -> [a] -> [a]
++ Maybe d -> [d]
forall (t :: * -> *) a. Foldable t => t a -> [a]
Foldable.toList Maybe d
element)


listOf :: Parser a -> Parser [a]
listOf :: Parser a -> Parser [a]
listOf = Parser Char -> Parser Char -> Parser Char -> Parser a -> Parser [a]
forall a b c d.
Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
collOf Parser Char
comma Parser Char
openSquare Parser Char
closeSquare

tupleOf :: Parser a -> Parser [a]
tupleOf :: Parser a -> Parser [a]
tupleOf = Parser Char -> Parser Char -> Parser Char -> Parser a -> Parser [a]
forall a b c d.
Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
collOf Parser Char
comma Parser Char
openParens Parser Char
closeParens

mapOf :: Ord b => Parser a -> Parser b -> Parser c -> Parser (Map b c)
mapOf :: Parser a -> Parser b -> Parser c -> Parser (Map b c)
mapOf Parser a
sep Parser b
p1 Parser c
p2 = [(b, c)] -> Map b c
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(b, c)] -> Map b c) -> Parser [(b, c)] -> Parser (Map b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char
-> Parser Char -> Parser Char -> Parser (b, c) -> Parser [(b, c)]
forall a b c d.
Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
collOf Parser Char
comma Parser Char
openCurly Parser Char
closeCurly Parser (b, c)
mapEntry  where

  mapEntry :: Parser (b, c)
mapEntry = do b
key <- Parser b
p1
                Parser String -> Parser a -> Parser a
forall a b. Parser a -> Parser b -> Parser b
maybeWithin Parser String
spacing Parser a
sep
                c
value <- Parser c
p2
                pure (b
key, c
value)

csvOf :: Parser a -> Parser [a]
csvOf :: Parser a -> Parser [a]
csvOf = Parser Char -> Parser () -> Parser () -> Parser a -> Parser [a]
forall a b c d.
Parser a -> Parser b -> Parser c -> Parser d -> Parser [d]
collOf Parser Char
comma (() -> Parser ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) (() -> Parser ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())