{-# LANGUAGE
    FlexibleContexts
  , FlexibleInstances
  , LambdaCase
  , MultiParamTypeClasses
  , PatternGuards
  , RecordWildCards
  #-}
-- | Memoized packrat parsing, inspired by Edward Kmett\'s
-- \"A Parsec Full of Rats\".
module Language.Bash.Parse.Internal
    ( -- * Packrat parsing
      D
    , pack
      -- * Tokens
    , satisfying
      -- * Whitespace
    , I.skipSpace
      -- * Words
    , anyWord
    , word
    , reservedWord
    , assignBuiltin
    , ioDesc
    , name
    , functionName
      -- * Operators
    , anyOperator
    , operator
      -- * Assignments
    , assign
      -- * Arithmetic expressions
    , arith
      -- * Here documents
    , heredocWord
    ) where

import Prelude hiding (Word)

import           Control.Applicative
import           Control.Monad
import           Data.Function
import           Data.Functor.Identity
import           Text.Parsec.Char
import           Text.Parsec.Combinator   hiding (optional)
import           Text.Parsec.Error
import           Text.Parsec.Prim         hiding ((<|>), token)
import           Text.Parsec.Pos

import qualified Language.Bash.Parse.Word as I
import           Language.Bash.Pretty
import           Language.Bash.Syntax
import           Language.Bash.Word

-- | A memoized result.
type Result d a = Consumed (Reply d () a)

-- | Build a parser from a field accessor.
rat :: Monad m => (d -> Result d a) -> ParsecT d u m a
rat :: forall (m :: * -> *) d a u.
Monad m =>
(d -> Result d a) -> ParsecT d u m a
rat d -> Result d a
f = (State d u -> m (Consumed (m (Reply d u a)))) -> ParsecT d u m a
forall (m :: * -> *) s u a.
Monad m =>
(State s u -> m (Consumed (m (Reply s u a)))) -> ParsecT s u m a
mkPT ((State d u -> m (Consumed (m (Reply d u a)))) -> ParsecT d u m a)
-> (State d u -> m (Consumed (m (Reply d u a)))) -> ParsecT d u m a
forall a b. (a -> b) -> a -> b
$ \State d u
s0 -> Consumed (m (Reply d u a)) -> m (Consumed (m (Reply d u a)))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Consumed (m (Reply d u a)) -> m (Consumed (m (Reply d u a))))
-> Consumed (m (Reply d u a)) -> m (Consumed (m (Reply d u a)))
forall a b. (a -> b) -> a -> b
$
    Reply d u a -> m (Reply d u a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Reply d u a -> m (Reply d u a))
