{-# LANGUAGE InstanceSigs #-}
module Text.Lexer.Inchworm.Scanner
( Scanner (..)
, scanSourceToList)
where
import Text.Lexer.Inchworm.Source
data Scanner m loc input a
= Scanner
{ runScanner :: Source m loc input -> m (Maybe a) }
instance Monad m
=> Functor (Scanner m loc input) where
fmap f (Scanner load)
= Scanner $ \source
-> do r <- load source
case r of
Nothing -> return Nothing
Just x -> return $ Just $ f x
{-# INLINE fmap #-}
instance Monad m
=> Applicative (Scanner m loc input) where
pure x
= Scanner $ \_ -> return (Just x)
(<*>) (Scanner loadF) (Scanner loadX)
= Scanner $ \ss
-> do mf <- loadF ss
case mf of
Nothing
-> return Nothing
Just f
-> do mx <- loadX ss
case mx of
Nothing -> return Nothing
Just x -> return $ Just (f x)
instance Monad m
=> Monad (Scanner m loc input) where
return x
= Scanner $ \_ -> return (Just x)
(>>=) (Scanner loadX) f
= Scanner $ \ss
-> do mx <- loadX ss
case mx of
Nothing -> return Nothing
Just x -> runScanner (f x) ss
scanSourceToList
:: Monad m
=> Source m loc [i] -> Scanner m loc [i] a
-> m ([a], loc, [i])
scanSourceToList ss (Scanner load)
= go []
where go acc
= load ss >>= \result
-> case result of
Just x -> go (x : acc)
Nothing
-> do (loc, src') <- sourceRemaining ss
return (reverse acc, loc, src')
{-# SPECIALIZE INLINE
scanSourceToList
:: Source IO Location [Char]
-> Scanner IO Location [Char] a
-> IO ([a], Location, [Char])
#-}