LCGlatexOf.ml 12.8 KB
(*
 *  ENIAM: Categorial Syntactic-Semantic Parser for Polish
 *  Copyright (C) 2016 Wojciech Jaworski <wjaworski atSPAMfree mimuw dot edu dot pl>
 *  Copyright (C) 2016 Institute of Computer Science Polish Academy of Sciences
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *)
 
open LCGtypes
open Xstd
open Printf
 
let type_term s = "\\text{" ^ s ^ "}"

let rec first_digit_index v n i =
  if i = n then n else
  if String.get v i >= '0' && String.get v i <= '9' then i 
  else first_digit_index v n (i+1)

let variable v =
  let n = String.length v in
  let i = first_digit_index v n 0 in
  if n = i then v else
  String.sub v 0 i ^ "_{" ^ String.sub v i (n-i) ^ "}"

let pred_name = function
    "name_token" -> "name\\_token"
  | s -> s
  
let rec linear_term c = function
    Var v -> variable v
  | Tuple l ->
      let l = Xlist.map l (linear_term 2) in
      let n = Xlist.fold l 0 (fun n s -> String.length s + n) in
      let s =
        if n < 100 then String.concat "\\otimes " l else
        let s = String.concat "\\otimes\\\\ {}" l in 
        "\\begin{array}{l}" ^ s ^ "\\end{array}" in
      if c > 1 then "(" ^ s ^ ")" else s
(*   | LetIn(l,s,t) -> "{\\bf let } " ^ String.concat "\\otimes " (Xlist.map l variable) ^ " = " ^ (linear_term 0 s) ^ " \\text{ {\\bf in }} " ^ (linear_term 0 t) *)
  | Variant(e,l) -> "\\langle " ^ String.concat ","(*"$,\\\\$"*) (Xlist.map l (fun (i,t) -> e^i^": "^linear_term 0 t)) ^ "\\rangle"
  | VariantVar(v,t) -> "\\langle " ^ linear_term 0 t ^ "\\rangle_\\text{" ^ v ^ "}"
