module System.IO.Uniform.Streamline.Scanner (
IOScanner,
IOScannerState(..),
textScanner,
anyScanner
)where
import Data.Default.Class
import Data.Word8 (Word8)
data IOScannerState a =
Finished |
LastPass a |
Running a
instance Functor IOScannerState where
fmap _ Finished = Finished
fmap f (LastPass x) = LastPass $ f x
fmap f (Running x) = Running $ f x
instance Applicative IOScannerState where
pure = Running
Finished <*> _ = Finished
_ <*> Finished = Finished
(LastPass f) <*> (LastPass x) = LastPass $ f x
(LastPass f) <*> (Running x) = LastPass $ f x
(Running f) <*> (LastPass x) = LastPass $ f x
(Running f) <*> (Running x) = Running $ f x
instance Monad IOScannerState where
return = pure
Finished >>= _ = Finished
(LastPass x) >>= f = case f x of
Finished -> Finished
LastPass y -> LastPass y
Running y -> LastPass y
(Running x) >>= f = f x
type IOScanner a = a -> Word8 -> IOScannerState a
anyScanner :: Default a => [IOScanner a] -> IOScanner [a]
anyScanner scanners = scan
where
scan st c = sequence $ apScanner scanners st c
apScanner [] _ _ = []
apScanner (s:ss) [] h = s def h : apScanner ss [] h
apScanner (s:ss) (t:tt) h = s t h : apScanner ss tt h
textScanner :: [Word8] -> IOScanner [[Word8]]
textScanner [] = \_ _ -> Finished
textScanner t@(c:_) = scanner
where
scanner st c'
| c == c' = popStacks (t:st) c'
| otherwise = popStacks st c'
popStacks :: IOScanner [[Word8]]
popStacks [] _ = Running []
popStacks ([]:_) _ = Finished
popStacks ((h':hh):ss) h
| h == h' && null hh = case popStacks ss h of
Finished -> Finished
LastPass ss' -> LastPass ss'
Running ss' -> LastPass ss'
| h == h' = case popStacks ss h of
Finished -> Finished
LastPass ss' -> LastPass $ hh:ss'
Running ss' -> Running $ hh:ss'
| otherwise = popStacks ss h