Commits

Kota UENISHI  committed 62967df

add sql parser

  • Participants
  • Parent commits db1d1f6

Comments (0)

Files changed (8)

File sql/OMakefile

 .PHONY: all install clean
 
+clean:
+	rm -rf $(filter-proper-targets $(ls R, .))
+	rm -rf *.omc
+
 USE_OCAMLFIND = true
-#
+
 # OCAMLPACKS[] =
 #    pack1
 #    pack2
-#
+
 if $(not $(OCAMLFIND_EXISTS))
    eprintln(This project requires ocamlfind\, but is was not found.)
    eprintln(You need to install ocamlfind and run "omake --configure".)
 # OCAML_NATIVE_LINK_FLAGS +=
 
 OCamlGeneratedFiles(sql_parser.ml sql_lexer.ml)
+# OCamlGeneratedFiles(json_parser.ml json_lexer.ml)
 
 ################################################
 # Build an OCaml library
 #
 # .DEFAULT: $(OCamlLibrary $(LIB), $(FILES))
 
-################################################
-# Build an OCaml program
-#
-
 FILES[] =
    main
    sql
    sql_parser
    sql_lexer
+   json
+   json_parser
+   json_lexer
 
 PROGRAM = sql
 # OCAML_LIBS +=
+
+type json_value = String of string
+                  | Number of num
+                  | Object of (string * json_value) list
+                  | Array  of json_value list
+                  | Bool of bool
+                  | Null
+and num = Int of int
+          | Float of float
+(* and so on? *)
+
+
+let rec pp_json = function
+  | String(s)-> Printf.sprintf "\"%s\"" s;
+  | Number(Int(i)) -> Printf.sprintf "%d" i;
+  | Number(Float(v)) -> Printf.sprintf "%f" v;
+  | Object(o) -> "{ " ^ (pp_object o) ^ " }";
+  | Array(a)  ->
+    "[" ^ (String.concat ", " (List.map pp_json a)) ^ "]";
+  | Bool(true) -> "true"
+  | Bool(false)-> "false";
+  | Null -> "null";
+and pp_object l =
+  String.concat ", " (List.map 
+    (fun (k,v) -> Printf.sprintf "%s : %s" k (pp_json v)) l)
+;;

File sql/json_lexer.mll

+
+{
+
+open Json_parser
+let debugprint = ref true;;
+let print str =  if !debugprint then print_endline str;;
+
+let quote_buf = String.create 8192;;
+let quote_ptr = ref 0;;
+let in_quote = ref false;;
+
+}
+
+let digit = ['0'-'9']*
+let literal = ['a'-'z']['A'-'Z' 'a'-'z' '_' '0'-'9']*
+
+rule token = parse
+  | '{' { LBRACE }
+  | '}' { RBRACE }
+  | '[' { LBRACE2 }
+  | ']' { RBRACE2 }
+  | ':' { COLON }
+  | ','     { COMMA }
+  | "true"  { TRUE  }
+  | "false" { FALSE }
+  | "null"  { NULL  }
+  | "\""      {
+    in_quote := true;
+    quote_ptr := 0;
+    quote lexbuf;
+    in_quote := false;
+    QUOTE (String.sub quote_buf 0 (!quote_ptr))
+  }
+  | "\n"         { print "f"; token lexbuf }
+  | digit as i { INT(int_of_string i) }
+(*  | eof	         { print "eof."; EOF } *)
+  | _            { token lexbuf }
+and quote = parse
+  | "\""  { () }
+  | _ as c {
+    (* TODO: support Unicod!! *)
+    String.set quote_buf (!quote_ptr) c;
+    quote_ptr := (!quote_ptr) + 1;
+    quote lexbuf
+  }
+
+{}

File sql/json_parser.mly

+
+%{
+
+  open Printf
+  let _ = Parsing.set_trace false;;
+  let debugprint = ref true;;
+  
+  let print str = if !debugprint then print_endline str;;
+  
+  let parse_error s = print ("parse_error->"^s);;
+
+%}
+
+%token TRUE FALSE NULL
+%token LBRACE RBRACE COLON COMMA
+%token LBRACE2 RBRACE2
+%token <int> INT
+
+%token <string> QUOTE
+
+%start input
+%type <Json.json_value> input
+
+%%
+
+input: | exp { $1 };
+
+exp:
+  | value { $1 }
+
+value:
+  | QUOTE { Json.String($1) }
+  | INT   { Json.Number(Json.Int($1)) }
+  | LBRACE pairs RBRACE    { Json.Object($2) }
+  | LBRACE2 values RBRACE2 { Json.Array($2)  }
+  | TRUE  { Json.Bool(true) }
+  | FALSE { Json.Bool(false)}
+  | NULL  { Json.Null }
+;
+
+pairs:
+  | QUOTE COLON value { [($1, $3)] }
+  | QUOTE COLON value COMMA pairs
+      { ($1, $3)::$5 }
+
+values:
+  | value { [$1] }
+  | value COMMA values { $1::$3 }
-
-let parse q =
+let parse_sql q =
   let lexbuf = Lexing.from_string q in
   try
     Sql_parser.input Sql_lexer.token lexbuf
       print_endline (Printexc.to_string exn);
       raise exn;;
 
+let parse_json q =
+  let lexbuf = Lexing.from_string q in
+  try
+    Json_parser.input Json_lexer.token lexbuf
+  with
+    | exn ->
+      print_endline (Printexc.to_string exn);
+      raise exn;;
+
 let sample_query = "select * from mytable where colA == 'foo'";;
+let sample_json  = "{ \"hello\":\"world!\", \"v\": 345, \"a\": [23,3,4, 0] }";;
 
 let _ =
   print_endline sample_query;
 (*  Sql.pp_query (Sql.Select(Sql.Columns(["hoge"; "hage"]), "tttttttttttttt")); *)
-  let q = parse sample_query in
+  let q = parse_sql sample_query in
   Sql.pp_query q;
+  print_endline sample_json;
+  let j = parse_json sample_json in
+  print_endline (Json.pp_json j);
   print_endline " => hello";;
+
                  | Regexp  of string * string
   
 type query = Select of columns * string * condition list
-             (* columns, table *)
+             (* columns, table, wheres *)
 
 let pp_cols = function
   | All_col -> "*";
 
 let pp_query = function
   | Select(columns, table, where) ->
-    Printf.printf "select: %s from %s where %s\n" (pp_cols columns) table (pp_where where);
+    Printf.printf "select: %s from %s where %s\n" (pp_cols columns) table (pp_where where);;

File sql/sql_lexer.mll

 {
 
 open Sql_parser
-let debugprint = ref true;;
+let debugprint = ref false;;
 let print str =  if !debugprint then print_endline str;;
 
 let quote_buf = String.create 8192;;
   | "*"      { ASTERISK }
   | "=="     { EQUAL }
   | "'"      {
-    print "quote =======>";
     in_quote := true;
     quote_ptr := 0;
     quote lexbuf;
     in_quote := false;
-    print " <============= quote";
-    QUOTE (String.sub quote_buf 0 (!quote_ptr))
+     QUOTE (String.sub quote_buf 0 (!quote_ptr))
   }
   | literal as s { LITERAL(s) }
   | "\n"         { print "f"; token lexbuf }

File sql/test.json

+{ "hello":"world" }