{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module      :  Network.Polkadot.Metadata.Type.ParserCombinators
-- Copyright   :  Aleksandr Krupenkin 2016-2024
-- License     :  Apache-2.0
--
-- Maintainer  :  mail@akru.me
-- Stability   :  experimental
-- Portability :  portable
--
-- Parser combinators for the metadata type.
--

module Network.Polkadot.Metadata.Type.ParserCombinators where

import           Data.Functor.Identity              (Identity)
import           Data.Text                          (pack)
import           Text.Parsec
import           Text.Parsec.Text                   ()

import           Network.Polkadot.Metadata.Type.Ast (PathSegment, QSelf,
                                                     TypeAst (..))

type' :: Stream s Identity Char => Parsec s () TypeAst
type' :: forall s. Stream s Identity Char => Parsec s () TypeAst
type' = [ParsecT s () Identity TypeAst] -> ParsecT s () Identity TypeAst
forall s (m :: * -> *) t u a.
Stream s m t =>
[ParsecT s u m a] -> ParsecT s u m a
choice
  [ TypeAst -> TypeAst
Slice (TypeAst -> TypeAst)
-> ParsecT s () Identity TypeAst -> ParsecT s () Identity TypeAst
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity TypeAst -> ParsecT s () Identity TypeAst
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ParsecT s () Identity TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
slice
  , [TypeAst] -> TypeAst
Tuple ([TypeAst] -> TypeAst)
-> ParsecT s () Identity [TypeAst] -> ParsecT s () Identity TypeAst
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity [TypeAst]
forall s. Stream s Identity Char => Parsec s () [TypeAst]
tuple
  , TypeAst -> Int -> TypeAst
Array (TypeAst -> Int -> TypeAst)
-> ParsecT s () Identity TypeAst
-> ParsecT s () Identity (Int -> TypeAst)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
arrayT ParsecT s () Identity (Int -> TypeAst)
-> ParsecT s () Identity Int -> ParsecT s () Identity TypeAst
forall a b.
ParsecT s () Identity (a -> b)
-> ParsecT s () Identity a -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT s () Identity Int
forall s. Stream s Identity Char => Parsec s () Int
arrayN
  , Maybe QSelf -> [PathSegment] -> TypeAst
Path (Maybe QSelf -> [PathSegment] -> TypeAst)
-> ParsecT s () Identity (Maybe QSelf)
-> ParsecT s () Identity ([PathSegment] -> TypeAst)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity QSelf -> ParsecT s () Identity (Maybe QSelf)
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe ParsecT s () Identity QSelf
forall s. Stream s Identity Char => Parsec s () QSelf
pathQself ParsecT s () Identity ([PathSegment] -> TypeAst)
-> ParsecT s () Identity [PathSegment]
-> ParsecT s () Identity TypeAst
forall a b.
ParsecT s () Identity (a -> b)
-> ParsecT s () Identity a -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT s () Identity [PathSegment]
forall s. Stream s Identity Char => Parsec s () [PathSegment]
path
  ]

slice :: Stream s Identity Char => Parsec s () TypeAst
slice :: forall s. Stream s Identity Char => Parsec s () TypeAst
slice = (String -> ParsecT s () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"[" ParsecT s () Identity String
-> ParsecT s () Identity String -> ParsecT s () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> ParsecT s () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"&[") ParsecT s () Identity String
-> ParsecT s () Identity TypeAst -> ParsecT s () Identity TypeAst
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT s () Identity TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
type' ParsecT s () Identity TypeAst
-> ParsecT s () Identity Char -> ParsecT s () Identity TypeAst
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
']'

tuple :: Stream s Identity Char => Parsec s () [TypeAst]
tuple :: forall s. Stream s Identity Char => Parsec s () [TypeAst]
tuple = Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'(' ParsecT s () Identity Char
-> ParsecT s () Identity [TypeAst]
-> ParsecT s () Identity [TypeAst]
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parsec s () TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
type' Parsec s () TypeAst
-> ParsecT s () Identity String -> ParsecT s () Identity [TypeAst]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy1` ParsecT s () Identity String
forall s. Stream s Identity Char => Parsec s () String
comma ParsecT s () Identity [TypeAst]
-> ParsecT s () Identity Char -> ParsecT s () Identity [TypeAst]
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
')'

arrayT :: Stream s Identity Char => Parsec s () TypeAst
arrayT :: forall s. Stream s Identity Char => Parsec s () TypeAst
arrayT = Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'[' ParsecT s () Identity Char
-> ParsecT s () Identity TypeAst -> ParsecT s () Identity TypeAst
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT s () Identity TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
type' ParsecT s () Identity TypeAst
-> ParsecT s () Identity String -> ParsecT s () Identity TypeAst
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT s () Identity String
forall {u}. ParsecT s u Identity String
dotcomma
  where dotcomma :: ParsecT s u Identity String
dotcomma = ParsecT s u Identity String -> ParsecT s u Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT s u Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"; ") ParsecT s u Identity String
-> ParsecT s u Identity String -> ParsecT s u Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> ParsecT s u Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
";"

arrayN :: Stream s Identity Char => Parsec s () Int
arrayN :: forall s. Stream s Identity Char => Parsec s () Int
arrayN = String -> Int
forall a. Read a => String -> a
read (String -> Int)
-> ParsecT s () Identity String -> ParsecT s () Identity Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity Char
-> ParsecT s () Identity Char -> ParsecT s () Identity String
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
manyTill ParsecT s () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit (Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
']')

pathQself :: Stream s Identity Char => Parsec s () QSelf
pathQself :: forall s. Stream s Identity Char => Parsec s () QSelf
pathQself = (Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'<' ParsecT s () Identity Char
-> ParsecT s () Identity QSelf -> ParsecT s () Identity QSelf
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT s () Identity QSelf
qselfP ParsecT s () Identity QSelf
-> ParsecT s () Identity Char -> ParsecT s () Identity QSelf
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>') ParsecT s () Identity QSelf
-> ParsecT s () Identity String -> ParsecT s () Identity QSelf
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* String -> ParsecT s () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"::"
  where qselfP :: ParsecT s () Identity QSelf
qselfP = (,) (TypeAst -> TypeAst -> QSelf)
-> ParsecT s () Identity TypeAst
-> ParsecT s () Identity (TypeAst -> QSelf)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ParsecT s () Identity TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
type' ParsecT s () Identity TypeAst
-> ParsecT s () Identity String -> ParsecT s () Identity TypeAst
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* String -> ParsecT s () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
" as ") ParsecT s () Identity (TypeAst -> QSelf)
-> ParsecT s () Identity TypeAst -> ParsecT s () Identity QSelf
forall a b.
ParsecT s () Identity (a -> b)
-> ParsecT s () Identity a -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT s () Identity TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
type'

path :: Stream s Identity Char => Parsec s () [PathSegment]
path :: forall s. Stream s Identity Char => Parsec s () [PathSegment]
path = ParsecT s () Identity PathSegment
path' ParsecT s () Identity PathSegment
-> ParsecT s () Identity String
-> ParsecT s () Identity [PathSegment]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy` String -> ParsecT s () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"::"
  where
    path' :: ParsecT s () Identity PathSegment
path' = (,) (Text -> Maybe [TypeAst] -> PathSegment)
-> ParsecT s () Identity Text
-> ParsecT s () Identity (Maybe [TypeAst] -> PathSegment)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s () Identity Text
forall {u}. ParsecT s u Identity Text
ident
                ParsecT s () Identity (Maybe [TypeAst] -> PathSegment)
-> ParsecT s () Identity (Maybe [TypeAst])
-> ParsecT s () Identity PathSegment
forall a b.
ParsecT s () Identity (a -> b)
-> ParsecT s () Identity a -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT s () Identity [TypeAst]
-> ParsecT s () Identity (Maybe [TypeAst])
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe (Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'<' ParsecT s () Identity Char
-> ParsecT s () Identity [TypeAst]
-> ParsecT s () Identity [TypeAst]
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parsec s () TypeAst
forall s. Stream s Identity Char => Parsec s () TypeAst
type' Parsec s () TypeAst
-> ParsecT s () Identity String -> ParsecT s () Identity [TypeAst]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy1` ParsecT s () Identity String
forall s. Stream s Identity Char => Parsec s () String
comma ParsecT s () Identity [TypeAst]
-> ParsecT s () Identity Char -> ParsecT s () Identity [TypeAst]
forall a b.
ParsecT s () Identity a
-> ParsecT s () Identity b -> ParsecT s () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> ParsecT s () Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'>')
    ident :: ParsecT s u Identity Text
ident = do
        Char
c <- ParsecT s u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
letter
        String
cs <- ParsecT s u Identity Char -> ParsecT s u Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (ParsecT s u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
alphaNum ParsecT s u Identity Char
-> ParsecT s u Identity Char -> ParsecT s u Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT s u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'_')
        Text -> ParsecT s u Identity Text
forall a. a -> ParsecT s u Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> ParsecT s u Identity Text)
-> Text -> ParsecT s u Identity Text
forall a b. (a -> b) -> a -> b
$ String -> Text
pack (Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: String
cs)

comma :: Stream s Identity Char => Parsec s () String
comma :: forall s. Stream s Identity Char => Parsec s () String
comma = ParsecT s () Identity String -> ParsecT s () Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT s () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
", ") ParsecT s () Identity String
-> ParsecT s () Identity String -> ParsecT s () Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> String -> ParsecT s () Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
","