{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Language.Bitcoin.Miniscript.Parser (
    miniscriptParser,
    parseMiniscript,
) where

import Control.Applicative ((<|>))
import Control.Monad (void)
import Data.Attoparsec.Text (Parser)
import qualified Data.Attoparsec.Text as A
import Data.Text (Text, pack)
import Haskoin.Constants (Network)

import Language.Bitcoin.Miniscript.Syntax (
    Miniscript (..),
    Value (..),
 )
import Language.Bitcoin.Script.Descriptors (keyDescriptorParser)
import Language.Bitcoin.Utils (
    alphanum,
    application,
    argList,
    comma,
    hex,
    spacePadded,
 )

parseMiniscript :: Network -> Text -> Either String Miniscript
parseMiniscript :: Network -> Text -> Either String Miniscript
parseMiniscript net :: Network
net = Parser Miniscript -> Text -> Either String Miniscript
forall a. Parser a -> Text -> Either String a
A.parseOnly (Parser Miniscript -> Text -> Either String Miniscript)
-> Parser Miniscript -> Text -> Either String Miniscript
forall a b. (a -> b) -> a -> b
$ Network -> Parser Miniscript
miniscriptParser Network
net

miniscriptParser :: Network -> Parser Miniscript
miniscriptParser :: Network -> Parser Miniscript
miniscriptParser net :: Network
net = Parser Miniscript -> Parser Miniscript
annotP Parser Miniscript
expression Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
expression
  where
    expression :: Parser Miniscript
expression =
        Parser Miniscript
keyP Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
keyCP Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
keyHP Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
keyHCP Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
olderP Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
afterP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
sha256P
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
ripemd160P
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
hash256P
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
hash160P
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
andOrP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
andVP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
andBP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
orBP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
orCP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
orDP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
orIP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
threshP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
multiP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
numberP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
trueP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
falseP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
bytesP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
keyDescriptorP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
letP
            Parser Miniscript -> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Miniscript
varP

    trueP :: Parser Miniscript
trueP = Bool -> Miniscript
Boolean Bool
True Miniscript -> Parser Text Char -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> Parser Text Char
A.char '1'
    falseP :: Parser Miniscript
falseP = Bool -> Miniscript
Boolean Bool
False Miniscript -> Parser Text Char -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> Parser Text Char
A.char '0'

    numberP :: Parser Miniscript
numberP = Int -> Miniscript
Number (Int -> Miniscript) -> Parser Text Int -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Int
forall a. Integral a => Parser a
A.decimal
    bytesP :: Parser Miniscript
bytesP = ByteString -> Miniscript
Bytes (ByteString -> Miniscript)
-> Parser Text ByteString -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text ByteString
hex

    keyDescriptorP :: Parser Miniscript
keyDescriptorP = KeyDescriptor -> Miniscript
KeyDesc (KeyDescriptor -> Miniscript)
-> Parser Text KeyDescriptor -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Parser Text KeyDescriptor
keyDescriptorParser Network
net

    keyP :: Parser Miniscript
keyP = Value KeyDescriptor -> Miniscript
Key (Value KeyDescriptor -> Miniscript)
-> Parser Text (Value KeyDescriptor) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value KeyDescriptor)
-> Parser Text (Value KeyDescriptor)
forall a. Text -> Parser a -> Parser a
application "pk_k" Parser Text (Value KeyDescriptor)
atomicKeyDescP
    keyCP :: Parser Miniscript
keyCP = Miniscript -> Miniscript
AnnC (Miniscript -> Miniscript)
-> (Value KeyDescriptor -> Miniscript)
-> Value KeyDescriptor
-> Miniscript
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value KeyDescriptor -> Miniscript
Key (Value KeyDescriptor -> Miniscript)
-> Parser Text (Value KeyDescriptor) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value KeyDescriptor)
-> Parser Text (Value KeyDescriptor)
forall a. Text -> Parser a -> Parser a
application "pk" Parser Text (Value KeyDescriptor)
atomicKeyDescP

    keyHP :: Parser Miniscript
