-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson-parser.sml
101 lines (91 loc) · 2.78 KB
/
json-parser.sml
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
(* json-parser.sml
*
* COPYRIGHT (c) 2008 The Fellowship of SML/NJ (http://www.smlnj.org)
* All rights reserved.
*)
structure JSONParser : sig
val parse : TextIO.instream -> JSON.value
val parseFile : string -> JSON.value
end = struct
structure Lex = JSONLexer
structure T = JSONTokens
structure J = JSON
fun parse' (srcMap, inStrm) = let
fun error (pos, msg, tok) = raise Fail(concat[
"error ", AntlrStreamPos.spanToString srcMap pos, ": ",
msg, ", found '", JSONTokens.toString tok, "'"
])
val lexer = Lex.lex srcMap
fun parseValue (strm : Lex.strm) = let
val (tok, pos, strm) = lexer strm
in
case tok
of T.LB => parseArray strm
| T.LCB => parseObject strm
| T.KW_null => (strm, J.NULL)
| T.KW_true => (strm, J.BOOL true)
| T.KW_false => (strm, J.BOOL false)
| T.INT n => (strm, J.INT n)
| T.FLOAT f => (strm, J.FLOAT f)
| T.STRING s => (strm, J.STRING s)
| _ => error (pos, "parsing value", tok)
(* end case *)
end
and parseArray (strm : Lex.strm) = (case lexer strm
of (T.RB, _, strm) => (strm, J.ARRAY[])
| _ => let
fun loop (strm, items) = let
val (strm, v) = parseValue strm
(* expect either a "," or a "]" *)
val (tok, pos, strm) = lexer strm
in
case tok
of T.RB => (strm, v::items)
| T.COMMA => loop (strm, v::items)
| _ => error (pos, "parsing array", tok)
(* end case *)
end
val (strm, items) = loop (strm, [])
in
(strm, J.ARRAY(List.rev items))
end
(* end case *))
and parseObject (strm : Lex.strm) = let
fun parseField strm = (case lexer strm
of (T.STRING s, pos, strm) => (case lexer strm
of (T.COLON, _, strm) => let
val (strm, v) = parseValue strm
in
SOME(strm, (s, v))
end
| (tok, pos, _) => error (pos, "parsing field", tok)
(* end case *))
| _ => NONE
(* end case *))
fun loop (strm, flds) = (case parseField strm
of SOME(strm, fld) => (
(* expect either "," or "}" *)
case lexer strm
of (T.RCB, pos, strm) => (strm, fld::flds)
| (T.COMMA, pos, strm) => loop (strm, fld::flds)
| (tok, pos, _) => error (pos, "parsing object", tok)
(* end case *))
| NONE => (strm, flds)
(* end case *))
val (strm, flds) = loop (strm, [])
in
(strm, J.OBJECT(List.rev flds))
end
in
#2 (parseValue (Lex.streamifyInstream inStrm))
end
fun parse inStrm = parse' (AntlrStreamPos.mkSourcemap (), inStrm)
fun parseFile fileName = let
val inStrm = TextIO.openIn fileName
val v = parse' (AntlrStreamPos.mkSourcemap' fileName, inStrm)
handle ex => (TextIO.closeIn inStrm; raise ex)
in
TextIO.closeIn inStrm;
v
end
end