|
@@ -1,6 +1,6 @@
|
|
|
(* json-stream-printer.sml
|
|
|
*
|
|
|
- * COPYRIGHT (c) 2008 The Fellowship of SML/NJ (http://www.smlnj.org)
|
|
|
+ * COPYRIGHT (c) 2020 The Fellowship of SML/NJ (http://www.smlnj.org)
|
|
|
* All rights reserved.
|
|
|
*)
|
|
|
|
|
@@ -38,7 +38,8 @@ structure JSONStreamPrinter : sig
|
|
|
* and punctuation, etc.
|
|
|
*)
|
|
|
and context
|
|
|
- = TOP (* top-most context *)
|
|
|
+ = CLOSED (* closed printer *)
|
|
|
+ | TOP (* top-most context *)
|
|
|
| FIRST of context (* first element of object or array; the argument *)
|
|
|
(* must be one of OBJECT or ARRAY. *)
|
|
|
| OBJECT of context (* in an object (after the first element) *)
|
|
@@ -54,8 +55,11 @@ structure JSONStreamPrinter : sig
|
|
|
|
|
|
fun new strm = new' {strm = strm, pretty = false}
|
|
|
|
|
|
- fun close (P{ctx = ref TOP, strm, ...}) = TextIO.output(strm, "\n")
|
|
|
- | close _ = raise Fail "premature close"
|
|
|
+ fun close (P{ctx, strm, ...}) = (case !ctx
|
|
|
+ of CLOSED => ()
|
|
|
+ | TOP => (TextIO.output(strm, "\n"); ctx := CLOSED)
|
|
|
+ | _ => raise Fail "premature close"
|
|
|
+ (* end case *))
|
|
|
|
|
|
fun pr (P{strm, ...}, s) = TextIO.output(strm, s)
|
|
|
|
|
@@ -90,7 +94,8 @@ structure JSONStreamPrinter : sig
|
|
|
(* end case *))
|
|
|
|
|
|
(* print a value, which may be proceeded by a comma if it is in a sequence *)
|
|
|
- fun prVal (p, v) = (optComma p; pr(p, v))
|
|
|
+ fun prVal (P{ctx = ref CLOSED, ...}, _) = raise Fail "closed printer"
|
|
|
+ | prVal (p, v) = (optComma p; pr(p, v))
|
|
|
|
|
|
fun null p = prVal (p, "null")
|
|
|
fun boolean (p, false) = prVal (p, "false")
|
|
@@ -122,16 +127,23 @@ structure JSONStreamPrinter : sig
|
|
|
prVal (p, F.format "\"%s\"" [F.STR(tr (0, []))])
|
|
|
end
|
|
|
|
|
|
- fun beginObject (p as P{ctx, ...}) = (
|
|
|
- optComma p;
|
|
|
- pr (p, "{"); incIndent(p, 2); nl p;
|
|
|
- ctx := FIRST(OBJECT(!ctx)))
|
|
|
+ fun beginObject (p as P{ctx, ...}) = (case !ctx
|
|
|
+ of CLOSED => raise Fail "closed printer"
|
|
|
+ | _ => (
|
|
|
+ optComma p;
|
|
|
+ pr (p, "{"); incIndent(p, 2); nl p;
|
|
|
+ ctx := FIRST(OBJECT(!ctx)))
|
|
|
+ (* end case *))
|
|
|
|
|
|
- fun objectKey (p as P{ctx = ref(KEY _), ...}, field) =
|
|
|
- raise Fail(concat["objectKey \"", field, "\" where value was expected"])
|
|
|
- | objectKey (p as P{ctx, ...}, field) = (
|
|
|
- string (p, field);
|
|
|
- ctx := KEY(!ctx))
|
|
|
+ fun objectKey (p as P{ctx, ...}, field) = (case !ctx
|
|
|
+ of CLOSED => raise Fail "closed printer"
|
|
|
+ | KEY _ => raise Fail(concat[
|
|
|
+ "objectKey \"", field, "\" where value was expected"
|
|
|
+ ])
|
|
|
+ | _ => (
|
|
|
+ string (p, field);
|
|
|
+ ctx := KEY(!ctx))
|
|
|
+ (* end case *))
|
|
|
|
|
|
fun endObject (p as P{ctx, ...}) = let
|
|
|
fun prEnd ctx' = (
|
|
@@ -139,16 +151,21 @@ structure JSONStreamPrinter : sig
|
|
|
indent(p, ~1); pr(p, "}"); decIndent (p, 2))
|
|
|
in
|
|
|
case !ctx
|
|
|
- of OBJECT ctx' => (nl p; prEnd ctx')
|
|
|
+ of CLOSED => raise Fail "closed printer"
|
|
|
+ | OBJECT ctx' => (nl p; prEnd ctx')
|
|
|
| FIRST(OBJECT ctx') => prEnd ctx'
|
|
|
+ | KEY _ => raise Fail "expecting value after key"
|
|
|
| _ => raise Fail "endObject not in object context"
|
|
|
(* end case *)
|
|
|
end
|
|
|
|
|
|
- fun beginArray (p as P{ctx, ...}) = (
|
|
|
- optComma p;
|
|
|
- pr (p, "["); incIndent(p, 2); nl p;
|
|
|
- ctx := FIRST(ARRAY(!ctx)))
|
|
|
+ fun beginArray (p as P{ctx, ...}) = (case !ctx
|
|
|
+ of CLOSED => raise Fail "closed printer"
|
|
|
+ | _ => (
|
|
|
+ optComma p;
|
|
|
+ pr (p, "["); incIndent(p, 2); nl p;
|
|
|
+ ctx := FIRST(ARRAY(!ctx)))
|
|
|
+ (* end case *))
|
|
|
|
|
|
fun endArray (p as P{ctx, ...}) = let
|
|
|
fun prEnd ctx' = (
|
|
@@ -156,7 +173,8 @@ structure JSONStreamPrinter : sig
|
|
|
indent(p, ~1); pr(p, "]"); decIndent (p, 2))
|
|
|
in
|
|
|
case !ctx
|
|
|
- of ARRAY ctx' => (nl p; prEnd ctx')
|
|
|
+ of CLOSED => raise Fail "closed printer"
|
|
|
+ | ARRAY ctx' => (nl p; prEnd ctx')
|
|
|
| FIRST(ARRAY ctx') => prEnd ctx'
|
|
|
| _ => raise Fail "endArray not in array context"
|
|
|
(* end case *)
|