1
1
{-# LANGUAGE OverloadedStrings #-}
2
2
3
3
module Parser
4
- (
4
+ ( runParser ,
5
+ Parser (.. ),
5
6
)
6
7
where
7
8
8
- import qualified Data.Map as M
9
+ import Control.Applicative
9
10
import qualified Data.Text as T
10
- import Text.Read (readMaybe )
11
-
12
- data JsonVal
13
- = -- Maybe indicates the fractional part of the number. This will obviously be `Nothing` if it's
14
- -- just a plain integer.
15
- JsonNumber Integer (Maybe Integer )
16
- | JsonBool Bool
17
- | JsonNull
18
- | JsonString T. Text
19
- | JsonArray [JsonVal ]
20
- | JsonObj (M. Map T. Text JsonVal )
21
- deriving (Eq , Show )
22
11
12
+ -- | Wraps a `parse` function into a newtype called `Parser` parameterized by some type `a`.
23
13
newtype Parser a = Parser { parse :: T. Text -> Maybe (a , T. Text )}
24
14
15
+ -- Lawful instance of Functor implemented for Parser
16
+ instance Functor Parser where
17
+ -- Applies a function to the parsed stream yielding another Parser with the transformed stream
18
+ fmap f p = Parser $ \ s -> do
19
+ (x, rest) <- parse p s
20
+ Just (f x, rest)
21
+
22
+ instance Applicative Parser where
23
+ pure x = Parser $ \ s -> Just (x, s)
24
+
25
+ -- This is how we'll essentially end up chaining parsers together
26
+ (<*>) (Parser p1) (Parser p2) = Parser $ \ s -> do
27
+ (f, s') <- p1 s
28
+ (x, s'') <- p2 s'
29
+ Just (f x, s'')
30
+
31
+ instance Alternative Parser where
32
+ -- Picks the first non-empty `Maybe`
33
+ (<|>) (Parser p1) (Parser p2) = Parser $ \ s -> p1 s <|> p2 s
34
+
35
+ -- The "empty" value for Parser will be a parser that parses to `Nothing` which indicates a failure
36
+ empty = Parser $ \ _ -> Nothing
37
+
25
38
runParser :: Parser a -> T. Text -> a
26
39
runParser m s =
27
40
case parse m s of
28
41
Just (res, " " ) -> res
29
42
Just (_, rest) -> error " Parser did not consume the entire stream"
30
43
Nothing -> error " Parser did not manage to parse anything"
31
-
32
- -- A test parser
33
- digit :: Parser Int
34
- digit = Parser $ \ s ->
35
- case s of
36
- " " -> Nothing
37
- t ->
38
- let ch = T. head t; cs = T. tail t
39
- in case readMaybe [ch] of
40
- Just x -> Just (x, cs)
41
- Nothing -> Nothing
0 commit comments