-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathParser.hs
67 lines (53 loc) · 1.54 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
module Parser where
import Control.Applicative
import Data.Char qualified as Char
newtype Parser a = Parser (String -> Maybe (a, String))
runParser :: Parser a -> String -> Maybe (a, String)
runParser (Parser f) = f
satisfy :: (Char -> Bool) -> Parser Char
satisfy pred = Parser f
where
f [] = Nothing
f (x : xs)
| pred x = Just (x, xs)
| otherwise = Nothing
char :: Char -> Parser Char
char c = satisfy (== c)
safeChar :: Char -> Parser String
safeChar c = (: []) <$> satisfy (== c) <|> pure []
digits :: Parser String
digits = Parser f
where
f xs = case span Char.isDigit xs of
([], _) -> Nothing
(nums, ys) -> Just (nums, ys)
instance Functor Parser where
fmap g p = Parser f
where
f xs = case runParser p xs of
Nothing -> Nothing
Just (m, n) -> Just (g m, n)
instance Applicative Parser where
pure x = Parser (\y -> Just (x, y))
f <*> p = Parser r
where
r xs = case runParser f xs of
Nothing -> Nothing
Just (m, n) -> runParser (fmap m p) n
instance Monad Parser where
p >>= k = Parser f
where
f x = case runParser p x of
Nothing -> Nothing
Just (m, n) -> runParser (k m) n
instance Alternative Parser where
empty = Parser (const Nothing)
p <|> q = Parser r
where
r xs = runParser p xs <|> runParser q xs
atleast0 :: Parser a -> Parser [a]
atleast0 p = atleast1 p <|> pure []
atleast1 :: Parser a -> Parser [a]
atleast1 p = (:) <$> p <*> atleast0 p
spaces :: Parser String
spaces = atleast0 (satisfy Char.isSpace)