-> (Reply d () a -> Reply d u a) -> Reply d () a -> m (Reply d u a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State d u -> Reply d () a -> Reply d u a
forall {s} {u} {s} {u} {a}. State s u -> Reply s u a -> Reply s u a
patch State d u
s0 (Reply d () a -> m (Reply d u a))
-> Result d a -> Consumed (m (Reply d u a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> d -> Result d a
f (State d u -> d
forall s u. State s u -> s
stateInput State d u
s0)
  where
    patch :: State s u -> Reply s u a -> Reply s u a
patch (State s
_ SourcePos
_ u
u) (Ok a
a (State s
s SourcePos
p u
_) ParseError
err) = a -> State s u -> ParseError -> Reply s u a
forall s u a. a -> State s u -> ParseError -> Reply s u a
Ok a
a (s -> SourcePos -> u -> State s u
forall s u. s -> SourcePos -> u -> State s u
State s
s SourcePos
p u
u) ParseError
err
    patch State s u
_             (Error ParseError
e)                = ParseError -> Reply s u a
forall s u a. ParseError -> Reply s u a
Error ParseError
e

-- | Obtain a result from a stateless parser.
womp :: d -> SourcePos -> ParsecT d () Identity a -> Result d a
womp :: forall d a. d -> SourcePos -> ParsecT d () Identity a -> Result d a
womp d
d SourcePos
pos ParsecT d () Identity a
p = (Identity (Reply d () a) -> Reply d () a)
-> Consumed (Identity (Reply d () a)) -> Consumed (Reply d () a)
forall a b. (a -> b) -> Consumed a -> Consumed b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Identity (Reply d () a) -> Reply d () a
forall a. Identity a -> a
runIdentity (Consumed (Identity (Reply d () a)) -> Consumed (Reply d () a))
-> (Identity (Consumed (Identity (Reply d () a)))
    -> Consumed (Identity (Reply d () a)))
-> Identity (Consumed (Identity (Reply d () a)))
-> Consumed (Reply d () a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity (Consumed (Identity (Reply d () a)))
-> Consumed (Identity (Reply d () a))
forall a. Identity a -> a
runIdentity (Identity (Consumed (Identity (Reply d () a)))
 -> Consumed (Reply d () a))
-> Identity (Consumed (Identity (Reply d () a)))
-> Consumed (Reply d () a)
forall a b. (a -> b) -> a -> b
$
    ParsecT d () Identity a
-> State d () -> Identity (Consumed (Identity (Reply d () a)))
forall (m :: * -> *) s u a.
Monad m =>
ParsecT s u m a -> State s u -> m (Consumed (m (Reply s u a)))
runParsecT ParsecT d () Identity a
p (d -> SourcePos -> () -> State d ()
forall s u. s -> SourcePos -> u -> State s u
State d
d SourcePos
pos ())

-- | Run a parser, merging it with another.
reparse :: Stream s m t0 => ParsecT s u m a -> s -> ParsecT t u m a
reparse :: forall s (m :: * -> *) t0 u a t.
Stream s m t0 =>
ParsecT s u m a -> s -> ParsecT t u m a
reparse ParsecT s u m a
p s
input = (State t u -> m (Consumed (m (Reply t u a)))) -> ParsecT t u m a
forall (m :: * -> *) s u a.
Monad m =>
(State s u -> m (Consumed (m (Reply s u a)))) -> ParsecT s u m a
mkPT ((State t u -> m (Consumed (m (Reply t u a)))) -> ParsecT t u m a)
-> (State t u -> m (Consumed (m (Reply t u a)))) -> ParsecT t u m a
forall a b. (a -> b) -> a -> b
$ \s0 :: State t u
s0@(State t
_ SourcePos
_ u
u) ->
    ((Reply t u a -> m (Reply t u a))
-> Consumed (Reply t u a) -> Consumed (m (Reply t u a))
forall a b. (a -> b) -> Consumed a -> Consumed b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Reply t u a -> m (Reply t u a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Consumed (Reply t u a) -> Consumed (m (Reply t u a)))
-> (Either ParseError a -> Consumed (Reply t u a))
-> Either ParseError a
-> Consumed (m (Reply t u a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State t u -> Either ParseError a -> Consumed (Reply t u a)
forall {s} {u} {a}.
State s u -> Either ParseError a -> Consumed (Reply s u a)
patch State t u
s0) (Either ParseError a -> Consumed (m (Reply t u a)))
-> m (Either ParseError a) -> m (Consumed (m (Reply t u a)))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` ParsecT s u m a -> u -> SourceName -> s -> m (Either ParseError a)
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> u -> SourceName -> s -> m (Either ParseError a)
runParserT ParsecT s u m a
p u
u SourceName
"" s
input
  where
    patch :: State s u -> Either ParseError a -> Consumed (Reply s u a)
patch (State s
_ SourcePos
pos u
_) (Left ParseError
e)  = Reply s u a -> Consumed (Reply s u a)
forall a. a -> Consumed a
Empty (ParseError -> Reply s u a
forall s u a. ParseError -> Reply s u a
Error (SourcePos -> ParseError -> ParseError
setErrorPos SourcePos
pos ParseError
e))
    patch State s u
s               (Right a
r) = Reply s u a -> Consumed (Reply s u a)
forall a. a -> Consumed a
Empty (a -> State s u -> ParseError -> Reply s u a
forall s u a. a -> State s u -> ParseError -> Reply s u a
Ok a
r State s u
s (State s u -> ParseError
forall s u. State s u -> ParseError
unknownError State s u
s))

-- | A token.
data Token
    = TWord Word
    | TIODesc IODesc

-- | A stream with memoized results.
data D = D
    { D -> Result D Token
_token       :: Result D Token
    , D -> Result D Word
_anyWord     :: Result D Word
    , D -> Result D IODesc
_ioDesc      :: Result D IODesc
    , D -> Result D SourceName
_anyOperator :: Result D String
    , D -> Result D Assign
_assign      :: Result D Assign
    , D -> Maybe (Char, D)
_uncons      :: Maybe (Char, D)
    }

instance Monad m => Stream D m Char where
    uncons :: D -> m (Maybe (Char, D))
uncons = Maybe (Char, D) -> m (Maybe (Char, D))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Char, D) -> m (Maybe (Char, D)))
-> (D -> Maybe (Char, D)) -> D -> m (Maybe (Char, D))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. D -> Maybe (Char, D)
_uncons

-- | Create a source from a string.
pack :: SourcePos -> String -> D
pack :: SourcePos -> SourceName -> D
pack SourcePos
p SourceName
s = (D -> D) -> D
forall a. (a -> a) -> a
fix ((D -> D) -> D) -> (D -> D) -> D
forall a b. (a -> b) -> a -> b
$ \D
d ->
    let result :: ParsecT D () Identity a -> Result D a
result       = D -> SourcePos -> ParsecT D () Identity a -> Result D a
forall d a. d -> SourcePos -> ParsecT d () Identity a -> Result d a
womp D
d SourcePos
p
        _token :: Result D Token
_token       = ParsecT D () Identity Token -> Result D Token
forall {a}. ParsecT D () Identity a -> Result D a
result (ParsecT D () Identity Token -> Result D Token)
-> ParsecT D () Identity Token -> Result D Token
forall a b. (a -> b) -> a -> b
$ do
            Word
t <- ParsecT D () Identity Word
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Word
I.word
            Bool -> ParsecT D () Identity ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ParsecT D () Identity ())
-> Bool -> ParsecT D () Identity ()
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Word -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Word
t)
            Maybe Char
next <- ParsecT D () Identity Char -> ParsecT D () Identity (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (ParsecT D () Identity Char -> ParsecT D () Identity Char
forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m a
lookAhead ParsecT D () Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar)
            ParsecT D () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
I.skipSpace
            Token -> ParsecT D () Identity Token
forall a. a -> ParsecT D () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Token -> ParsecT D () Identity Token)
-> Token -> ParsecT D () Identity Token
forall a b. (a -> b) -> a -> b
$ case Maybe Char
next of
                Just Char
c | Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'<' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'>'
                       , Right IODesc
desc <- Parsec SourceName () IODesc
-> SourceName -> SourceName -> Either ParseError IODesc
forall s t a.
Stream s Identity t =>
Parsec s () a -> SourceName -> s -> Either ParseError a
parse (Parsec SourceName () IODesc
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m IODesc
descriptor Parsec SourceName () IODesc
-> ParsecT SourceName () Identity () -> Parsec SourceName () IODesc
forall a b.
ParsecT SourceName () Identity a
-> ParsecT SourceName () Identity b
-> ParsecT SourceName () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT SourceName () Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof) SourceName
"" (Word -> SourceName
forall a. Pretty a => a -> SourceName
prettyText Word
t)
                  -> IODesc -> Token
TIODesc IODesc
desc
                Maybe Char
_ -> Word -> Token
TWord Word
t
        _anyWord :: Result D Word
_anyWord     = ParsecT D () Identity Word -> Result D Word
forall {a}. ParsecT D () Identity a -> Result D a
result (ParsecT D () Identity Word -> Result D Word)
-> ParsecT D () Identity Word -> Result D Word
forall a b. (a -> b) -> a -> b
$ ParsecT D () Identity Token
forall (m :: * -> *) u. Monad m => ParsecT D u m Token
token ParsecT D () Identity Token
-> (Token -> ParsecT D () Identity Word)
-> ParsecT D () Identity Word
forall a b.
ParsecT D () Identity a
-> (a -> ParsecT D () Identity b) -> ParsecT D () Identity b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
            TWord Word
w -> Word -> ParsecT D () Identity Word
forall a. a -> ParsecT D () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Word
w
            Token
_       -> ParsecT D () Identity Word
forall a. ParsecT D () Identity a
forall (f :: * -> *) a. Alternative f => f a
empty
        _ioDesc :: Result D IODesc
_ioDesc      = ParsecT D () Identity IODesc -> Result D IODesc
forall {a}. ParsecT D () Identity a -> Result D a
result (ParsecT D () Identity IODesc -> Result D IODesc)
-> ParsecT D () Identity IODesc -> Result D IODesc
forall a b. (a -> b) -> a -> b
$ ParsecT D () Identity Token
forall (m :: * -> *) u. Monad m => ParsecT D u m Token
token ParsecT D () Identity Token
-> (Token -> ParsecT D () Identity IODesc)
-> ParsecT D () Identity IODesc
forall a b.
ParsecT D () Identity a
-> (a -> ParsecT D () Identity b) -> ParsecT D () Identity b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
            TIODesc IODesc
desc -> IODesc -> ParsecT D () Identity IODesc
forall a. a -> ParsecT D () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return IODesc
desc
            Token
_            -> ParsecT D () Identity IODesc
forall a. ParsecT D () Identity a
forall (f :: * -> *) a. Alternative f => f a
empty
        _anyOperator :: Result D SourceName
_anyOperator = ParsecT D () Identity SourceName -> Result D SourceName
forall {a}. ParsecT D () Identity a -> Result D a
result (ParsecT D () Identity SourceName -> Result D SourceName)
-> ParsecT D () Identity SourceName -> Result D SourceName
forall a b. (a -> b) -> a -> b
$ [SourceName] -> ParsecT D () Identity SourceName
forall s (m :: * -> *) u.
Stream s m Char =>
[SourceName] -> ParsecT s u m SourceName
I.operator [SourceName]
operators ParsecT D () Identity SourceName
-> ParsecT D () Identity () -> ParsecT D () Identity SourceName
forall a b.
ParsecT D () Identity a
-> ParsecT D () Identity b -> ParsecT D () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT D () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
I.skipSpace
        _assign :: Result D Assign
_assign      = ParsecT D () Identity Assign -> Result D Assign
forall {a}. ParsecT D () Identity a -> Result D a
result (ParsecT D () Identity Assign -> Result D Assign)
-> ParsecT D () Identity Assign -> Result D Assign
forall a b. (a -> b) -> a -> b
$ ParsecT D () Identity Assign
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Assign
I.assign ParsecT D () Identity Assign
-> ParsecT D () Identity () -> ParsecT D () Identity Assign
forall a b.
ParsecT D () Identity a
-> ParsecT D () Identity b -> ParsecT D () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT D () Identity ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
I.skipSpace
        _uncons :: Maybe (Char, D)
_uncons      = case SourceName
s of
            []     -> Maybe (Char, D)
forall a. Maybe a
Nothing
            (Char
x:SourceName
xs) -> (Char, D) -> Maybe (Char, D)
forall a. a -> Maybe a
Just (Char
x, SourcePos -> SourceName -> D
pack (SourcePos -> Char -> SourcePos
updatePosChar SourcePos
p Char
x) SourceName
xs)
    in  D {Maybe (Char, D)
Result D SourceName
Result D Word
Result D Assign
Result D IODesc
Result D Token
_token :: Result D Token
_anyWord :: Result D Word
_ioDesc :: Result D IODesc
_anyOperator :: Result D SourceName
_assign :: Result D Assign
_uncons :: Maybe (Char, D)
_token :: Result D Token
_anyWord :: Result D Word
_ioDesc :: Result D IODesc
_anyOperator :: Result D SourceName
_assign :: Result D Assign
_uncons :: Maybe (Char, D)
..}

-- | Parse a value satisfying the predicate.
satisfying
    :: (Stream s m t, Show a)
    => ParsecT s u m a
    -> (a -> Bool)
    -> ParsecT s u m a
satisfying :: forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> (a -> Bool) -> ParsecT s u m a
satisfying ParsecT s u m a
a a -> Bool
p = ParsecT s u m a -> ParsecT s u m a
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (ParsecT s u m a -> ParsecT s u m a)
-> ParsecT s u m a -> ParsecT s u m a
forall a b. (a -> b) -> a -> b
$ do
    a
t <- ParsecT s u m a
a
    if a -> Bool
p a
t then a -> ParsecT s u m a
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
t else SourceName -> ParsecT s u m a
forall s (m :: * -> *) t u a.
Stream s m t =>
SourceName -> ParsecT s u m a
unexpected (a -> SourceName
forall a. Show a => a -> SourceName
show a
t)

-- | Shell reserved words.
reservedWords :: [Word]
reservedWords :: [Word]
reservedWords = (SourceName -> Word) -> [SourceName] -> [Word]
forall a b. (a -> b) -> [a] -> [b]
map SourceName -> Word
stringToWord
    [ SourceName
"!", SourceName
"[[", SourceName
"]]", SourceName
"{", SourceName
"}"
    , SourceName
"if", SourceName
"then", SourceName
"else", SourceName
"elif", SourceName
"fi"
    , SourceName
"case", SourceName
"esac", SourceName
"for", SourceName
"select", SourceName
"while", SourceName
"until"
    , SourceName
"in", SourceName
"do", SourceName
"done", SourceName
"time", SourceName
"function"
    ]

-- | Shell assignment builtins. These builtins can take assignments as
-- arguments.
assignBuiltins :: [Word]
assignBuiltins :: [Word]
assignBuiltins = (SourceName -> Word) -> [SourceName] -> [Word]
forall a b. (a -> b) -> [a] -> [b]
map SourceName -> Word
stringToWord
    [ SourceName
"alias", SourceName
"declare", SourceName
"export", SourceName
"eval"
    , SourceName
"let", SourceName
"local", SourceName
"readonly", SourceName
"typeset"
    ]

-- | All Bash operators.
operators :: [String]
operators :: [SourceName]
operators =
    [ SourceName
"(", SourceName
")", SourceName
";;", SourceName
";&", SourceName
";;&"
    , SourceName
"|", SourceName
"|&", SourceName
"||", SourceName
"&&", SourceName
";", SourceName
"&", SourceName
"\r\n", SourceName
"\n"
    , SourceName
"<", SourceName
">", SourceName
">|", SourceName
">>", SourceName
"&>", SourceName
"&>>", SourceName
"<<<", SourceName
"<&", SourceName
">&", SourceName
"<>"
    , SourceName
"<<", SourceName
"<<-"
    ]

-- | Parse a descriptor.
descriptor :: Stream s m Char => ParsecT s u m IODesc
descriptor :: forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m IODesc
descriptor = Int -> IODesc
IONumber (Int -> IODesc) -> (SourceName -> Int) -> SourceName -> IODesc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SourceName -> Int
forall a. Read a => SourceName -> a
read (SourceName -> IODesc)
-> ParsecT s u m SourceName -> ParsecT s u m IODesc
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT s u m Char -> ParsecT s u m SourceName
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many1 ParsecT s u m Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit
         ParsecT s u m IODesc
-> ParsecT s u m IODesc -> ParsecT s u m IODesc
forall a. ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> SourceName -> IODesc
IOVar (SourceName -> IODesc)
-> ParsecT s u m Char -> ParsecT s u m (SourceName -> IODesc)
forall a b. a -> ParsecT s u m b -> ParsecT s u m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'{' ParsecT s u m (SourceName -> IODesc)
-> ParsecT s u m SourceName -> ParsecT s u m IODesc
forall a b.
ParsecT s u m (a -> b) -> ParsecT s u m a -> ParsecT s u m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT s u m SourceName
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m SourceName
I.name ParsecT s u m IODesc -> ParsecT s u m Char -> ParsecT s u m IODesc
forall a b. ParsecT s u m a -> ParsecT s u m b -> ParsecT s u m a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> ParsecT s u m Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'}'

-- | Parse a single token.
token :: Monad m => ParsecT D u m Token
token :: forall (m :: * -> *) u. Monad m => ParsecT D u m Token
token = ParsecT D u m Token -> ParsecT D u m Token
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((D -> Result D Token) -> ParsecT D u m Token
forall (m :: * -> *) d a u.
Monad m =>
(d -> Result d a) -> ParsecT d u m a
rat D -> Result D Token
_token) ParsecT D u m Token -> SourceName -> ParsecT D u m Token
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"token"

-- | Parse any word.
anyWord :: Monad m => ParsecT D u m Word
anyWord :: forall (m :: * -> *) u. Monad m => ParsecT D u m Word
anyWord = ParsecT D u m Word -> ParsecT D u m Word
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((D -> Result D Word) -> ParsecT D u m Word
forall (m :: * -> *) d a u.
Monad m =>
(d -> Result d a) -> ParsecT d u m a
rat D -> Result D Word
_anyWord) ParsecT D u m Word -> SourceName -> ParsecT D u m Word
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"word"

-- | Parse the given word.
word :: Monad m => String -> ParsecT D u m Word
word :: forall (m :: * -> *) u. Monad m => SourceName -> ParsecT D u m Word
word SourceName
w = ParsecT D u m Word
forall (m :: * -> *) u. Monad m => ParsecT D u m Word
anyWord ParsecT D u m Word -> (Word -> Bool) -> ParsecT D u m Word
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> (a -> Bool) -> ParsecT s u m a
`satisfying` (Word -> Word -> Bool
forall a. Eq a => a -> a -> Bool
== SourceName -> Word
stringToWord SourceName
w) ParsecT D u m Word -> SourceName -> ParsecT D u m Word
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName -> SourceName
forall a. Pretty a => a -> SourceName
prettyText SourceName
w

-- | Parse a reversed word.
reservedWord :: Monad m => ParsecT D u m Word
reservedWord :: forall (m :: * -> *) u. Monad m => ParsecT D u m Word
reservedWord = ParsecT D u m Word
forall (m :: * -> *) u. Monad m => ParsecT D u m Word
anyWord ParsecT D u m Word -> (Word -> Bool) -> ParsecT D u m Word
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> (a -> Bool) -> ParsecT s u m a
`satisfying` (Word -> [Word] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word]
reservedWords) ParsecT D u m Word -> SourceName -> ParsecT D u m Word
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"reserved word"

-- | Parse an assignment builtin.
assignBuiltin :: Monad m => ParsecT D u m Word
assignBuiltin :: forall (m :: * -> *) u. Monad m => ParsecT D u m Word
assignBuiltin = ParsecT D u m Word
forall (m :: * -> *) u. Monad m => ParsecT D u m Word
anyWord ParsecT D u m Word -> (Word -> Bool) -> ParsecT D u m Word
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> (a -> Bool) -> ParsecT s u m a
`satisfying` (Word -> [Word] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Word]
assignBuiltins)
    ParsecT D u m Word -> SourceName -> ParsecT D u m Word
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"assignment builtin"

-- | Parse a redirection word or number.
ioDesc :: Monad m => ParsecT D u m IODesc
ioDesc :: forall (m :: * -> *) u. Monad m => ParsecT D u m IODesc
ioDesc = ParsecT D u m IODesc -> ParsecT D u m IODesc
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((D -> Result D IODesc) -> ParsecT D u m IODesc
forall (m :: * -> *) d a u.
Monad m =>
(d -> Result d a) -> ParsecT d u m a
rat D -> Result D IODesc
_ioDesc) ParsecT D u m IODesc -> SourceName -> ParsecT D u m IODesc
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"IO descriptor"

-- | Parse a variable name.
name :: Monad m => ParsecT D u m String
name :: forall (m :: * -> *) u. Monad m => ParsecT D u m SourceName
name = (Word -> SourceName
forall a. Pretty a => a -> SourceName
prettyText (Word -> SourceName)
-> ParsecT D u m Word -> ParsecT D u m SourceName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT D u m Word
forall (m :: * -> *) u. Monad m => ParsecT D u m Word
anyWord) ParsecT D u m SourceName
-> (SourceName -> Bool) -> ParsecT D u m SourceName
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> (a -> Bool) -> ParsecT s u m a
`satisfying` SourceName -> Bool
forall {a}. Pretty a => a -> Bool
isName ParsecT D u m SourceName -> SourceName -> ParsecT D u m SourceName
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"name"
  where
    isName :: a -> Bool
isName a
s = case Parsec SourceName () SourceName
-> SourceName -> SourceName -> Either ParseError SourceName
forall s t a.
Stream s Identity t =>
Parsec s () a -> SourceName -> s -> Either ParseError a
parse (Parsec SourceName () SourceName
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m SourceName
I.name Parsec SourceName () SourceName
-> ParsecT SourceName () Identity ()
-> Parsec SourceName () SourceName
forall a b.
ParsecT SourceName () Identity a
-> ParsecT SourceName () Identity b
-> ParsecT SourceName () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT SourceName () Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof) SourceName
"" (a -> SourceName
forall a. Pretty a => a -> SourceName
prettyText a
s) of
        Left ParseError
_  -> Bool
False
        Right SourceName
_ -> Bool
True

-- | Parse a function name.
functionName :: Monad m => ParsecT D u m String
functionName :: forall (m :: * -> *) u. Monad m => ParsecT D u m SourceName
functionName = (Word -> SourceName
forall a. Pretty a => a -> SourceName
prettyText (Word -> SourceName)
-> ParsecT D u m Word -> ParsecT D u m SourceName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT D u m Word
forall (m :: * -> *) u. Monad m => ParsecT D u m Word
anyWord) ParsecT D u m SourceName
-> (SourceName -> Bool) -> ParsecT D u m SourceName
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> (a -> Bool) -> ParsecT s u m a
`satisfying` SourceName -> Bool
forall {a}. Pretty a => a -> Bool
isFunctionName
   ParsecT D u m SourceName -> SourceName -> ParsecT D u m SourceName
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"function name"
  where
    isFunctionName :: a -> Bool
isFunctionName a
s = case Parsec SourceName () SourceName
-> SourceName -> SourceName -> Either ParseError SourceName
forall s t a.
Stream s Identity t =>
Parsec s () a -> SourceName -> s -> Either ParseError a
parse (Parsec SourceName () SourceName
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m SourceName
I.functionName Parsec SourceName () SourceName
-> ParsecT SourceName () Identity ()
-> Parsec SourceName () SourceName
forall a b.
ParsecT SourceName () Identity a
-> ParsecT SourceName () Identity b
-> ParsecT SourceName () Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT SourceName () Identity ()
forall s (m :: * -> *) t u.
(Stream s m t, Show t) =>
ParsecT s u m ()
eof) SourceName
"" (a -> SourceName
forall a. Pretty a => a -> SourceName
prettyText a
s) of
        Left ParseError
_  -> Bool
False
        Right SourceName
_ -> Bool
True

-- | Parse any operator.
anyOperator :: Monad m => ParsecT D u m String
anyOperator :: forall (m :: * -> *) u. Monad m => ParsecT D u m SourceName
anyOperator = ParsecT D u m SourceName -> ParsecT D u m SourceName
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((D -> Result D SourceName) -> ParsecT D u m SourceName
forall (m :: * -> *) d a u.
Monad m =>
(d -> Result d a) -> ParsecT d u m a
rat D -> Result D SourceName
_anyOperator) ParsecT D u m SourceName -> SourceName -> ParsecT D u m SourceName
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"operator"

-- | Parse a given operator.
operator :: Monad m => String -> ParsecT D u m String
operator :: forall (m :: * -> *) u.
Monad m =>
SourceName -> ParsecT D u m SourceName
operator SourceName
op = ParsecT D u m SourceName
forall (m :: * -> *) u. Monad m => ParsecT D u m SourceName
anyOperator ParsecT D u m SourceName
-> (SourceName -> Bool) -> ParsecT D u m SourceName
forall s (m :: * -> *) t a u.
(Stream s m t, Show a) =>
ParsecT s u m a -> (a -> Bool) -> ParsecT s u m a
`satisfying` (SourceName -> SourceName -> Bool
forall a. Eq a => a -> a -> Bool
== SourceName
op) ParsecT D u m SourceName -> SourceName -> ParsecT D u m SourceName
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
op

-- | Parse an assignment.
assign :: Monad m => ParsecT D u m Assign
assign :: forall (m :: * -> *) u. Monad m => ParsecT D u m Assign
assign = ParsecT D u m Assign -> ParsecT D u m Assign
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try ((D -> Result D Assign) -> ParsecT D u m Assign
forall (m :: * -> *) d a u.
Monad m =>
(d -> Result d a) -> ParsecT d u m a
rat D -> Result D Assign
_assign) ParsecT D u m Assign -> SourceName -> ParsecT D u m Assign
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"assignment"

-- | Parse an arithmetic expression.
arith :: Monad m => ParsecT D u m String
arith :: forall (m :: * -> *) u. Monad m => ParsecT D u m SourceName
arith = ParsecT D u m SourceName -> ParsecT D u m SourceName
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (SourceName -> ParsecT D u m SourceName
forall s (m :: * -> *) u.
Stream s m Char =>
SourceName -> ParsecT s u m SourceName
string SourceName
"((") ParsecT D u m SourceName
-> ParsecT D u m SourceName -> ParsecT D u m SourceName
forall a b. ParsecT D u m a -> ParsecT D u m b -> ParsecT D u m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT D u m SourceName
forall s (m :: * -> *) u.
Stream s m Char =>
ParsecT s u m SourceName
I.arith ParsecT D u m SourceName
-> ParsecT D u m SourceName -> ParsecT D u m SourceName
forall a b. ParsecT D u m a -> ParsecT D u m b -> ParsecT D u m a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* SourceName -> ParsecT D u m SourceName
forall s (m :: * -> *) u.
Stream s m Char =>
SourceName -> ParsecT s u m SourceName
string SourceName
"))" ParsecT D u m SourceName
-> ParsecT D u m () -> ParsecT D u m SourceName
forall a b. ParsecT D u m a -> ParsecT D u m b -> ParsecT D u m a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ParsecT D u m ()
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m ()
I.skipSpace
    ParsecT D u m SourceName -> SourceName -> ParsecT D u m SourceName
forall s u (m :: * -> *) a.
ParsecT s u m a -> SourceName -> ParsecT s u m a
<?> SourceName
"arithmetic expression"

-- | Reparse a here document into a word.
heredocWord :: Monad m => String -> ParsecT s u m Word
heredocWord :: forall (m :: * -> *) s u.
Monad m =>
SourceName -> ParsecT s u m Word
heredocWord = ParsecT SourceName u m Word -> SourceName -> ParsecT s u m Word
forall s (m :: * -> *) t0 u a t.
Stream s m t0 =>
ParsecT s u m a -> s -> ParsecT t u m a
reparse ParsecT SourceName u m Word
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Word
I.heredocWord