/
Attoparsec.fs
78 lines (60 loc) · 1.83 KB
/
Attoparsec.fs
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
module Attoparsec.Json
open Attoparsec
open Attoparsec.String
open System
open Helper
open Ast
let ws = spaces
let str = pstring
let stringLiteral =
let escape =
oneOf "\"\\/bfnrt"
|>> (function
| 'b' -> "\b"
| 'f' -> "\u000C"
| 'n' -> "\n"
| 'r' -> "\r"
| 't' -> "\t"
| c -> string c)
let hex = satisfy (inClass "0-9a-fA-F")
let unicodeEscape =
let hex2int c = (int c &&& 15) + (int c >>> 6) * 9
str "u" >>.
hex >>= fun h3 ->
hex >>= fun h2 ->
hex >>= fun h1 ->
hex |>> fun h0 ->
(hex2int h3) * 4096 + (hex2int h2) * 256 + (hex2int h1) * 16 + hex2int h0
|> char |> string
between (str "\"") (str "\"")
(stringsSepBy (manySatisfy (fun c -> c <> '"' && c <> '\\')) (str "\\" >>. (escape <|> unicodeEscape)) |>> BmpString.toString)
let jstring = stringLiteral |>> JString
let pfloat = scientific |>> float
let jnumber = pfloat |>> JNumber
let jtrue = pstring "true" >>% (JBool true)
let jfalse = pstring "false" >>% (JBool false)
let jnull = pstring "null" >>% JNull
let jvalue, jvalueRef = createParserForwardedToRef()
let listBetweenStrings sOpen sClose pElement f =
between (str sOpen) (str sClose) (ws >>. sepBy (pElement .>> ws) (str "," .>> ws) |>> f)
let keyValue = tuple2 stringLiteral (ws >>. str ":" >>. ws >>. jvalue)
let jlist = listBetweenStrings "[" "]" jvalue JList
let jobject = listBetweenStrings "{" "}" keyValue (Map.ofList >> JObject)
do
jvalueRef :=
choice [
jobject
jlist
jstring
jnumber
jtrue
jfalse
jnull
]
let json = ws >>. jvalue .>> ws
let parseJsonString str = parse json str
let formatResult result =
match ParseResult.feed "" result with
| Partial _
| Done _ -> "Success"
| Fail(_, _, e) -> e