-
Notifications
You must be signed in to change notification settings - Fork 0
/
Json.idr
107 lines (91 loc) · 3.09 KB
/
Json.idr
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
module Main
import Data.SortedMap
import Invincy
data JsonValue = JsonString String
| JsonNumber Double
| JsonBool Bool
| JsonNull
| JsonArray (List JsonValue)
| JsonObject (SortedMap String JsonValue)
-- can't generate it with elaborator reflection yet
data JsonType = JTString
| JTNumber
| JTBool
| JTNull
| JTArray
| JTObject
-- derivation with Pruviloj.Derive.DecEq leads to strange errors
implementation DecEq JsonType where
decEq JTString JTString = Yes Refl
decEq JTNumber JTNumber = Yes Refl
decEq JTBool JTBool = Yes Refl
decEq JTNull JTNull = Yes Refl
decEq JTArray JTArray = Yes Refl
decEq JTObject JTObject = Yes Refl
decEq x y = No $ believe_me (x = y -> Void) -- won't need those
jcArgs : JsonType -> (x ** x -> JsonValue)
%runElab (cArgs (NS (UN "jcArgs") ["Main"]))
dsJson : JsonValue -> (x ** getWitness (jcArgs x))
%runElab (dArgs `(\x => getWitness (jcArgs x)) (NS (UN "dsJson") ["Main"]))
jsonNull' : PP String ()
jsonNull' = raw' "null"
jsonBool' : PP String Bool
jsonBool' = choices' {f=const ()} {e=Bool} (const {b=()}) (\b => (b ** ()))
[(True ** raw' "true"),
(False ** raw' "false")]
jsonNumber' : PP String Double
jsonNumber' = (jsonNumber, MkPrinter $ fromString . show)
where
jsonNumber : Parser String Double
jsonNumber = do
x <- getWitness <$> some digit
y <- option $ Prelude.Applicative.(*>) (val '.') (getWitness <$> some digit)
return $ cast . pack $ x ++ (maybe neutral ('.' ::) y)
jsonString' : PP String String
jsonString' = (jsonString, MkPrinter $ fromString . show)
where
jsonStr : Parser String String
jsonStr = (val '"' *> pure neutral) <|> do
c <- sat (/= '"')
if (c == '\\')
then cons <$> oneOf ['"', '\\', '/', '\b', '\f', '\n', '\r', '\t'] <*> jsonStr
else (cons c) <$> jsonStr
jsonString : Parser String String
jsonString = val '"' *> jsonStr
mutual
jsonValue' : PP String JsonValue
jsonValue' = choices dsJson
[ (JTString ** jsonString')
, (JTNumber ** jsonNumber')
, (JTBool ** jsonBool')
, (JTNull ** jsonNull')
, (JTArray ** jsonArray')
, (JTObject ** jsonObject')
]
jsonArray' : PP String (List JsonValue)
jsonArray' =
val' '[' *> spaces' *>
sepBy' jsonValue' (spaces' *> val' ',' <* spaces')
<* spaces' <* val' ']'
jsonObject' : PP String (SortedMap String JsonValue)
jsonObject' = (fromList, toList) <$>
(val' '{' *> spaces' *>
sepBy' (jsonString' <* spaces' <* val' ':' <* spaces' <*> jsonValue')
(spaces' *> val' ',' <* spaces')
<* spaces' <* val' '}')
json' : PP String JsonValue
json' = choices dsJson
[ (JTArray ** jsonArray')
, (JTObject ** jsonObject')
]
main : IO ()
main = do
putStrLn "Type some JSON here:"
v <- parseWith' (spaces' *> json') $ (++ "\n") <$> getLine
case v of
Done i x => do
putStrLn "Parsed! Printing:"
putStrLn $ print' json' x
Failure s => putStrLn $ "Failure: " ++ s
Partial _ => putStrLn "Uh oh, partial"
main