1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
(**Module initializing eventual glossaries*)
let glossaries = Hashtbl.create 1;;
(** Alias for Sys.file_exists *)
let glossary_exists glossary = Sys.file_exists glossary;;
(** Returns true if the length of the glossary is greater than 0 and false otherwise *)
let glossary_provided () = not ((Hashtbl.length glossaries) = 0);;
(** returns false if a string is empty or a newline *)
let not_is_empty = function
| "\n" -> false
| "" -> false
| s when String.trim s = "" -> false
| _ -> true;;
let parse_glossary_entry entry =
let name_regexp = Str.regexp "name="
and desc_regexp = Str.regexp "description="
and accolade_fermante_regexp = Str.regexp "}"
and accolade_ouvrante_regexp = Str.regexp "{" in
let rec read_desc acc = function
| [] -> acc,[]
| t::q when t='{' -> read_desc acc q
| t::q when t='}' -> acc,q
| t::q -> read_desc (acc^(String.make 1 t)) q
and read_name acc = function
| [] -> acc,[]
| t::q when t='{' -> read_name acc q
| t::q when t='}' -> acc,q
| t::q when t=',' -> acc,q
| t::q -> read_name (acc^(String.make 1 t)) q
and read_def acc = function
| [] -> acc,[]
| t::q when t='{' -> read_def acc q
| t::_ when t='}' -> acc,[]
| t::q -> read_def (acc^(String.make 1 t)) q
and s = fun (s) -> String.sub s 1 (String.length s -1)
in let not_comma_then_s = fun t -> t |> s |> String.trim
in let a,q = read_desc "" (Utils.string_to_list entry)
in let b,q2 = read_name "" q
in let c,_ = read_def "" q2
in let a = [a;b;c]
in let a = List.map (fun c -> Str.global_replace accolade_ouvrante_regexp "" (Str.global_replace accolade_fermante_regexp "" c)) a
in match a with
| a::b::c::[] -> let a,b,c = (a,Str.global_replace name_regexp "" b, Str.global_replace desc_regexp "" c) in
Hashtbl.add glossaries a ((not_comma_then_s b), (not_comma_then_s c))
| _ -> ();;
(** Takes a glossary file and parse it in a list of string *)
let parse_glossaries file =
let glossary_regexp = Str.regexp "\\\\newglossaryentry" in
let newline_regexp = Str.regexp "\n" in
if not (glossary_exists file) then []
else
let string = Utils.read_file file in
let string = String.concat "\n" string in
let list_of_entries = Str.split glossary_regexp string |> List.filter (not_is_empty)
|> List.map (Str.global_replace newline_regexp "") in
list_of_entries;;
let init_glossary glossary =
Hashtbl.clear glossaries;
parse_glossaries glossary |> List.iter (parse_glossary_entry);;
(** Combines parse_glosaries and parse_glossary_entry *)
let total_glossaries file =
parse_glossaries file
|> List.map parse_glossary_entry
|> ignore;;
(** Transform the glossary to an HTML file *)
let prints_glossary () =
if not @@ glossary_provided () then "" else
let line = "<div id=\"glossary\"><br>\n>" in
let line = line^"<h2>Glossary</h2>" in
let rec aux result (entries) =
match entries with
| [] -> result
| (desc,(name,def))::q -> let l = "\t<div id=\"" ^ desc ^ "\">\n\t\t<h3>" ^ name ^ "</h3>\n\t\t<p>" ^ def ^ "</p>\n\t</div>\n"
in aux (result^l) q
in let line = aux line (List.of_seq (Hashtbl.to_seq glossaries))
in line^"</div>\n";;
(**Takes a glossary descriptor and returns its name and definition*)
let recognize_gls name =
try
Hashtbl.find glossaries name;
with _ -> name,name;;