(*   | Proj(n,t) -> "\\pi_" ^ (string_of_int n) ^ (linear_term c t) *)
  | ProjVar(v,t) -> "\\pi_{" ^ variable v ^ "}" ^ (linear_term c t)
  | SubstVar v -> variable v
  | Subst(s,v,t) -> "{\\bf subst}(" ^ (linear_term 0 s) ^ "," ^ variable v ^ "," ^ (linear_term 0 t) ^ ")"
  | Inj(n,t) -> "{\\bf inj}_{" ^ (string_of_int n) ^ "}" ^ (linear_term c t)
  | Case(t,l) -> "{\\bf case}\\; " ^ (linear_term 0 t) ^ " \\;{\\bf of}\\; " ^ 
      (String.concat " | " (Xlist.map l (fun (v,t) -> variable v ^ " \\to " ^ (linear_term 0 t))))
  | Lambda(v,t) -> "\\lambda " ^ variable v ^ "." ^ (linear_term c t)
  | LambdaSet(l,t) -> "\\lambda " ^ (String.concat "," (Xlist.map l variable)) ^ "." ^ (linear_term c t)
  | LambdaRot(n,t) -> "{\\bf rot}_" ^ (string_of_int n) ^ (linear_term c t)
  | App(s,t) -> "\\big((" ^ (linear_term 0 s) ^ ")(" ^ (linear_term 0 t) ^ ")\\big)"
  | Dot -> "\\bullet"
  | Val s -> "\\text{" ^ LatexMain.escape_string s ^ "}"
  | SetAttr(e,s,t) -> "{\\bf setattr}(\\text{{\\sc " ^ LatexMain.escape_string e ^ "}}," ^ linear_term 0 s ^ "," ^ linear_term 0 t ^ ")"
  | Fix(s,t) -> "{\\bf fix}(" ^ linear_term 0 s ^ "," ^ linear_term 0 t ^ ")"
  | Empty t -> "{\\bf empty}(" ^ linear_term 0 t ^ ")"
  | Apply t -> "{\\bf apply}(" ^ linear_term 0 t ^ ")"
  | Insert(s,t) -> "{\\bf insert}(" ^ linear_term 0 s ^ "," ^ linear_term 0 t ^ ")"
  | Node t -> 
         "{\\left[\\begin{array}{ll}" ^ 
          (String.concat "\\\\ " (Xlist.map (["PRED",Val t.pred;"CAT",Val t.cat;"ID",Val (string_of_int t.id);"WEIGHT",Val (string_of_float t.weight);"GS",t.gs;"ARGS",t.args] @ t.attrs) (fun (e,t) -> 
            "\\text{" ^ (LatexMain.escape_string e) ^ "} & " ^ (linear_term 0 t)))) ^ "\\end{array}\\right]}"
  | Morf m -> "\\text{" ^ LatexMain.escape_string (WalStringOf.morf m) ^ "}"
  | Gf s -> "\\text{" ^ LatexMain.escape_string (WalStringOf.gf s) ^ "}"
  | Ref i -> "{\\bf ref}\\; " ^ string_of_int i
  | Cut t -> "{\\bf cut}(" ^ linear_term 0 t ^ ")"
  | Choice choices -> "{\\bf choice}(" ^ String.concat ";" (StringMap.fold choices [] (fun l ei t -> (sprintf "%s: %s" ei (linear_term 0 t)) :: l)) ^ ")"
  | Concept c -> 
         "{\\left[\\begin{array}{ll}" ^ 
          (String.concat "\\\\ " (Xlist.map ([
            "SENSE",c.c_sense;"NAME",c.c_name;
            "VARIABLE",Val (fst c.c_variable ^ "_" ^ snd c.c_variable);"POS",Val (string_of_int c.c_pos);
            "QUANT",c.c_quant;"LOCAL-QUANT",if c.c_local_quant then Val "+" else Val "-";"RELATIONS",c.c_relations]) (fun (e,t) -> 
            "\\text{" ^ (LatexMain.escape_string e) ^ "} & " ^ (linear_term 0 t)))) ^ "\\end{array}\\right]}"
  | Context c -> 
         "{\\left[\\begin{array}{ll}" ^ 
          (String.concat "\\\\ " (Xlist.map ([
            "SENSE",c.cx_sense;
            "VARIABLE",Val (fst c.cx_variable ^ "_" ^ snd c.cx_variable);"POS",Val (string_of_int c.cx_pos);
            "RELATIONS",c.cx_relations;"CONTENTS",c.cx_contents]) (fun (e,t) -> 
            "\\text{" ^ (LatexMain.escape_string e) ^ "} & " ^ (linear_term 0 t)))) ^ "\\end{array}\\right]}"
  | Relation(r,a,c) -> "{\\bf relation}(" ^ linear_term 0 r ^ "," ^ linear_term 0 a ^ "," ^ linear_term 0 c ^ ")"
  | RevRelation(r,a,c) -> "{\\bf revrelation}(" ^ linear_term 0 r ^ "," ^ linear_term 0 a ^ "," ^ linear_term 0 c ^ ")"
  | SingleRelation r -> "{\\bf singlerelation}(" ^ linear_term 0 r ^ ")"
  | AddRelation(t,r,a,s) -> "{\\bf addrelation}(" ^ linear_term 0 t ^ "," ^ r ^ "," ^ a ^ "," ^ linear_term 0 s ^ ")"
  | RemoveRelation r -> "{\\bf removerelation}(" ^ linear_term 0 r ^ ")"
  | SetContextName(s,t) -> "{\\bf setcontextname}(" ^ s ^ "," ^ linear_term 0 t ^ ")"

let rec linear_term_simple c = function
    Var v -> variable v
  | Tuple l -> 
      let s = String.concat "\\otimes " (Xlist.map l (linear_term_simple 2)) in 
      if c > 1 then "(" ^ s ^ ")" else s
(*   | LetIn(l,s,t) -> "\\;$\\\\\n${\\bf let } " ^ String.concat "\\otimes " (Xlist.map l variable) ^ " = " ^ (linear_term_simple 0 s) ^ " \\text{ {\\bf in }} " ^ (linear_term_simple 0 t) *)
(*   | Triple(t1,t2,t3) -> "\\{" ^ linear_term_simple 0 t1 ^ "," ^ linear_term_simple 0 t2 ^ "," ^ linear_term_simple 0 t3 ^ "\\}" *)
  | Variant(e,l) -> "\\langle " ^ String.concat "," (Xlist.map l (fun (i,t) -> e^i^": "^linear_term_simple 0 t)) ^ "\\rangle"
  | VariantVar(v,t) -> "\\langle " ^ linear_term_simple 0 t ^ "\\rangle_\\text{" ^ v ^ "}"
