module Data.JustParse.Internal (
Stream (..),
Parser (..),
Result (..),
isDone,
isPartial,
toPartial,
finalize,
extend,
streamAppend
) where
import Prelude hiding ( length )
import Control.Monad ( MonadPlus, mzero, mplus, (>=>), ap )
import Control.Applicative ( Alternative, Applicative, pure, (<*>), empty, (<|>) )
import Data.Monoid ( Monoid, mempty, mappend )
import Data.List ( intercalate )
class (Eq s, Monoid s) => Stream s t | s -> t where
uncons :: Stream s t => s -> Maybe (t, s)
length :: Stream s t => s -> Int
length s =
case uncons s of
Nothing -> 0
Just (x, xs) -> 1 + length xs
newtype Parser s a =
Parser {
parse :: Maybe s -> [Result s a]
}
instance Stream s t => Monoid (Parser s a) where
mempty = mzero
mappend = mplus
instance Functor (Parser s) where
fmap f (Parser p) = Parser $ map (fmap f) . p
instance Applicative (Parser s) where
pure = return
(<*>) = ap
instance Stream s t => Alternative (Parser s) where
empty = mzero
(<|>) = mplus
instance Monad (Parser s) where
return v = Parser $ \s -> [Done v s]
(Parser p) >>= f = Parser $ p >=> g
where
g (Done a s) = parse (f a) s
g (Partial p) = [Partial $ p >=> g]
instance Stream s t => MonadPlus (Parser s) where
mzero = Parser $ const []
mplus a b = Parser $ \s ->
let
g [] = parse b s
g xs
| any isDone xs = xs
| otherwise = [Partial $ \s' ->
case s' of
Nothing ->
case finalize (parse a s) of
[] -> finalize (parse b s)
r -> r
_ -> parse (mplus a b) (streamAppend s s')]
in
g (parse a s)
data Result s a
=
Partial {
continue :: Maybe s -> [Result s a]
} |
Done {
value :: a,
leftover :: Maybe s
}
isDone :: Result s a -> Bool
isDone (Done _ _) = True
isDone _ = False
isPartial :: Result s a -> Bool
isPartial (Partial _) = True
isPartial _ = False
toPartial :: Parser s a -> [Result s a]
toPartial (Parser p) = [Partial p]
instance Functor (Result s) where
fmap f (Partial p) = Partial $ map (fmap f) . p
fmap f (Done a s) = Done (f a) s
instance Show a => Show (Result s a) where
show (Partial _) = "Partial"
show (Done a _) = show a
finalize :: (Eq s, Monoid s) => [Result s a] -> [Result s a]
finalize = extend Nothing
extend :: (Eq s, Monoid s) => Maybe s -> [Result s a] -> [Result s a]
extend s rs = rs >>= g
where
g (Partial p) = p s
g (Done a s') = [Done a (streamAppend s' s)]
streamAppend :: (Eq s, Monoid s) => Maybe s -> Maybe s -> Maybe s
streamAppend Nothing _ = Nothing
streamAppend (Just s) Nothing = if s == mempty then Nothing else Just s
streamAppend s s' = mappend s s'