scrambler/main.ml

164 lines
4.8 KiB
OCaml

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 <filename> <extension>\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 () ;;