<ocaml>_to_json should be basically done; json_to_<ocaml> remains.
Made a minor directory reorg, and added an omakefile to ease standalone builds.
--- /dev/null
+.PHONY: clean
+
+OCAMLFLAGS += -dtypes
+
+JSON_FILES[] =
+ json
+ json_parse
+ base_conv
+
+LIB = json
+JSON_LIB = $(OCamlLibrary $(LIB), $(JSON_FILES))
+
+section
+ TEST_PARSER_PROG = test_parser
+ OCAML_LIBS += json
+ TEST_PARSER = $(OCamlProgram $(TEST_PARSER_PROG), test_parser $(JSON_FILES))
+ export TEST_PARSER
+
+section
+ GEN_FILES = parser.mli parser.ml lexer.ml
+ OCamlGeneratedFiles($(GEN_FILES))
+ CONV_FILES[] =
+ lexer
+ parser
+ syntax
+ codegen
+ jsonc
+
+ JSON_CONV_PROG = jsonc
+ JSON_CONV = $(OCamlProgram $(JSON_CONV_PROG), $(CONV_FILES))
+ export JSON_CONV
+
+.DEFAULT: $(JSON_LIB) $(TEST_PARSER) $(JSON_CONV)
+
+clean:
+ rm -f $(filter-proper-targets $(ls R, .)) *.annot *.cmo
--- /dev/null
+open build/OCaml
+
+#
+# The command-line variables are defined *after* the
+# standard configuration has been loaded.
+#
+DefineCommandVars()
+
+#
+# Include the OMakefile in this directory.
+#
+.SUBDIRS: .
--- /dev/null
+(*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+open Json
+
+exception Json_conv_failure of string
+
+let string_of_json ?(permissive=false) j =
+ let strict = function
+ | Json_null _ -> raise (Json_conv_failure "null->string")
+ | Json_bool _ -> raise (Json_conv_failure "bool->string")
+ | Json_int _ -> raise (Json_conv_failure "int->string")
+ | Json_float _ -> raise (Json_conv_failure "float->string")
+ | Json_string s -> s
+ | Json_object _ -> raise (Json_conv_failure "object->string")
+ | Json_array _ -> raise (Json_conv_failure "array->string") in
+ let lenient = function
+ | Json_null _ -> ""
+ | Json_bool _ -> raise (Json_conv_failure "bool->string")
+ | Json_int _ -> raise (Json_conv_failure "int->string")
+ | Json_float _ -> raise (Json_conv_failure "float->string")
+ | Json_string s -> s
+ | Json_object _ -> raise (Json_conv_failure "object->string")
+ | Json_array a ->
+ if Array.length a = 0 then
+ raise (Json_conv_failure "array->string")
+ else
+ strict a.(0) in
+ if not permissive then strict j else lenient j
+
+let string_to_json s = Json_string s
+
+
+let int_of_json ?(permissive=false) j =
+ let strict = function
+ | Json_null _ -> raise (Json_conv_failure "null->int")
+ | Json_bool _ -> raise (Json_conv_failure "bool->int")
+ | Json_int i -> Int64.to_int i
+ | Json_float _ -> raise (Json_conv_failure "float->int")
+ | Json_string _ -> raise (Json_conv_failure "float->int")
+ | Json_object _ -> raise (Json_conv_failure "object->int")
+ | Json_array _ -> raise (Json_conv_failure "array->int") in
+ let lenient = function
+ | Json_null _ -> 0
+ | Json_bool b -> if b then 1 else 0
+ | Json_int i -> Int64.to_int i
+ | Json_float _ -> raise (Json_conv_failure "float->int")
+ | Json_string _ -> raise (Json_conv_failure "string->int")
+ | Json_object _ -> raise (Json_conv_failure "object->int")
+ | Json_array a ->
+ if Array.length a = 0 then
+ raise (Json_conv_failure "array->int")
+ else
+ strict a.(0) in
+ if not permissive then strict j else lenient j
+
+let int_to_json i = Json_int (Int64.of_int i)
+
+
+let int64_of_json ?(permissive=false) j =
+ let strict = function
+ | Json_null _ -> raise (Json_conv_failure "null->int64")
+ | Json_bool _ -> raise (Json_conv_failure "bool->int64")
+ | Json_int i -> i
+ | Json_float _ -> raise (Json_conv_failure "float->int64")
+ | Json_string _ -> raise (Json_conv_failure "float->int64")
+ | Json_object _ -> raise (Json_conv_failure "object->int64")
+ | Json_array _ -> raise (Json_conv_failure "array->int64") in
+ let lenient = function
+ | Json_null _ -> 0L
+ | Json_bool b -> if b then 1L else 0L
+ | Json_int i -> i
+ | Json_float _ -> raise (Json_conv_failure "float->int64")
+ | Json_string _ -> raise (Json_conv_failure "string->int64")
+ | Json_object _ -> raise (Json_conv_failure "object->int64")
+ | Json_array a ->
+ if Array.length a = 0 then
+ raise (Json_conv_failure "array->int64")
+ else
+ strict a.(0) in
+ if not permissive then strict j else lenient j
+
+let int64_to_json i = Json_int i
+
+let bool_of_json ?(permissive=false) j =
+ let strict = function
+ | Json_null _ -> raise (Json_conv_failure "null->bool")
+ | Json_bool b -> b
+ | Json_int i -> raise (Json_conv_failure "int->bool")
+ | Json_float _ -> raise (Json_conv_failure "float->bool")
+ | Json_string _ -> raise (Json_conv_failure "float->bool")
+ | Json_object _ -> raise (Json_conv_failure "object->bool")
+ | Json_array _ -> raise (Json_conv_failure "array->bool") in
+ let lenient = function
+ | Json_null _ -> false
+ | Json_bool b -> b
+ | Json_int i -> i <> 0L
+ | Json_float _ -> raise (Json_conv_failure "float->bool")
+ | Json_string _ -> raise (Json_conv_failure "string->bool")
+ | Json_object _ -> raise (Json_conv_failure "object->bool")
+ | Json_array a ->
+ if Array.length a = 0 then
+ raise (Json_conv_failure "array->bool")
+ else
+ strict a.(0) in
+ if not permissive then strict j else lenient j
+
+let bool_to_json b = Json_bool b
--- /dev/null
+(*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+exception Json_conv_failure of string
+
+val string_of_json: ?permissive:bool -> Json.t -> string
+val string_to_json: string -> Json.t
+
+val int_of_json: ?permissive:bool -> Json.t -> int
+val int_to_json: int -> Json.t
+
+val int64_of_json: ?permissive:bool -> Json.t -> int64
+val int64_to_json: int64 -> Json.t
+
+val bool_of_json: ?permissive:bool -> Json.t -> bool
+val bool_to_json: bool -> Json.t
+
+
+
--- /dev/null
+(*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+open Syntax
+open Format
+
+let base_to_str = function
+ | B_string -> "string" | B_int -> "int" | B_int64 -> "int64"
+ | B_bool -> "bool" | B_ident s -> s
+
+type var = { stem: string; mark: int }
+
+let name_of_var v =
+ match v.mark with
+ | 0 -> Printf.sprintf "%s" v.stem
+ | d -> Printf.sprintf "%s_%d" v.stem d
+
+module type VAR_ENV = sig
+ type t
+ val new_env: t
+ val new_ident_from_name: t -> ?prefix:string -> ?suffix:string -> string -> var * t
+ val new_ident_from_type: t -> complex_type -> var * t
+ val new_idents_from_types: t -> complex_type list -> var list * t
+ val new_idents_from_vars: t -> ?prefix:string -> ?suffix:string -> var list -> var list * t
+end
+
+module Var_env : VAR_ENV = struct
+ module StringMap = Map.Make (struct type t = string let compare = compare end)
+
+ type name_entry = { cur_mark: int; entries: var list; }
+
+ let new_name_entry = { cur_mark = 0; entries = [] }
+
+ let make_new_var name_entry name =
+ let var = { stem = name; mark = name_entry.cur_mark} in
+ var, { cur_mark = var.mark + 1; entries = var :: name_entry.entries }
+
+ type t = name_entry StringMap.t
+ let new_env = StringMap.empty
+
+ let new_var env full_name =
+ let var, new_entry = make_new_var (try StringMap.find full_name env
+ with Not_found -> new_name_entry) full_name in
+ var, (StringMap.add full_name new_entry env)
+
+ let new_ident_from_name env ?(prefix="") ?(suffix="") stem =
+ new_var env (prefix ^ stem ^ suffix)
+
+ let base_to_stem = function
+ | B_string -> "str" | B_int -> "int" | B_int64 -> "int64"
+ | B_bool -> "bool" | B_ident s -> s
+
+ let complex_type_to_stem = function
+ | C_base b -> base_to_stem b | C_option _ -> "opt" | C_list _ -> "lst"
+ | C_array _ -> "arr" | C_tuple _ -> "tup" | C_record _ -> "rec"
+ | C_variant _ -> "var"
+
+ let new_ident_from_type env ct =
+ new_ident_from_name env (complex_type_to_stem ct)
+
+ let new_idents_from_types env cts =
+ let vlist, env =
+ List.fold_left (fun (vlist, env) ct ->
+ let v, env' = new_ident_from_type env ct in
+ (v :: vlist), env'
+ ) ([], env) cts in
+ (List.rev vlist), env
+
+ let new_ident_from_var env ?(prefix="") ?(suffix="") var =
+ new_ident_from_name env ~prefix ~suffix var.stem
+
+ let new_idents_from_vars env ?(prefix="") ?(suffix="") vlist =
+ let vlist, env =
+ List.fold_left (fun (vlist, env) v ->
+ let v, env' = new_ident_from_var env ~prefix ~suffix v in
+ (v :: vlist), env'
+ ) ([], env) vlist in
+ (List.rev vlist), env
+end
+
+module To = struct
+ let prod_vars_to_str vlist =
+ let elems = List.map name_of_var vlist in
+ String.concat ", " elems
+ let to_array_str ?(constr="") vlist =
+ let elems = List.map name_of_var vlist in
+ let constr = if constr = "" then "" else "(string_to_json \"" ^ constr ^ "\"); " in
+ "[| " ^ constr ^ (String.concat "; " elems) ^ " |]"
+ let to_object_str fn_list fv_list =
+ let elems = List.map2 (fun f v ->
+ Printf.sprintf "(\"%s\", %s)" f (name_of_var v)
+ ) fn_list fv_list in
+ "[| " ^ (String.concat "; " elems) ^ " |]"
+ let to_record_str fnlist fvlist =
+ let fields = List.map2 (fun fn fv ->
+ Printf.sprintf "%s = %s" fn (name_of_var fv)
+ ) fnlist fvlist in
+ "{ " ^ (String.concat "; " fields) ^ " }"
+ let rec to_json ff venv inv typ =
+ let v = name_of_var inv in
+ match typ with
+ | C_base bt ->
+ fprintf ff "%s_to_json %s" (base_to_str bt) v
+ | C_option optt ->
+ let optv, venv' = Var_env.new_ident_from_type venv optt in
+ fprintf ff "(match %s with@," v;
+ fprintf ff "| None -> Json_null@,";
+ fprintf ff "@[<v 8>| Some %s ->@," (name_of_var optv);
+ to_json ff venv' optv optt;
+ fprintf ff "@]@,)"
+ | C_list elemt ->
+ let elemv, venv' = Var_env.new_ident_from_type venv elemt in
+ let jlistv, venv' = Var_env.new_ident_from_name venv' v ~suffix:"_jlist" in
+ let jlistvn = name_of_var jlistv in
+ fprintf ff "@[<v 8>let %s = List.map@," jlistvn;
+ fprintf ff "@[<v 8>(fun %s ->@," (name_of_var elemv);
+ to_json ff venv' elemv elemt;
+ fprintf ff "@]@,) %s in@]@," v;
+ fprintf ff "Json_array (Array.of_list %s)" jlistvn
+ | C_array elemt ->
+ let elemv, venv' = Var_env.new_ident_from_type venv elemt in
+ let jarrayv, venv' = Var_env.new_ident_from_name venv' v ~suffix:"_jarray" in
+ let jarrayvn = name_of_var jarrayv in
+ fprintf ff "@[<v 8>let %s = Array.map@," jarrayvn;
+ fprintf ff "@[<v 8>(fun %s ->@," (name_of_var elemv);
+ to_json ff venv' elemv elemt;
+ fprintf ff "@]@,) %s in@]@," v;
+ fprintf ff "Json_array %s" jarrayvn
+ | C_tuple ctlist ->
+ let cvlist, venv' = Var_env.new_idents_from_types venv ctlist in
+ let letvlist, venv' = Var_env.new_idents_from_vars venv' ~prefix:"j_" cvlist in
+ let cvtlist = List.combine cvlist ctlist in
+ fprintf ff "(match %s with@," v;
+ fprintf ff "@[<v 8>| %s ->@," (prod_vars_to_str cvlist);
+ List.iter2 (fun letv (cv, ct) ->
+ let_bind ff venv' letv cv ct
+ ) letvlist cvtlist;
+ fprintf ff "Json_array %s@]@,)" (to_array_str letvlist)
+ | C_record cls ->
+ let fnlist, ftlist = List.split cls in
+ let fvlist, venv' = Var_env.new_idents_from_types venv ftlist in
+ let letvlist, venv' = Var_env.new_idents_from_vars venv' ~prefix:"j_" fvlist in
+ fprintf ff "(match %s with@," v;
+ fprintf ff "@[<v 8>| %s ->@," (to_record_str fnlist fvlist);
+ List.iter2 (fun letv (fv, ft) ->
+ let_bind ff venv' letv fv ft
+ ) letvlist (List.combine fvlist ftlist);
+ fprintf ff "Json_object %s@]@,)" (to_object_str fnlist letvlist)
+ | C_variant cdlist ->
+ fprintf ff "(match %s with@," v;
+ List.iter (fun cd -> variant ff venv cd) cdlist;
+ fprintf ff ")"
+ and variant ff venv (CD_tuple (vname, vtlist)) =
+ let vlist, venv' = Var_env.new_idents_from_types venv vtlist in
+ let letvlist, venv' = Var_env.new_idents_from_vars venv' ~prefix:"j_" vlist in
+ if List.length vlist = 0 then
+ fprintf ff "@[<v 8>| %s ->@," vname
+ else
+ fprintf ff "@[<v 8>| %s (%s) ->@," vname (prod_vars_to_str vlist);
+ List.iter2 (fun letv (v, vt) ->
+ let_bind ff venv' letv v vt
+ ) letvlist (List.combine vlist vtlist);
+ fprintf ff "Json_array %s@]@," (to_array_str ~constr:vname letvlist)
+ and let_bind ff venv letv inv typ =
+ fprintf ff "@[<v 8>let %s =@," (name_of_var letv);
+ to_json ff venv inv typ;
+ fprintf ff " in@]@,"
+ let def ff venv fn_name typ is_and =
+ let fnv, venv' = Var_env.new_ident_from_name venv fn_name in
+ let inv, venv' = Var_env.new_ident_from_name venv' "o" in
+ fprintf ff "@[<v 8>%s %s %s =@," (if is_and then "and" else "let rec") fn_name (name_of_var inv);
+ to_json ff venv' inv typ;
+ fprintf ff "@]@,@\n"
+end
+
+let generate_to_def ff is_and (tname, trep) =
+ let fn = tname ^ "_to_json" in
+ To.def ff Var_env.new_env fn trep is_and
+
+let generate_from_def ff is_and (tname, trep) =
+ let fn = tname ^ "_from_json" in
+ Printf.printf "Generating %s\n" fn
+ (* From.def ff Var_env.new_env Type_env.new_env fn trep *)
+
+let generate_header ff ifn =
+ let md = Filename.basename (Filename.chop_extension ifn) in
+ fprintf ff "open Json@\n";
+ fprintf ff "open Base_conv@\n";
+ fprintf ff "open %s@\n" (String.capitalize md);
+ fprintf ff "@\n"
+
+let generate_one_defn ff td =
+ match td with
+ | [] -> ()
+ | h :: t ->
+ generate_to_def ff false h;
+ List.iter (generate_to_def ff true) t;
+ generate_from_def ff false h;
+ List.iter (generate_from_def ff true) t
+
+let generate defn_list ofn ifn =
+ let ff = formatter_of_out_channel (open_out ofn) in
+ generate_header ff ifn;
+ List.iter (generate_one_defn ff) defn_list
let to_buffer t buf =
to_fct t (fun s -> Buffer.add_string buf s)
-let to_string t =
+let json_to_string t =
let buf = Buffer.create 2048 in
to_buffer t buf;
Buffer.contents buf
| Json_object of (string * t) array
| Json_array of t array
-val to_string: t -> string
+val json_to_string: t -> string
+++ /dev/null
-(*
- * Copyright (C) 2009 Citrix Ltd.
- * Author Prashanth Mundkur <firstname.lastname@citrix.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; version 2.1 only. with the special
- * exception on linking described in file LICENSE.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *)
-
-let options = [ ]
-
-let parse_args () =
- let file = ref None in
- let usage = Printf.sprintf "Usage: %s file" Sys.argv.(0) in
- Arg.parse (Arg.align options) (fun f -> file := Some f) usage;
- match !file with
- | Some f -> f
- | None -> Printf.eprintf "%s\n" usage; exit 1
-
-let read_whole_file ic =
- let buf = Buffer.create 512 in
- let rec do_read () =
- try
- let line = input_line ic in
- Buffer.add_string buf line;
- do_read ()
- with End_of_file ->
- Buffer.contents buf
- in do_read ()
-
-let parse_file f =
- let ic = open_in f in
- let input = ref (read_whole_file ic) in
- let state = ref (Json_parse.init_parse_state ()) in
- while String.length !input > 0 do
- match Json_parse.parse !state !input with
- | Json_parse.Json_value (v, rem) ->
- Printf.printf "%s\n" (Json.to_string v);
- input := rem;
- state := Json_parse.init_parse_state ()
- | Json_parse.Json_parse_incomplete st ->
- input := "";
- state := st
- done;
- match Json_parse.finish_parse !state with
- | Some v -> Printf.printf "%s\n" (Json.to_string v)
- | None -> ()
-
-let print_exception e =
- match e with
- | Json_parse.Unexpected_char (c, state) ->
- Printf.eprintf "Unexpected char %C (x%X) encountered in state %s\n"
- c (Char.code c) state
- | Json_parse.Invalid_value (v, t) ->
- Printf.eprintf "'%s' is an invalid %s\n" v t
- | Json_parse.Invalid_leading_zero s ->
- Printf.eprintf "'%s' should not have leading zeros\n" s
- | Json_parse.Unterminated_value s ->
- Printf.eprintf "unterminated %s\n" s
- | Json_parse.Internal_error m ->
- Printf.eprintf "Internal error: %s\n" m
- | Sys_error s ->
- Printf.eprintf "%s\n" s
- | e ->
- Printf.eprintf "%s\n" (Printexc.to_string e)
-
-let is_internal_error = function
- | Json_parse.Internal_error _ -> true
- | _ -> false
-
-let _ =
- let input_file = parse_args () in
- try
- parse_file input_file;
- exit 0
- with e ->
- print_exception e;
- if is_internal_error e then exit 255 else exit 1
-
--- /dev/null
+(*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+open Syntax
+open Parser
+open Lexing
+
+let show_syntax_error e l =
+ let loc = Printf.sprintf "%s at line %d, char %d"
+ l.pos_fname l.pos_lnum (l.pos_cnum - l.pos_bol) in
+ let msg =
+ match e with
+ | Illegal_character c -> Printf.sprintf "Illegal character %c" c
+ | Invalid_ident s -> Printf.sprintf "Invalid/unsupported identifier %s" s
+ | Unmatched_comment -> Printf.sprintf "Unmatched comment"
+ | Unterminated_comment -> Printf.sprintf "Unterminated comment"
+ in
+ Printf.printf "%s: %s\n" loc msg;
+ exit 1
+
+let show_parse_error lexbuf =
+ let lxm = lexeme lexbuf in
+ let loc = Printf.sprintf "%s at line %d, char %d"
+ lexbuf.lex_curr_p.pos_fname lexbuf.lex_curr_p.pos_lnum
+ (lexbuf.lex_curr_p.pos_cnum - lexbuf.lex_curr_p.pos_bol) in
+ (match lxm with
+ | "" -> Printf.printf "%s: parsing error\n" loc
+ | _ -> Printf.printf "%s: parsing error at \"%s\"\n" loc lxm);
+ exit 1
+
+let parse_file file =
+ let f = open_in file in
+ let lexbuf = Lexing.from_channel f in
+ try
+ Lexer.init lexbuf file;
+ Parser.defn_list Lexer.main lexbuf
+ with
+ | Syntax_error (e, l) ->
+ show_syntax_error e l
+ | Parsing.Parse_error ->
+ show_parse_error lexbuf
+
+let default_output_filename f =
+ let dir, base = Filename.dirname f, Filename.basename f in
+ let stem = Filename.chop_extension base in
+ Filename.concat dir (stem ^ "_json_conv.ml")
+
+let gen_code defn_list f =
+ Codegen.generate defn_list f
+
+let () =
+ let input = ref "" in
+ let output = ref "" in
+
+ (* parse argv *)
+ let larg = [
+ ("-i", Arg.Set_string input, "input file");
+ ("-o", Arg.Set_string output, "output file");
+ ] in
+ let usage_msg = Printf.sprintf "%s -i <file> [-o <file>]" Sys.argv.(0) in
+ Arg.parse larg (fun s -> ()) usage_msg;
+
+ if !output = "" then output := default_output_filename !input;
+
+ match !input with
+ | "" -> Printf.printf "%s\n" usage_msg
+ | file -> gen_code (parse_file file) !output !input
--- /dev/null
+(*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+{
+
+open Lexing
+open Syntax
+open Parser
+
+let comment_depth = ref 0
+let comment_start = ref dummy_pos
+
+let line_num = ref 0
+
+let init lexbuf fname =
+ lexbuf.lex_curr_p <- { pos_fname = fname;
+ pos_lnum = 1;
+ pos_bol = 0;
+ pos_cnum = 0 }
+
+let raise_syntax_error e loc =
+ raise (Syntax_error (e, loc))
+
+}
+
+let letter = ['A'-'Z' 'a'-'z']
+
+(* The handling of '.' is a bit of a hack for now; not sure if it's
+ really needed. *)
+let ident_first = letter | '_'
+let ident_others = letter | ['0'-'9'] | '_' | '\'' | '.'
+let ident = ident_first ident_others*
+
+rule main = parse
+| [' ' '\009' '\012' '\r']+
+ { main lexbuf }
+| ['\n']
+ { new_line lexbuf;
+ main lexbuf
+ }
+| "*/"
+ { raise_syntax_error Unmatched_comment (lexeme_start_p lexbuf) }
+| "/*"
+ { comment_depth := 1;
+ comment_start := lexeme_start_p lexbuf;
+ comment lexbuf;
+ main lexbuf
+ }
+
+| eof { EOF }
+| "=" { EQUAL }
+| "*" { STAR }
+| ";" { SEMI }
+| ";;" { SEMISEMI }
+| ":" { COLON }
+| "|" { BAR }
+
+| "{" { LBRACE }
+| "}" { RBRACE }
+| "(" { LPAREN }
+| ")" { RPAREN }
+| "[" { LBRACK }
+| "]" { RBRACK }
+
+| "type" { TYPE }
+| "and" { AND }
+| "mutable" { MUTABLE }
+| "of" { OF }
+
+(* hardcoded type constructors; this could be handled more
+ intelligently later. *)
+
+| "option" { OPTION }
+| "list" { LIST }
+| "array" { ARRAY }
+
+| "string" { STRING }
+| "int" { INT }
+| "int64" { INT64 }
+| "bool" { BOOL }
+
+(* general identifiers. we could handle the '.' here. *)
+| ident
+ { let str = lexeme lexbuf in
+ match String.get str 0 with
+ | 'A' .. 'Z' -> UIDENT str
+ | 'a' .. 'z' -> LIDENT str
+ | _ -> raise_syntax_error (Invalid_ident str) (lexeme_start_p lexbuf)
+ }
+| _
+ { raise_syntax_error (Illegal_character (lexeme_char lexbuf 0)) (lexeme_start_p lexbuf) }
+
+
+and comment = parse
+| "/*"
+ { incr comment_depth;
+ comment lexbuf
+ }
+| "*/"
+ { decr comment_depth;
+ if !comment_depth > 0 then comment lexbuf
+ }
+| ['\n']
+ { new_line lexbuf;
+ comment lexbuf
+ }
+| eof
+ { raise_syntax_error Unterminated_comment !comment_start }
+| _
+ { comment lexbuf }
--- /dev/null
+/*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+
+%{
+
+open Syntax
+
+let raise_syntax_error e pos =
+ raise (Syntax_error (e, pos))
+
+%}
+
+/* keywords */
+%token TYPE AND MUTABLE OF
+%token OPTION LIST ARRAY STRING INT INT64 BOOL
+
+%token LBRACE RBRACE LPAREN RPAREN LBRACK RBRACK
+%token EQUAL STAR SEMI SEMISEMI COLON BAR
+%token EOF
+
+%token <string> UIDENT LIDENT
+
+%start defn_list
+
+%type <Syntax.type_defn list> defn_list
+
+%%
+
+defn_list:
+| defns EOF
+ { List.rev $1 }
+;
+
+defns:
+| defns top_defn_term
+ { $2 :: $1 }
+| /* epsilon */
+ { [] }
+;
+
+top_defn_term:
+| defn semi
+ { $1 }
+
+defn:
+| TYPE eqn
+ { [ $2 ] }
+
+| TYPE eqn AND defn_parts
+ { $2 :: (List.rev $4) }
+
+defn_parts:
+| defn_parts AND eqn
+ { $3 :: $1 }
+| eqn
+ { [ $1 ] }
+
+eqn:
+| LIDENT EQUAL repn
+ { ($1, $3) }
+;
+
+semi:
+| SEMISEMI
+ {}
+| /* epsilon */
+ {}
+
+repn:
+| expr
+ { $1 }
+| expr STAR tuple
+ { C_tuple ($1 :: (List.rev $3)) }
+| record
+ { C_record (List.rev $1) }
+| variant
+ { C_variant (List.rev $1) }
+
+expr:
+| LPAREN expr RPAREN
+ { $2 }
+| LPAREN expr STAR tuple RPAREN
+ { C_tuple ($2 :: (List.rev $4)) }
+| expr OPTION
+ { C_option $1 }
+| expr LIST
+ { C_list $1 }
+| expr ARRAY
+ { C_array $1 }
+| base
+ { C_base $1 }
+
+tuple:
+| tuple STAR expr
+ { $3 :: $1 }
+| expr
+ { [ $1 ] }
+
+base:
+| STRING { B_string }
+| INT { B_int }
+| INT64 { B_int64 }
+| BOOL { B_bool }
+| LIDENT { B_ident $1 }
+/* TODO:
+| UIDENT { raise_syntax_error (Invalid_ident $1) }
+*/
+
+record:
+| LBRACE field_decls RBRACE
+ { $2 }
+
+field_decls:
+| field_decls SEMI field_decl
+ { $3 :: $1 }
+| field_decl
+ { [ $1 ] }
+
+field_decl:
+| LIDENT COLON expr
+ { ($1, $3) }
+| MUTABLE LIDENT COLON expr
+ { ($2, $4) }
+
+variant:
+| variant BAR constr
+ { $3 :: $1 }
+| constr
+ { [ $1 ] }
+| /* epsilon */
+ { [] }
+
+constr:
+| UIDENT
+ { CD_tuple ($1, []) }
+| UIDENT OF expr
+ { CD_tuple ($1, [ $3 ]) }
+
+| UIDENT OF expr STAR tuple
+ { CD_tuple ($1, ($3 :: (List.rev $5))) }
+
--- /dev/null
+/*
+Copyright (c) 2005 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
--- /dev/null
+The .json files in this directory are taken from the JSON_checker
+project [1], and are covered by the license in LICENSE.txt.
+
+[1] http://www.json.org/JSON_checker/
--- /dev/null
+"A JSON payload should be an object or array, not a string."
\ No newline at end of file
--- /dev/null
+{"Extra value after close": true} "misplaced quoted value"
\ No newline at end of file
--- /dev/null
+{"Illegal expression": 1 + 2}
\ No newline at end of file
--- /dev/null
+{"Illegal invocation": alert()}
\ No newline at end of file
--- /dev/null
+{"Numbers cannot have leading zeroes": 013}
\ No newline at end of file
--- /dev/null
+{"Numbers cannot be hex": 0x14}
\ No newline at end of file
--- /dev/null
+["Illegal backslash escape: \x15"]
\ No newline at end of file
--- /dev/null
+[\naked]
\ No newline at end of file
--- /dev/null
+["Illegal backslash escape: \017"]
\ No newline at end of file
--- /dev/null
+[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
\ No newline at end of file
--- /dev/null
+{"Missing colon" null}
\ No newline at end of file
--- /dev/null
+["Unclosed array"
\ No newline at end of file
--- /dev/null
+{"Double colon":: null}
\ No newline at end of file
--- /dev/null
+{"Comma instead of colon", null}
\ No newline at end of file
--- /dev/null
+["Colon instead of comma": false]
\ No newline at end of file
--- /dev/null
+["Bad value", truth]
\ No newline at end of file
--- /dev/null
+['single quote']
\ No newline at end of file
--- /dev/null
+[" tab character in string "]
\ No newline at end of file
--- /dev/null
+["tab\ character\ in\ string\ "]
\ No newline at end of file
--- /dev/null
+["line
+break"]
\ No newline at end of file
--- /dev/null
+["line\
+break"]
\ No newline at end of file
--- /dev/null
+[0e]
\ No newline at end of file
--- /dev/null
+{unquoted_key: "keys must be quoted"}
\ No newline at end of file
--- /dev/null
+[0e+]
\ No newline at end of file
--- /dev/null
+[0e+-1]
\ No newline at end of file
--- /dev/null
+{"Comma instead if closing brace": true,
\ No newline at end of file
--- /dev/null
+["mismatch"}
\ No newline at end of file
--- /dev/null
+["extra comma",]
\ No newline at end of file
--- /dev/null
+["double extra comma",,]
\ No newline at end of file
--- /dev/null
+[ , "<-- missing value"]
\ No newline at end of file
--- /dev/null
+["Comma after the close"],
\ No newline at end of file
--- /dev/null
+["Extra close"]]
\ No newline at end of file
--- /dev/null
+{"Extra comma": true,}
\ No newline at end of file
--- /dev/null
+[
+ "JSON Test Pattern pass1",
+ {"object with 1 member":["array with 1 element"]},
+ {},
+ [],
+ -42,
+ true,
+ false,
+ null,
+ {
+ "integer": 1234567890,
+ "real": -9876.543210,
+ "e": 0.123456789e-12,
+ "E": 1.234567890E+34,
+ "": 23456789012E66,
+ "zero": 0,
+ "one": 1,
+ "space": " ",
+ "quote": "\"",
+ "backslash": "\\",
+ "controls": "\b\f\n\r\t",
+ "slash": "/ & \/",
+ "alpha": "abcdefghijklmnopqrstuvwyz",
+ "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
+ "digit": "0123456789",
+ "0123456789": "digit",
+ "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
+ "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
+ "true": true,
+ "false": false,
+ "null": null,
+ "array":[ ],
+ "object":{ },
+ "address": "50 St. James Street",
+ "url": "http://www.JSON.org/",
+ "comment": "// /* <!-- --",
+ "# -- --> */": " ",
+ " s p a c e d " :[1,2 , 3
+
+,
+
+4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
+ "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
+ "quotes": "" \u0022 %22 0x22 034 "",
+ "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+: "A key can be any string"
+ },
+ 0.5 ,98.6
+,
+99.44
+,
+
+1066,
+1e1,
+0.1e1,
+1e-1,
+1e00,2e+00,2e-00
+,"rosebud"]
\ No newline at end of file
--- /dev/null
+[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
\ No newline at end of file
--- /dev/null
+{
+ "JSON Test Pattern pass3": {
+ "The outermost value": "must be an object or array.",
+ "In this test": "It is an object."
+ }
+}
--- /dev/null
+#!/bin/bash
+
+PROG=../test_parser
+
+for f in `ls *pass*.json`; do
+ $PROG $f > /dev/null 2>&1
+ ec=$?
+ if [ $ec -eq 1 ] ; then
+ echo "Test case $f should pass, but failed."
+ elif [ $ec -eq 255 ] ; then
+ echo "Test case $f triggered an internal error!"
+ fi
+done
+for f in `ls *fail*.json`; do
+ $PROG $f > /dev/null 2>&1
+ ec=$?
+ if [ $ec -eq 0 ] ; then
+ echo "Test case $f should fail, but passed."
+ elif [ $ec -eq 255 ] ; then
+ echo "Test case $f triggered an internal error!"
+ fi
+done
--- /dev/null
+(*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+type syntax_error =
+ | Illegal_character of char
+ | Invalid_ident of string
+ | Unmatched_comment
+ | Unterminated_comment
+
+exception Syntax_error of syntax_error * Lexing.position
+
+type base_type =
+ | B_string
+ | B_int
+ | B_int64
+ | B_bool
+ | B_ident of string
+
+type complex_type =
+ | C_base of base_type
+ | C_option of complex_type
+ | C_list of complex_type
+ | C_array of complex_type
+ | C_tuple of complex_type list
+ | C_record of (string * complex_type) list
+ | C_variant of constr_decl list
+
+and constr_decl =
+ | CD_tuple of string * complex_type list
+
+type type_defn = (string * complex_type) list
+
--- /dev/null
+(*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Prashanth Mundkur <firstname.lastname@citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *)
+
+let options = [ ]
+
+let parse_args () =
+ let file = ref None in
+ let usage = Printf.sprintf "Usage: %s file" Sys.argv.(0) in
+ Arg.parse (Arg.align options) (fun f -> file := Some f) usage;
+ match !file with
+ | Some f -> f
+ | None -> Printf.eprintf "%s\n" usage; exit 1
+
+let read_whole_file ic =
+ let buf = Buffer.create 512 in
+ let rec do_read () =
+ try
+ let line = input_line ic in
+ Buffer.add_string buf line;
+ do_read ()
+ with End_of_file ->
+ Buffer.contents buf
+ in do_read ()
+
+let parse_file f =
+ let ic = open_in f in
+ let input = ref (read_whole_file ic) in
+ let state = ref (Json_parse.init_parse_state ()) in
+ while String.length !input > 0 do
+ match Json_parse.parse !state !input with
+ | Json_parse.Json_value (v, rem) ->
+ Printf.printf "%s\n" (Json.json_to_string v);
+ input := rem;
+ state := Json_parse.init_parse_state ()
+ | Json_parse.Json_parse_incomplete st ->
+ input := "";
+ state := st
+ done;
+ match Json_parse.finish_parse !state with
+ | Some v -> Printf.printf "%s\n" (Json.json_to_string v)
+ | None -> ()
+
+let print_exception e =
+ match e with
+ | Json_parse.Unexpected_char (c, state) ->
+ Printf.eprintf "Unexpected char %C (x%X) encountered in state %s\n"
+ c (Char.code c) state
+ | Json_parse.Invalid_value (v, t) ->
+ Printf.eprintf "'%s' is an invalid %s\n" v t
+ | Json_parse.Invalid_leading_zero s ->
+ Printf.eprintf "'%s' should not have leading zeros\n" s
+ | Json_parse.Unterminated_value s ->
+ Printf.eprintf "unterminated %s\n" s
+ | Json_parse.Internal_error m ->
+ Printf.eprintf "Internal error: %s\n" m
+ | Sys_error s ->
+ Printf.eprintf "%s\n" s
+ | e ->
+ Printf.eprintf "%s\n" (Printexc.to_string e)
+
+let is_internal_error = function
+ | Json_parse.Internal_error _ -> true
+ | _ -> false
+
+let _ =
+ let input_file = parse_args () in
+ try
+ parse_file input_file;
+ exit 0
+ with e ->
+ print_exception e;
+ if is_internal_error e then exit 255 else exit 1
+
+++ /dev/null
-/*
-Copyright (c) 2005 JSON.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-The Software shall be used for Good, not Evil.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
+++ /dev/null
-The .json files in this directory are taken from the JSON_checker
-project [1], and are covered by the license in LICENSE.txt.
-
-[1] http://www.json.org/JSON_checker/
+++ /dev/null
-"A JSON payload should be an object or array, not a string."
\ No newline at end of file
+++ /dev/null
-{"Extra value after close": true} "misplaced quoted value"
\ No newline at end of file
+++ /dev/null
-{"Illegal expression": 1 + 2}
\ No newline at end of file
+++ /dev/null
-{"Illegal invocation": alert()}
\ No newline at end of file
+++ /dev/null
-{"Numbers cannot have leading zeroes": 013}
\ No newline at end of file
+++ /dev/null
-{"Numbers cannot be hex": 0x14}
\ No newline at end of file
+++ /dev/null
-["Illegal backslash escape: \x15"]
\ No newline at end of file
+++ /dev/null
-[\naked]
\ No newline at end of file
+++ /dev/null
-["Illegal backslash escape: \017"]
\ No newline at end of file
+++ /dev/null
-[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
\ No newline at end of file
+++ /dev/null
-{"Missing colon" null}
\ No newline at end of file
+++ /dev/null
-["Unclosed array"
\ No newline at end of file
+++ /dev/null
-{"Double colon":: null}
\ No newline at end of file
+++ /dev/null
-{"Comma instead of colon", null}
\ No newline at end of file
+++ /dev/null
-["Colon instead of comma": false]
\ No newline at end of file
+++ /dev/null
-["Bad value", truth]
\ No newline at end of file
+++ /dev/null
-['single quote']
\ No newline at end of file
+++ /dev/null
-[" tab character in string "]
\ No newline at end of file
+++ /dev/null
-["tab\ character\ in\ string\ "]
\ No newline at end of file
+++ /dev/null
-["line
-break"]
\ No newline at end of file
+++ /dev/null
-["line\
-break"]
\ No newline at end of file
+++ /dev/null
-[0e]
\ No newline at end of file
+++ /dev/null
-{unquoted_key: "keys must be quoted"}
\ No newline at end of file
+++ /dev/null
-[0e+]
\ No newline at end of file
+++ /dev/null
-[0e+-1]
\ No newline at end of file
+++ /dev/null
-{"Comma instead if closing brace": true,
\ No newline at end of file
+++ /dev/null
-["mismatch"}
\ No newline at end of file
+++ /dev/null
-["extra comma",]
\ No newline at end of file
+++ /dev/null
-["double extra comma",,]
\ No newline at end of file
+++ /dev/null
-[ , "<-- missing value"]
\ No newline at end of file
+++ /dev/null
-["Comma after the close"],
\ No newline at end of file
+++ /dev/null
-["Extra close"]]
\ No newline at end of file
+++ /dev/null
-{"Extra comma": true,}
\ No newline at end of file
+++ /dev/null
-[
- "JSON Test Pattern pass1",
- {"object with 1 member":["array with 1 element"]},
- {},
- [],
- -42,
- true,
- false,
- null,
- {
- "integer": 1234567890,
- "real": -9876.543210,
- "e": 0.123456789e-12,
- "E": 1.234567890E+34,
- "": 23456789012E66,
- "zero": 0,
- "one": 1,
- "space": " ",
- "quote": "\"",
- "backslash": "\\",
- "controls": "\b\f\n\r\t",
- "slash": "/ & \/",
- "alpha": "abcdefghijklmnopqrstuvwyz",
- "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
- "digit": "0123456789",
- "0123456789": "digit",
- "special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
- "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
- "true": true,
- "false": false,
- "null": null,
- "array":[ ],
- "object":{ },
- "address": "50 St. James Street",
- "url": "http://www.JSON.org/",
- "comment": "// /* <!-- --",
- "# -- --> */": " ",
- " s p a c e d " :[1,2 , 3
-
-,
-
-4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
- "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
- "quotes": "" \u0022 %22 0x22 034 "",
- "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
-: "A key can be any string"
- },
- 0.5 ,98.6
-,
-99.44
-,
-
-1066,
-1e1,
-0.1e1,
-1e-1,
-1e00,2e+00,2e-00
-,"rosebud"]
\ No newline at end of file
+++ /dev/null
-[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
\ No newline at end of file
+++ /dev/null
-{
- "JSON Test Pattern pass3": {
- "The outermost value": "must be an object or array.",
- "In this test": "It is an object."
- }
-}
+++ /dev/null
-#!/bin/bash
-
-PROG=../json_test
-
-for f in `ls *pass*.json`; do
- $PROG $f > /dev/null 2>&1
- ec=$?
- if [ $ec -eq 1 ] ; then
- echo "Test case $f should pass, but failed."
- elif [ $ec -eq 255 ] ; then
- echo "Test case $f triggered an internal error!"
- fi
-done
-for f in `ls *fail*.json`; do
- $PROG $f > /dev/null 2>&1
- ec=$?
- if [ $ec -eq 0 ] ; then
- echo "Test case $f should fail, but passed."
- elif [ $ec -eq 255 ] ; then
- echo "Test case $f triggered an internal error!"
- fi
-done