1
+ {-# LANGUAGE OverloadedStrings #-}
2
+
3
+ module Primitives () where
4
+
5
+ import Control.Applicative
6
+ import Data.Char (isDigit )
7
+ import qualified Data.Map as M
8
+ import qualified Data.Text as T
9
+ import Parser
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
+
23
+ jsonVal :: Parser JsonVal
24
+ jsonVal = jsonNumber <|> jsonNull <|> jsonBool
25
+
26
+ satisfy :: (Char -> Bool ) -> Parser T. Text
27
+ satisfy predicate = Parser $ \ s ->
28
+ let (t, rest) = span predicate $ T. unpack s
29
+ in -- If we don't manage to extract any valid tokens, then the received text will be null
30
+ -- If so, we'll fail the parsing
31
+ case t of
32
+ [] -> Nothing
33
+ _ -> Just (T. pack t, T. pack rest)
34
+
35
+ -- TODO: Implement parsing of floating point numbers
36
+ jsonNumber :: Parser JsonVal
37
+ jsonNumber = f <$> (satisfy isDigit)
38
+ where
39
+ f s = JsonNumber (read $ T. unpack s) Nothing
40
+
41
+ charP :: Char -> Parser Char
42
+ charP ch = Parser fn
43
+ where
44
+ fn s =
45
+ case T. uncons s of
46
+ Just (c, cs) | c == ch -> Just (c, cs)
47
+ _ -> Nothing
48
+
49
+ stringP :: T. Text -> Parser [Char ]
50
+ stringP s = (sequenceA . map charP) $ T. unpack s
51
+
52
+ jsonNull :: Parser JsonVal
53
+ jsonNull = (\ _ -> JsonNull ) <$> stringP " null"
54
+
55
+ jsonBool :: Parser JsonVal
56
+ jsonBool = f <$> (stringP " true" <|> stringP " false" )
57
+ where
58
+ f a = case a of
59
+ " true" -> JsonBool True
60
+ " false" -> JsonBool False
61
+
62
+ -- A test parser
63
+ digit :: Parser Int
64
+ digit = Parser $ \ s ->
65
+ case T. uncons s of
66
+ Nothing -> Nothing
67
+ Just (c, cs) -> case readMaybe [c] of
68
+ Just x -> Just (x, cs)
69
+ Nothing -> Nothing
0 commit comments