(**********************************************************************************)
(* Libcaml-grew - a Graph Rewriting library dedicated to NLP applications *)
(* *)
(* Copyright 2011-2013 Inria, Université de Lorraine *)
(* *)
(* Webpage: http://grew.loria.fr *)
(* License: CeCILL (see LICENSE folder or "http://www.cecill.info") *)
(* Authors: see AUTHORS file *)
(**********************************************************************************)
open Printf
open Log
open Grew_base
open Grew_types
open Grew_ast
open Grew_domain
open Grew_graph
open Grew_rule
open Grew_grs
let html_header ?css_file ?title ?(add_lines=[]) buff =
let wnl fmt = Printf.ksprintf (fun x -> Printf.bprintf buff "%s\n" x) fmt in
wnl "";
wnl "";
wnl "
";
wnl " ";
(match css_file with
| Some file -> wnl " " file
| None -> ()
);
(match title with
| Some t -> wnl " %s " (Str.global_replace (Str.regexp "#") " " t)
| None -> ()
);
List.iter (fun line -> wnl " %s" line) add_lines;
wnl " ";
(* ================================================================================*)
module Html_doc = struct
let string_of_concat_item = function
| Ast.Qfn_item id -> sprintf "%s" (Ast.dump_feature_ident id)
| Ast.String_item s -> sprintf "\"%s\"" s
| Ast.Param_item var -> sprintf "%s" var
let buff_html_command ?(li_html=false) buff (u_command,_) =
bprintf buff " ";
if li_html then bprintf buff "";
bprintf buff "%s" (Ast.string_of_u_command u_command);
if li_html then bprintf buff " \n" else bprintf buff ";\n"
let html_feature (u_feature,_) =
match u_feature.Ast.kind with
| Ast.Equality values ->
sprintf "%s=%s" u_feature.Ast.name (List_.to_string (fun x->x) "|" values)
| Ast.Disequality [] ->
sprintf "%s=*" u_feature.Ast.name
| Ast.Absent ->
sprintf "!%s" u_feature.Ast.name
| Ast.Disequality values ->
sprintf "%s<>%s" u_feature.Ast.name (List_.to_string (fun x->x) "|" values)
| Ast.Equal_param index ->
sprintf "%s=%s" u_feature.Ast.name index
let buff_html_node buff (u_node,_) =
bprintf buff " %s [" u_node.Ast.node_id;
bprintf buff "%s" (String.concat ", " (List.map html_feature u_node.Ast.fs));
bprintf buff "];\n"
let buff_html_edge buff (u_edge,_) =
bprintf buff " ";
bprintf buff "%s" (match u_edge.Ast.edge_id with Some n -> n^": " | None -> "");
match u_edge.Ast.edge_label_cst with
| Ast.Pos_list l -> bprintf buff "%s -[%s]-> %s;\n" u_edge.Ast.src (List_.to_string (fun x->x) "|" l) u_edge.Ast.tar
| Ast.Neg_list l -> bprintf buff "%s -[^%s]-> %s;\n" u_edge.Ast.src (List_.to_string (fun x->x) "|" l) u_edge.Ast.tar
| Ast.Regexp re -> bprintf buff "%s -[re\"%s\"]-> %s;\n" u_edge.Ast.src re u_edge.Ast.tar
let buff_html_const buff (u_const,_) =
bprintf buff " ";
(match u_const with
| Ast.Cst_out (ident, Ast.Neg_list []) ->
bprintf buff "%s -> *" ident
| Ast.Cst_out (ident, Ast.Pos_list labels) ->
bprintf buff "%s -[%s]-> *" ident (List_.to_string (fun x->x) "|" labels)
| Ast.Cst_out (ident, Ast.Neg_list labels) ->
bprintf buff "%s -[^%s]-> *" ident (List_.to_string (fun x->x) "|" labels)
| Ast.Cst_out (ident, Ast.Regexp re) ->
bprintf buff "%s -[re\"%s\"]-> *" ident re
| Ast.Cst_in (ident, Ast.Neg_list []) ->
bprintf buff "* -> %s" ident
| Ast.Cst_in (ident, Ast.Pos_list labels) ->
bprintf buff "* -[%s]-> %s" (List_.to_string (fun x->x) "|" labels) ident
| Ast.Cst_in (ident, Ast.Neg_list labels) ->
bprintf buff "* -[^%s]-> %s" (List_.to_string (fun x->x) "|" labels) ident
| Ast.Cst_in (ident, Ast.Regexp re) ->
bprintf buff "* -[re\"%s\"]-> %s" re ident
| Ast.Features_eq (feat_id_l, feat_id_r) ->
bprintf buff "%s = %s" (Ast.dump_feature_ident feat_id_l) (Ast.dump_feature_ident feat_id_r);
| Ast.Features_diseq (feat_id_l, feat_id_r) ->
bprintf buff "%s <> %s" (Ast.dump_feature_ident feat_id_l) (Ast.dump_feature_ident feat_id_r);
| Ast.Features_ineq (ineq, feat_id_l, feat_id_r) ->
bprintf buff "%s %s %s" (Ast.dump_feature_ident feat_id_l) (Ast.string_of_ineq ineq) (Ast.dump_feature_ident feat_id_r)
| Ast.Feature_ineq_cst (ineq, feat_id_l, constant) ->
bprintf buff "%s %s %f" (Ast.dump_feature_ident feat_id_l) (Ast.string_of_ineq ineq) constant
| Ast.Feature_eq_cst (feat_id_l, value) ->
bprintf buff "%s = \"%s\"" (Ast.dump_feature_ident feat_id_l) value;
| Ast.Feature_diff_cst (feat_id_l, value) ->
bprintf buff "%s ≠ \"%s\"" (Ast.dump_feature_ident feat_id_l) value;
| Ast.Feature_eq_float (feat_id_l, value) ->
bprintf buff "%s = %g" (Ast.dump_feature_ident feat_id_l) value;
| Ast.Feature_diff_float (feat_id_l, value) ->
bprintf buff "%s ≠ %g" (Ast.dump_feature_ident feat_id_l) value;
| Ast.Feature_eq_regexp (feat_id, regexp) ->
bprintf buff "%s == \"%s\"" (Ast.dump_feature_ident feat_id) regexp
| Ast.Immediate_prec (id1, id2) ->
bprintf buff "%s < %s" id1 id2
| Ast.Large_prec (id1, id2) ->
bprintf buff "%s << %s" id1 id2
);
bprintf buff "\n"
let buff_html_pos_basic buff pos_basic =
bprintf buff " match { \n";
List.iter (buff_html_node buff) pos_basic.Ast.pat_nodes;
List.iter (buff_html_edge buff) pos_basic.Ast.pat_edges;
List.iter (buff_html_const buff) pos_basic.Ast.pat_const;
bprintf buff " } \n"
let buff_html_neg_basic buff neg_basic =
bprintf buff " without { \n";
List.iter (buff_html_node buff) neg_basic.Ast.pat_nodes;
List.iter (buff_html_edge buff) neg_basic.Ast.pat_edges;
List.iter (buff_html_const buff) neg_basic.Ast.pat_const;
bprintf buff " } \n"
let to_html_rules rules =
let buff = Buffer.create 32 in
List.iter
(fun rule ->
(* the first line: (lex_)rule / filter *)
(match (rule.Ast.commands, rule.Ast.param) with
| (_,None) ->
bprintf buff "rule %s { \n" rule.Ast.rule_id
| (_,Some (files, vars)) ->
let param =
match files with
| [] -> sprintf "(feature %s)" (String.concat ", " vars)
| l -> sprintf "(feature %s; %s)"
(String.concat ", " vars)
(String.concat ", " (List.map (fun f -> sprintf "file \"%s\"" f) l)) in
bprintf buff "lex_rule %s %s { \n" rule.Ast.rule_id param
);
(* the match part *)
buff_html_pos_basic buff rule.Ast.pattern.Ast.pat_pos;
(* the without parts *)
List.iter (buff_html_neg_basic buff) rule.Ast.pattern.Ast.pat_negs;
(* the commands part *)
bprintf buff " commands { \n";
List.iter (buff_html_command buff) rule.Ast.commands;
bprintf buff " } \n";
bprintf buff "} \n";
) rules;
Buffer.contents buff
let doc_to_html string =
if Str.string_match (Str.regexp "^ \\* ") string 0
then sprintf "%s " (String.sub string 4 ((String.length string)-4))
else
List.fold_left
(fun acc (re,str) -> Str.global_replace (Str.regexp re) str acc)
string
[
"\\[", "";
"\\]", " ";
"~", " ";
]
let of_opt_color = function
| [] -> "black"
| c::_ -> String.sub c 1 ((String.length c) - 1)
let module_page_text ~corpus prev next module_ =
let buff = Buffer.create 32 in
let wnl fmt = Printf.ksprintf (fun x -> Printf.bprintf buff "%s\n" x) fmt in
let w fmt = Printf.ksprintf (fun x -> Printf.bprintf buff "%s" x) fmt in
let title = sprintf "Grew -- Module %s" module_.Ast.module_id in
html_header ~css_file:"style.css" ~title buff;
wnl " ";
if corpus
then wnl "Sentences -- Rewriting stats -- GRS documentation";
wnl " ";
w " ";
(match prev with Some p -> w "
Previous " p | _ -> ());
w "
Up ";
(match next with Some n -> w "
Next " n | _ -> ());
wnl "
";
wnl " Module %s
" module_.Ast.module_id;
List.iter (fun s -> wnl " %s " (doc_to_html s)) module_.Ast.module_doc;
wnl " %d Rules " (List.length module_.Ast.rules);
wnl " ";
List.iter
(fun rule ->
wnl " ";
wnl " %s " module_.Ast.module_id rule.Ast.rule_id rule.Ast.rule_id;
(match rule.Ast.rule_doc with [] -> () | l::_ -> wnl " %s " (doc_to_html l));
wnl " ";
) module_.Ast.rules;
wnl "
";
wnl " ";
wnl "";
Buffer.contents buff
let rule_page_text ~corpus ~dep prev next rule_ module_ =
let rid = rule_.Ast.rule_id in
let mid = module_.Ast.module_id in
let buff = Buffer.create 32 in
let wnl fmt = Printf.ksprintf (fun x -> Printf.bprintf buff "%s\n" x) fmt in
let w fmt = Printf.ksprintf (fun x -> Printf.bprintf buff "%s" x) fmt in
let title = sprintf "Grew -- Rule %s/%s" mid rid in
html_header ~css_file:"style.css" ~title buff;
wnl " ";
if corpus
then wnl "Sentences -- Rewriting stats -- GRS documentation";
wnl " ";
w " ";
(match prev with Some p -> w "
Previous " mid p | _ -> ());
w "
Up " mid;
(match next with Some n -> w "
Next " mid n | _ -> ());
wnl "
";
wnl "Rule %s . %s
" mid mid rid;
List.iter (fun s -> wnl " %s " (doc_to_html s)) rule_.Ast.rule_doc;
wnl "Code ";
wnl "";
w "%s" (to_html_rules [rule_]);
wnl " ";
if dep
then
begin
wnl "Pattern ";
wnl "";
w " " (sprintf "%s_%s-patt.png" mid rid);
wnl " "
end;
let output_table args lines =
wnl " ";
wnl " %s " (List_.to_string (fun x -> sprintf "%s " x) "" args);
List.iter
(fun l -> wnl "%s "
(List_.to_string (fun x -> sprintf "%s " x) "" (Str.split (Str.regexp "#+") l))
) lines;
wnl "
" in
(match rule_.Ast.param with
| None -> ()
| Some (files, args) ->
wnl "Lexical parameters ";
(* output local lexical parameters (if any) *)
(match rule_.Ast.lex_par with
| None -> ()
| Some lines ->
wnl "Local parameters ";
output_table args lines
);
(* output external lexical parameters (if any) *)
List.iter
(fun file ->
let filename = Filename.concat module_.Ast.mod_dir file in
wnl "File: %s " file;
let lines =
try File.read filename
with Sys_error msg -> wnl "Error: %s " msg; [] in
output_table args lines
) files
);
wnl " ";
wnl "