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

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

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
start Parser b
end Parser c
sep Parser d
elemParser = Parser a
start Parser a -> Parser [d] -> Parser [d]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser [d]
elemsParser Parser [d] -> Parser b -> Parser [d]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser b
end   where

  elemsParser :: Parser [d]
elemsParser = Parser c -> Parser d -> Parser [d]
forall a b. Parser a -> Parser b -> Parser [b]
anySeparatedBy Parser c
sep (Parser d -> Parser [d]) -> Parser d -> Parser [d]
forall a b. (a -> b) -> a -> b
$ Parser String -> Parser d -> Parser d
forall a b. Parser a -> Parser b -> Parser b
maybeWithin Parser String
spacing Parser d
elemParser

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
openSquare Parser Char
closeSquare Parser Char
comma

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
openParens Parser Char
closeParens Parser Char
comma

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
openCurly Parser Char
closeCurly Parser Char
comma Parser (b, c)
mapEntry  where

  mapEntry :: Parser (b, c)
mapEntry = (,) (b -> c -> (b, c)) -> Parser b -> Parser (c -> (b, c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser b
p1 Parser (c -> (b, c)) -> Parser a -> Parser (c -> (b, c))
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser String -> Parser a -> Parser a
forall a b. Parser a -> Parser b -> Parser b
maybeWithin Parser String
spacing Parser a
sep Parser (c -> (b, c)) -> Parser c -> Parser (b, c)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser c
p2