-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParser.hs
81 lines (64 loc) · 1.75 KB
/
Parser.hs
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{-# LANGUAGE LambdaCase #-}
module Parser where
import Control.Applicative
import Control.Monad.Trans.State
type Parser c a = StateT [c] Maybe a
runParser :: StateT s m a -> s -> m (a, s)
runParser = runStateT
(<#>) :: Parser c a -> [c] -> Maybe (a, [c])
(<#>) = runParser
parser :: (s -> m (a, s)) -> StateT s m a
parser = StateT
char :: Eq c => c -> Parser c c
char c = parser $ \case
[] -> empty
(x : xs) | c == x -> return (x, xs)
| otherwise -> empty
string :: Eq c => [c] -> Parser c [c]
string = mapM char
satisfy :: (c -> Bool) -> Parser c c
satisfy f = parser $ \case
[] -> empty
(x : xs) | f x -> return (x, xs)
| otherwise -> empty
while :: (c -> Bool) -> Parser c [c]
while = many . satisfy
while1 :: (c -> Bool) -> Parser c [c]
while1 = some . satisfy
sepBy :: Parser c b -> Parser c a -> Parser c [a]
sepBy s e = sepBy1 s e <|> return []
sepBy1 :: Parser c b -> Parser c a -> Parser c [a]
sepBy1 s e = (:) <$> e <*> many (s *> e)
chainl :: Parser c a -> Parser c (a -> a -> a) -> Parser c a -> Parser c a
chainl p op = (chainl1 p op <|>)
chainl1 :: Parser c a -> Parser c (a -> a -> a) -> Parser c a
chainl1 p op = p >>= rest
where
rest x =
do
o <- op
y <- p
rest (x `o` y)
<|> return x
chainr :: Parser c a -> Parser c (a -> a -> a) -> Parser c a -> Parser c a
chainr p op = (chainr1 p op <|>)
chainr1 :: Parser c a -> Parser c (a -> a -> a) -> Parser c a
chainr1 p op = scan
where
scan = do
x <- p
rest x
rest x =
(do
f <- op
f x <$> scan
)
<|> return x
eoi :: Parser c ()
eoi = parser $ \case
[] -> return ((), [])
_ -> empty
anyChar :: Parser c c
anyChar = parser $ \case
[] -> empty
(x : xs) -> return (x, xs)