{-# LANGUAGE PostfixOperators #-}

module Parsers.Collections where

import Parser (Parser)
import ParserCombinators (IsMatch(..), (<|>), (|*), (|?), maybeWithin)
import Parsers.Char (colon, 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
elem  <- 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
                                     [d] -> Parser [d]
forall (f :: * -> *) a. Applicative f => a -> f a
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
elem)


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 -> Parser c -> Parser (b, c)
forall a b. Parser a -> Parser b -> Parser (a, b)
mapEntryOf Parser b
p1 Parser c
p2)  where

  mapEntryOf :: Parser a -> Parser b -> Parser (a, b)
mapEntryOf Parser a
p1 Parser b
p2 = do a
key <- Parser a
p1
                        Parser String -> Parser a -> Parser a
forall a b. Parser a -> Parser b -> Parser b
maybeWithin Parser String
spacing Parser a
sep
                        b
value <- Parser b
p2
                        (a, b) -> Parser (a, b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
key, b
value)