1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
import Control.Monad.Trans.Either
import Control.Monad.Trans.State
import Control.Pipe
import Control.Pipe.Category
import Control.Pipe.Trans
import Data.Monoid
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Text (Text)
newtype ParseP p a b r = ParseP {
unParseP :: StateP Text (EitherP String p) a b r }
deriving (Monad, MonadPipe)
instance PipeTrans ParseP where
liftP = ParseP . liftP . liftP
runParseP = runEitherP . (`runStateP` T.empty) . unParseP
take' :: Monad m => Int -> ParseP (Pipe m) Text b Text
take' n = ParseP go where
go = do
s <- P get
if (T.length s < n)
then do
s' <- liftP $ liftP await
P $ put (s <> s')
go
else do
let (h, t) = T.splitAt n s
P $ put t
return h
parseFail str = ParseP $ liftP $ P $ left str
string :: (Monad m) => Text -> ParseP (Pipe m) Text b Text
string str = do
str' <- take' (T.length str)
if (str' == str)
then return str
else parseFail $ concat [
"Expected: '", T.unpack str, "' -- Found: ", T.unpack str', "'"]
source :: (Monad m) => Pipe m x Text ()
source = do
yield $ T.pack "Hell"
yield $ T.pack "o, world!"
sink :: ParseP (Pipe IO) Text x ()
sink = do
string $ T.pack "Hello"
str <- take' 5
liftP $ liftPipe $ T.putStrLn str
|