(*   | Proj(n,t) -> "\\pi_" ^ (string_of_int n) ^ (linear_term_simple c t) *)
  | ProjVar(v,t) -> "\\pi_{" ^ variable v ^ "}" ^ (linear_term_simple c t)
  | SubstVar v -> variable v
  | Subst(s,v,t) -> "{\\bf subst}(" ^ (linear_term_simple 0 s) ^ "," ^ variable v ^ "," ^ (linear_term_simple 0 t) ^ ")"
  | Inj(n,t) -> "{\\bf inj}_" ^ (string_of_int n) ^ (linear_term_simple c t)
  | Case(t,l) -> "{\\bf case}\\; " ^ (linear_term_simple 0 t) ^ " \\;{\\bf of}\\; " ^ 
      (String.concat " | " (Xlist.map l (fun (v,t) -> variable v ^ " \\to " ^ (linear_term_simple 0 t))))
  | Lambda(v,t) -> "\\lambda " ^ variable v ^ "." ^ (linear_term_simple c t)
  | LambdaSet(l,t) -> "\\lambda " ^ (String.concat "," (Xlist.map l variable)) ^ "." ^ (linear_term_simple c t)
  | LambdaRot(n,t) -> "{\\bf rot}_" ^ (string_of_int n) ^ (linear_term_simple c t)
  | App(s,t) -> "\\big((" ^ (linear_term_simple 0 s) ^ ")(" ^ (linear_term_simple 0 t) ^ ")\\big)"
  | Dot -> "\\bullet"
  | Val s -> "\\text{" ^ LatexMain.escape_string s ^ "}"
  | SetAttr(e,s,t) -> "{\\bf setattr}(\\text{{\\sc " ^ LatexMain.escape_string e ^ "}}," ^ linear_term_simple 0 s ^ "," ^ linear_term_simple 0 t ^ ")"
  | Fix(s,t) -> "{\\bf fix}(" ^ linear_term_simple 0 s ^ "," ^ linear_term_simple 0 t ^ ")"
  | Empty t -> "{\\bf empty}(" ^ linear_term_simple 0 t ^ ")"
  | Apply t -> "{\\bf apply}(" ^ linear_term_simple 0 t ^ ")"
  | Insert(s,t) -> "{\\bf insert}(" ^ linear_term_simple 0 s ^ "," ^ linear_term_simple 0 t ^ ")"
  | Node _ -> "node"
  | Morf m -> "\\text{" ^ LatexMain.escape_string (WalStringOf.morf m) ^ "}"
  | Gf s -> "\\text{" ^ LatexMain.escape_string (WalStringOf.gf s) ^ "}"
  | Ref i -> "{\\bf ref}\\; " ^ string_of_int i
  | Cut t -> "{\\bf cut}(" ^ linear_term_simple 0 t ^ ")"
  | Choice choices -> "{\\bf choice}(" ^ String.concat ";" (StringMap.fold choices [] (fun l ei t -> (sprintf "%s: %s" ei (linear_term_simple 0 t)) :: l)) ^ ")"
  | Concept c -> 
         "{\\left[\\begin{array}{ll}" ^ 
          (String.concat "\\\\ " (Xlist.map ([
            "SENSE",c.c_sense;"NAME",c.c_name;
            "VARIABLE",Val (fst c.c_variable ^ "_" ^ snd c.c_variable);"POS",Val (string_of_int c.c_pos);
            "QUANT",c.c_quant;"LOCAL-QUANT",if c.c_local_quant then Val "+" else Val "-";"RELATIONS",c.c_relations]) (fun (e,t) -> 
            "\\text{" ^ (LatexMain.escape_string e) ^ "} & " ^ (linear_term_simple 0 t)))) ^ "\\end{array}\\right]}"
  | Context c -> 
         "{\\left[\\begin{array}{ll}" ^ 
          (String.concat "\\\\ " (Xlist.map ([
            "SENSE",c.cx_sense;
            "VARIABLE",Val (fst c.cx_variable ^ "_" ^ snd c.cx_variable);"POS",Val (string_of_int c.cx_pos);
            "RELATIONS",c.cx_relations;"CONTENTS",c.cx_contents]) (fun (e,t) -> 
            "\\text{" ^ (LatexMain.escape_string e) ^ "} & " ^ (linear_term_simple 0 t)))) ^ "\\end{array}\\right]}"
  | Relation(r,a,c) -> "{\\bf relation}(" ^ linear_term_simple 0 r ^ "," ^ linear_term_simple 0 a ^ "," ^ linear_term_simple 0 c ^ ")"
  | RevRelation(r,a,c) -> "{\\bf revrelation}(" ^ linear_term_simple 0 r ^ "," ^ linear_term_simple 0 a ^ "," ^ linear_term_simple 0 c ^ ")"
  | SingleRelation r -> "{\\bf singlerelation}(" ^ linear_term_simple 0 r ^ ")"
  | AddRelation(t,r,a,s) -> "{\\bf addrelation}(" ^ linear_term_simple 0 t ^ "," ^ r ^ "," ^ a ^ "," ^ linear_term_simple 0 s ^ ")"
  | RemoveRelation r -> "{\\bf removerelation}(" ^ linear_term_simple 0 r ^ ")"
  | SetContextName(s,t) -> "{\\bf setcontextname}(" ^ s ^ "," ^ linear_term_simple 0 t ^ ")"

