123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- (* json-parser.sml
- *
- * COPYRIGHT (c) 2008 The Fellowship of SML/NJ (http://www.smlnj.org)
- * All rights reserved.
- *)
- structure JSONParser :> sig
- (* abstract type of JSON input *)
- type source = JSONSource.source
- (* open a text input stream as a source *)
- val openStream : TextIO.instream -> source
- (* open a text file as a source *)
- val openFile : string -> source
- (* open a string as a source *)
- val openString : string -> source
- (* close a source *)
- val close : source -> unit
- val parse : source -> JSON.value
- val parseFile : string -> JSON.value
- end = struct
- structure Lex = JSONLexer
- structure T = JSONTokens
- structure J = JSON
- datatype source = datatype JSONSource.source
- val openStream = JSONSource.openStream
- val openFile = JSONSource.openFile
- val openString = JSONSource.openString
- val close = JSONSource.close
- fun parse (Src{closed = ref true, ...}) = raise Fail "closed JSON source"
- | parse (src as Src{srcMap, strm, ...}) = let
- val errorMsg = JSONSource.errorMsg src
- fun error arg = raise Fail(errorMsg arg)
- val lexer = Lex.lex srcMap
- fun parseValue (strm : Lex.strm) = let
- val (tok, span, 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 (span, "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, span, strm) = lexer strm
- in
- case tok
- of T.RB => (strm, v::items)
- | T.COMMA => loop (strm, v::items)
- | _ => error (span, "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 ((T.STRING s, _, strm), flds) = (case lexer strm
- of (T.COLON, _, strm) => let
- val (strm, v) = parseValue strm
- in
- parseFields (strm, (s, v)::flds)
- end
- | (tok, span, _) => error (span, "parsing field", tok)
- (* end case *))
- | parseField ((tok, span, _), _) = error (span, "parsing field", tok)
- and parseFields (strm, flds) = (case lexer strm
- of (T.RCB, span, strm) => (strm, J.OBJECT(List.rev flds))
- | (T.COMMA, span, strm) => parseField (lexer strm, flds)
- | (tok, span, _) => error (span, "parsing object", tok)
- (* end case *))
- in
- case lexer strm
- of (T.RCB, span, strm) => (strm, J.OBJECT[])
- | tokEtc => parseField (tokEtc, [])
- (* end case *)
- end
- val (inStrm, value) = parseValue (!strm)
- in
- strm := inStrm;
- value
- end
- fun parseFile fileName = let
- val inStrm = openFile fileName
- val v = parse inStrm
- handle ex => (close inStrm; raise ex)
- in
- close inStrm;
- v
- end
- end
|