-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJSONParser.hs
More file actions
79 lines (68 loc) · 2.24 KB
/
JSONParser.hs
File metadata and controls
79 lines (68 loc) · 2.24 KB
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
{-
Abstract syntax & parser for JSON values (http://www.json.org)
Pedro Vasconcelos, 2016
Modified by Rui Afonso Pereira, 2017
-}
module JSONParser
(
JSONValue(..)
) where
import Text.Parsec
import Text.Parsec.Language (emptyDef)
import qualified Text.Parsec.Token as P
-- a string parser with no user-state
type Parser = Parsec String ()
{- abstract syntax for JSON values
(http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)
-}
data JSONValue = Number Integer
-- ^ NB: floating-point values ommitted for brevity
| String String
| Bool Bool
| Null
| Array [JSONValue]
| Object [(String, JSONValue)]
deriving (Eq, Ord, Show)
--- tokenizer
lexer = P.makeTokenParser emptyDef
whiteSpace = P.whiteSpace lexer
symbol = P.symbol lexer
reserved = P.reserved lexer
integer = P.integer lexer
stringLiteral = P.stringLiteral lexer
--- syntax rules
jsonValue :: Parser JSONValue
jsonValue = do { n <- integer; return (Number n) }
<|> do { b <- boolean; return (Bool b) }
<|> do { s <- stringLiteral; return (String s) }
<|> do { reserved "null"; return Null }
<|> do { symbol "[";
vs <- jsonValue `sepBy` comma;
symbol "]";
return (Array vs)
}
<|> do { symbol "{";
pairs <- keyValuePair `sepBy` comma;
symbol "}";
return (Object pairs)
}
keyValuePair :: Parser (String, JSONValue)
keyValuePair = do { n <- stringLiteral;
colon;
v <- jsonValue;
return (n, v)
}
comma = symbol ","
colon = symbol ":"
boolean :: Parser Bool
boolean = do { reserved "true"; return True } <|>
do { reserved "false"; return False }
--- File input
readJson :: FilePath -> IO JSONValue
readJson filepath
= do { contents <- readFile filepath
; case parse topValue filepath contents of
Left err -> error (show err)
Right val -> return val
}
topValue = do whiteSpace; v <- jsonValue; eof; return v