keyHP = Value KeyDescriptor -> Miniscript
KeyH (Value KeyDescriptor -> Miniscript)
-> Parser Text (Value KeyDescriptor) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value KeyDescriptor)
-> Parser Text (Value KeyDescriptor)
forall a. Text -> Parser a -> Parser a
application "pk_h" Parser Text (Value KeyDescriptor)
atomicKeyDescP
    keyHCP :: Parser Miniscript
keyHCP = Miniscript -> Miniscript
AnnC (Miniscript -> Miniscript)
-> (Value KeyDescriptor -> Miniscript)
-> Value KeyDescriptor
-> Miniscript
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value KeyDescriptor -> Miniscript
KeyH (Value KeyDescriptor -> Miniscript)
-> Parser Text (Value KeyDescriptor) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value KeyDescriptor)
-> Parser Text (Value KeyDescriptor)
forall a. Text -> Parser a -> Parser a
application "pkh" Parser Text (Value KeyDescriptor)
atomicKeyDescP

    olderP :: Parser Miniscript
olderP = Value Int -> Miniscript
Older (Value Int -> Miniscript)
-> Parser Text (Value Int) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser Text (Value Int) -> Parser Text (Value Int)
forall a. Text -> Parser a -> Parser a
application "older" Parser Text (Value Int)
atomicNumberP
    afterP :: Parser Miniscript
afterP = Value Int -> Miniscript
After (Value Int -> Miniscript)
-> Parser Text (Value Int) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Parser Text (Value Int) -> Parser Text (Value Int)
forall a. Text -> Parser a -> Parser a
application "after" Parser Text (Value Int)
atomicNumberP

    sha256P :: Parser Miniscript
sha256P = Value ByteString -> Miniscript
Sha256 (Value ByteString -> Miniscript)
-> Parser Text (Value ByteString) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value ByteString) -> Parser Text (Value ByteString)
forall a. Text -> Parser a -> Parser a
application "sha256" Parser Text (Value ByteString)
atomicBytesP
    ripemd160P :: Parser Miniscript
ripemd160P = Value ByteString -> Miniscript
Ripemd160 (Value ByteString -> Miniscript)
-> Parser Text (Value ByteString) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value ByteString) -> Parser Text (Value ByteString)
forall a. Text -> Parser a -> Parser a
application "ripemd160" Parser Text (Value ByteString)
atomicBytesP
    hash256P :: Parser Miniscript
hash256P = Value ByteString -> Miniscript
Hash256 (Value ByteString -> Miniscript)
-> Parser Text (Value ByteString) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value ByteString) -> Parser Text (Value ByteString)
forall a. Text -> Parser a -> Parser a
application "hash256" Parser Text (Value ByteString)
atomicBytesP
    hash160P :: Parser Miniscript
hash160P = Value ByteString -> Miniscript
Hash160 (Value ByteString -> Miniscript)
-> Parser Text (Value ByteString) -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> Parser Text (Value ByteString) -> Parser Text (Value ByteString)
forall a. Text -> Parser a -> Parser a
application "hash160" Parser Text (Value ByteString)
atomicBytesP

    andOrP :: Parser Miniscript
andOrP =
        Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "andor" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$
            Miniscript -> Miniscript -> Miniscript -> Miniscript
