let __prefixes__ = [|"let"; "rec"; "and"; "for"; "mutable"|] ;; let __keywords__ = [|"let"; "while"; "do"; "done"; "for"; "to"; "begin"; "end"; "try"; "with"; "raise"; "in"|] ;; let fbd = [|' '; '\n'; '('; ')'; '['; ']'; '{'; '}'; ';'; ','; '.'; ':'; '*'; '|'; '-'; '+'; '*'; '/'; '='; '<'; '>'; '!'|] ;; let concat_str (str : string ref) nstr = let n = String.length nstr in let i = ref 0 in while !i < n && nstr.[!i] = ' ' do incr i done; if !i <> n then begin let cct = String.init (n - !i) (fun k -> nstr.[k + !i]) in str := (!str)^cct^"\n" end;; let parse_the_whole_thing filename = let ptr = open_in filename in let res = ref "" in try while true do let line = input_line ptr in concat_str res line (*res := (!res)^line^"\n"*) done; "0 factorielle" with | End_of_file -> close_in ptr; !res ;; let is_an_integer ch = Char.code ch >= 48 && Char.code ch <= 57 ;; let to_list str = let n = String.length str in let rec aux acc i = match i with | k when k >= n -> acc | k -> let k1 = ref k and k2 = ref k in while !k2 < String.length str && (Array.mem str.[!k2] fbd || is_an_integer str.[!k2]) do incr k2; incr k1 done; while !k2 < String.length str && not (Array.mem str.[!k2] fbd) do incr k2 done; aux (((0, String.init (!k2 - !k1) (fun i -> str.[!k1 + i])), (!k1, !k2))::acc) (!k2+1) in List.rev (aux [] 0) ;; let print_to_list (res : ((int * string) * (int * int)) list) = let rec aux = function | [] -> () | ((b, str), (i, j))::t -> Printf.printf "[%d] %s --> (%d <-> %d)\n" b str i j ; aux t in aux res ;; let random_string nmin nmax = String.init (Random.int (nmax - nmin) + nmin) (fun i -> Char.chr (97 + Random.int 25)) ;; let detect_names (res : ((int * string) * (int * int)) list) = let rec aux isname = function | [] -> [] | ((status, str), (i, j))::t when isname -> if Array.mem str __prefixes__ then ((status, str), (i, j))::(aux true t) else ((1, str), (i, j))::(aux false t) | ((status, str), (i, j))::t -> ((status, str), (i, j))::(aux (Array.mem str __prefixes__) t) in aux false res ;; let str_equal s1 s2 = if (String.length s1) <> (String.length s2) then false else Array.fold_left (fun acc v -> acc && fst v = snd v) true (Array.init (String.length s1) (fun i -> (s1.[i], s2.[i]))) ;; let generate_conversion_hash (res : ((int * string) * (int * int)) list) = let hash = Hashtbl.create (List.length res +2) in let rec aux = function | [] -> () |((isname, str), (i, j))::t -> if Hashtbl.find_opt hash str = None then begin if isname = 1 then Hashtbl.add hash str (random_string 10 11) else Hashtbl.add hash str str ; end; (*if Hashtbl.find_opt hash str = None then begin if not (Array.mem str __prefixes__) then Hashtbl.add hash str (random_string 10 11) else Hashtbl.add hash str str ; end;*) aux t in aux res ; hash ;; let list_to_array (l : 'a list) = let hd = List.hd l in let n = List.length l in let res = Array.make n hd in let rec aux i = function | [] -> () | h::t -> res.(i) <- h ; aux (i+1) t in aux 0 l; res ;; let write_out (filename : string) str (ext : string) (words : ((int * string) * (int * int)) list) (hash : (string, string) Hashtbl.t) = let ptr = open_out ("tests/"^filename^"_improved."^ext) in let n = String.length str in let i = ref 0 in let cwords = list_to_array words in let cindex = ref 0 in try while true do while !i < fst (snd cwords.(!cindex)) do (* write normally *) Printf.fprintf ptr "%c" str.[!i] ; incr i; done; Printf.fprintf ptr "%s" (Hashtbl.find hash (snd (fst cwords.(!cindex)))) ; i := (snd (snd cwords.(!cindex))) ; incr cindex ; done; close_out ptr ; with | Invalid_argument _ -> while !i < n do Printf.fprintf ptr "%c" str.[!i] ; incr i; done; close_out ptr ;; let convert filename ext = let whole = parse_the_whole_thing (filename^"."^ext) in (*Printf.printf "%s" whole ;*) let words = to_list whole in print_to_list words ; let fnames = detect_names words in (*print_to_list fnames ;*) let conversion_hash = generate_conversion_hash fnames in (*Hashtbl.iter (fun k v -> Printf.printf "%s ----> %s\n" k v) conversion_hash ;*) write_out filename whole ext fnames conversion_hash ;; let main () = if Array.length Sys.argv <> 3 then begin Printf.fprintf stderr "Usage : ./a.out \nNote : filename should not include the <.extension> (e.g. enter 'main' and not 'main.c' or 'main.ml')\n" ; assert false ; end else convert Sys.argv.(1) Sys.argv.(2) ;; main () ;;