let direction = function
    Forward -> "/"
  | Backward  -> "\\backslash"
  | Both -> "|"

let atom = function
    "m1" -> "\\text{m}_1"
  | "m2" -> "\\text{m}_2"
  | "m3" -> "\\text{m}_3"
  | "n1" -> "\\text{n}_1"
  | "n2" -> "\\text{n}_2"
  | "f" -> "\\text{f}"
  | "p1" -> "\\text{p}_1"
  | "p2" -> "\\text{p}_2"
  | "p3" -> "\\text{p}_3"
  | s -> "\\text{" ^ LatexMain.escape_string s ^ "}"
  
let rec internal_grammar_symbol c = function
    Atom x -> atom x
  | AVar x -> " " ^ x
  | With l -> 
      let s = String.concat "\\with" (Xlist.map l (internal_grammar_symbol 2)) in 
      if c > 1 then "(" ^ s ^ ")" else s
  | Zero -> "0"
  | Top -> "\\top"

let rec grammar_symbol c = function
    Tensor l -> 
      let s = String.concat "\\otimes" (Xlist.map l (internal_grammar_symbol 2)) in 
      if c > 1 then "(" ^ s ^ ")" else s
  | Plus l -> 
      let s = String.concat "\\oplus" (Xlist.map l (grammar_symbol 2)) in 
      if c > 1 then "(" ^ s ^ ")" else s
  | Imp(s,d,t) -> "(" ^ (grammar_symbol 2 s) ^ "\\\\ \\hspace{1cm}" ^ direction d ^ (grammar_symbol 2 t) ^ ")"
  | One -> "1"
  | ImpSet(s,l) -> 
      let s = (grammar_symbol 1 s) ^ "\\{" ^ String.concat "\n," (Xlist.map l (fun (d,a) -> "\\\\ \\hspace{1cm}" ^ direction d ^ grammar_symbol 1 a)) ^ "\\}" in 
      if c > 0 then "(" ^ s ^ ")" else s
  | WithVar(v,s,e,t) -> "\\bigwith_{" ^ e ^ ":" ^ v ^ ":=" ^ (internal_grammar_symbol 2 s) ^ "} " ^ (grammar_symbol 2 t)
  | Star s -> grammar_symbol 2 s ^ "^\\star"
  | Bracket(lf,rf,s) -> "\\langle " ^ (if lf then "\\langle " else "") ^ (grammar_symbol 0 s) ^ "\\rangle" ^ (if rf then "\\rangle " else "") 
  | BracketSet d -> "{\\bf BracketSet}(" ^ direction d ^ ")"
  | Maybe s -> "?" ^ grammar_symbol 2 s

let graph g = 
  let layers = LCGchart.fold g IntMap.empty (fun layers (symbol,node1,node2,sem,layer) ->
    let nodes = try IntMap.find layers layer with Not_found -> IntMap.empty in
    let content = node2, grammar_symbol 0 symbol, linear_term 0 sem in
(*     let nodes = IntMap.add_inc nodes node1 (node2,[content]) (fun (n,l) -> if n <> node2 then failwith "to_latex" else n, content :: l) in *)
    let nodes = IntMap.add_inc nodes node1 [content] (fun l -> content :: l) in
    IntMap.add layers layer nodes) in
  "\\begin{longtable}{|l|l|l|p{20cm}|}\n\\hline\n" ^
  String.concat "" (List.rev (IntMap.fold layers [] (fun l layer nodes ->
    IntMap.fold nodes l (fun l node1 contents -> 
      Xlist.fold contents l (fun l (node2,symbol,sem) -> 
        (Printf.sprintf "%d & %d--%d & $\\begin{array}{l}%s\\end{array}$ & $%s$\\\\\n\\hline\n" layer node1 node2 symbol sem) :: l))))) ^
  "\\end{longtable}"
  
let print_references name references =
  LatexMain.latex_file_out "results/" name "a0" false (fun file ->
    Int.iter 0 (Array.length references - 1) (fun i ->
      if references.(i) <> Dot then Printf.fprintf file "{\\bf %d} $%s$\\\\\n" i (linear_term 0 references.(i))));
  LatexMain.latex_compile_and_clean "results/" name