AndOr (Miniscript -> Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript
-> Parser Text (Miniscript -> Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
mp
                Parser Text (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp
                Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp

    andVP :: Parser Miniscript
andVP = Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "and_v" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$ Miniscript -> Miniscript -> Miniscript
AndV (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
mp Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp
    andBP :: Parser Miniscript
andBP = Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "and_b" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$ Miniscript -> Miniscript -> Miniscript
AndB (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
mp Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp
    orBP :: Parser Miniscript
orBP = Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "or_b" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$ Miniscript -> Miniscript -> Miniscript
OrB (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
mp Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp
    orCP :: Parser Miniscript
orCP = Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "or_c" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$ Miniscript -> Miniscript -> Miniscript
OrC (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
mp Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp
    orDP :: Parser Miniscript
orDP = Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "or_d" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$ Miniscript -> Miniscript -> Miniscript
OrD (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
mp Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp
    orIP :: Parser Miniscript
orIP = Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "or_i" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$ Miniscript -> Miniscript -> Miniscript
OrI (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
mp Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp

    varP :: Parser Miniscript
varP = Text -> Miniscript
Var (Text -> Miniscript) -> Parser Text Text -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text
varIdentP
    varIdentP :: Parser Text Text
varIdentP = String -> Text
pack (String -> Text) -> Parser Text String -> Parser Text Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Char -> Parser Text String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
A.many' (Parser Text Char
alphanum Parser Text Char -> Parser Text Char -> Parser Text Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser Text Char
A.char '_')

    letP :: Parser Miniscript
letP = do
        Parser Text Text -> Parser Text ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser Text Text -> Parser Text ())
-> Parser Text Text -> Parser Text ()
forall a b. (a -> b) -> a -> b
$ Text -> Parser Text Text
A.string "let"
        Text -> Miniscript -> Miniscript -> Miniscript
Let (Text -> Miniscript -> Miniscript -> Miniscript)
-> Parser Text Text
-> Parser Text (Miniscript -> Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text -> Parser Text Text
forall a. Parser a -> Parser a
spacePadded Parser Text Text
varIdentP
            Parser Text (Miniscript -> Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Char -> Parser Text Char
A.char '=' Parser Text Char -> Parser Miniscript -> Parser Miniscript
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
spacePadded Parser Miniscript
mp)
            Parser Text (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Text -> Parser Text Text
A.string "in" Parser Text Text -> Parser Miniscript -> Parser Miniscript
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
spacePadded Parser Miniscript
mp)

    threshP :: Parser Miniscript
threshP =
        Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "thresh" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$
            Value Int -> Miniscript -> [Miniscript] -> Miniscript
Thresh (Value Int -> Miniscript -> [Miniscript] -> Miniscript)
-> Parser Text (Value Int)
-> Parser Text (Miniscript -> [Miniscript] -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text (Value Int)
atomicNumberP Parser Text (Miniscript -> [Miniscript] -> Miniscript)
-> Parser Miniscript -> Parser Text ([Miniscript] -> Miniscript)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Miniscript -> Parser Miniscript
forall a. Parser a -> Parser a
comma Parser Miniscript
mp Parser Text ([Miniscript] -> Miniscript)
-> Parser Text [Miniscript] -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text [Miniscript] -> Parser Text [Miniscript]
forall a. Parser a -> Parser a
comma (Parser Miniscript -> Parser Text [Miniscript]
forall a. Parser a -> Parser [a]
argList Parser Miniscript
mp)

    multiP :: Parser Miniscript
multiP =
        Text -> Parser Miniscript -> Parser Miniscript
forall a. Text -> Parser a -> Parser a
application "multi" (Parser Miniscript -> Parser Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall a b. (a -> b) -> a -> b
$
            Value Int -> [Value KeyDescriptor] -> Miniscript
Multi (Value Int -> [Value KeyDescriptor] -> Miniscript)
-> Parser Text (Value Int)
-> Parser Text ([Value KeyDescriptor] -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text (Value Int)
atomicNumberP Parser Text ([Value KeyDescriptor] -> Miniscript)
-> Parser Text [Value KeyDescriptor] -> Parser Miniscript
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text [Value KeyDescriptor]
-> Parser Text [Value KeyDescriptor]
forall a. Parser a -> Parser a
comma (Parser Text (Value KeyDescriptor)
-> Parser Text [Value KeyDescriptor]
forall a. Parser a -> Parser [a]
argList Parser Text (Value KeyDescriptor)
atomicKeyDescP)

    atomicNumberP :: Parser Text (Value Int)
atomicNumberP = (Int -> Value Int
forall a. a -> Value a
Lit (Int -> Value Int) -> Parser Text Int -> Parser Text (Value Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Int
forall a. Integral a => Parser a
A.decimal) Parser Text (Value Int)
-> Parser Text (Value Int) -> Parser Text (Value Int)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Text -> Value Int
forall a. Text -> Value a
Variable (Text -> Value Int) -> Parser Text Text -> Parser Text (Value Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text
varIdentP)
    atomicBytesP :: Parser Text (Value ByteString)
atomicBytesP = (ByteString -> Value ByteString
forall a. a -> Value a
Lit (ByteString -> Value ByteString)
-> Parser Text ByteString -> Parser Text (Value ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text ByteString
hex) Parser Text (Value ByteString)
-> Parser Text (Value ByteString) -> Parser Text (Value ByteString)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Text -> Value ByteString
forall a. Text -> Value a
Variable (Text -> Value ByteString)
-> Parser Text Text -> Parser Text (Value ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text
varIdentP)
    atomicKeyDescP :: Parser Text (Value KeyDescriptor)
atomicKeyDescP = (KeyDescriptor -> Value KeyDescriptor
forall a. a -> Value a
Lit (KeyDescriptor -> Value KeyDescriptor)
-> Parser Text KeyDescriptor -> Parser Text (Value KeyDescriptor)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Network -> Parser Text KeyDescriptor
keyDescriptorParser Network
net) Parser Text (Value KeyDescriptor)
-> Parser Text (Value KeyDescriptor)
-> Parser Text (Value KeyDescriptor)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Text -> Value KeyDescriptor
forall a. Text -> Value a
Variable (Text -> Value KeyDescriptor)
-> Parser Text Text -> Parser Text (Value KeyDescriptor)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text Text
varIdentP)

    annotP :: Parser Miniscript -> Parser Miniscript
annotP p :: Parser Miniscript
p = do
        Miniscript -> Miniscript
anns <- String -> Miniscript -> Miniscript
calcAnnotation (String -> Miniscript -> Miniscript)
-> Parser Text String -> Parser Text (Miniscript -> Miniscript)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text String
annPrefixP
        Miniscript -> Miniscript
anns (Miniscript -> Miniscript)
-> Parser Miniscript -> Parser Miniscript
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Miniscript
p

    annPrefixP :: Parser Text String
annPrefixP = Parser Text Char -> Parser Text String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
A.many' (Parser Text Char -> Parser Text Char
forall a. Parser a -> Parser a
spacePadded (Parser Text Char -> Parser Text Char)
-> Parser Text Char -> Parser Text Char
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> Parser Text Char
A.satisfy Char -> Bool
isAnn) Parser Text String -> Parser Text Char -> Parser Text String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text Char -> Parser Text Char
forall a. Parser a -> Parser a
spacePadded (Char -> Parser Text Char
A.char ':')

    calcAnnotation :: String -> Miniscript -> Miniscript
calcAnnotation = (Miniscript -> String -> Miniscript)
-> String -> Miniscript -> Miniscript
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Miniscript -> String -> Miniscript)
 -> String -> Miniscript -> Miniscript)
-> (Miniscript -> String -> Miniscript)
-> String
-> Miniscript
-> Miniscript
forall a b. (a -> b) -> a -> b
$ (Char -> Miniscript -> Miniscript)
-> Miniscript -> String -> Miniscript
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Char -> Miniscript -> Miniscript
toAnn

    toAnn :: Char -> Miniscript -> Miniscript
toAnn = \case
        'a' -> Miniscript -> Miniscript
AnnA
        's' -> Miniscript -> Miniscript
AnnS
        'c' -> Miniscript -> Miniscript
AnnC
        'd' -> Miniscript -> Miniscript
AnnD
        'v' -> Miniscript -> Miniscript
AnnV
        'j' -> Miniscript -> Miniscript
AnnJ
        'n' -> Miniscript -> Miniscript
AnnN
        't' -> (Miniscript -> Miniscript -> Miniscript
`AndV` Bool -> Miniscript
Boolean Bool
True)
        'l' -> Miniscript -> Miniscript -> Miniscript
OrI (Bool -> Miniscript
Boolean Bool
False)
        'u' -> (Miniscript -> Miniscript -> Miniscript
`OrI` Bool -> Miniscript
Boolean Bool
False)
        _ -> String -> Miniscript -> Miniscript
forall a. HasCallStack => String -> a
error "unexpected annotation"

    isAnn :: Char -> Bool
isAnn = String -> Char -> Bool
A.inClass "asctdvjnlu"

    mp :: Parser Miniscript
mp = Network -> Parser Miniscript
miniscriptParser Network
net